Skip to Content
Technical Articles

Communication channel password recovery – “Secure Storage”

Hi experts,

More than one year ago I published how to recover your communication channel passwords in a very simple way, but this approach is not working anymore in the latest versions due to a patch, since that moment I had curiosity regarding how the CCs passwords are stored in the system.

I found that the application responsible to retrieve and store the CCs passwords is using the “Secure Storage“, in another words the most “secure” way to protect them( Is that really true?…. ).

So the first questions that pop-up in my head was  “is there any way to find all this secured data in the system?”, and guess what…., the configtool is the answer 🙂 . You can navigate through the entire properties of all the applications running in the system( “context” ), but why is this so important?, if you understood how to use the secure storage in the system you should know that the “context” is where the “secured” data is stored, and it’s the only thing required to retrieve this data.

Let’s say that you want to navigate to the communication channel secured data through the configtool ( context = “cluster_config/system/custom_global/cfg/apps/sap.com/com.sap.xi.directory/appcfg/Channel/<channel id>/<channel version>” ):

As you can imagine the password values are those entries flagged as “secure content”.

The second question in my head was so obvious “is there any way to get those values from JAVA code?”, and the answer is the following UDF:

import javax.naming.*;
import com.sap.engine.frame.core.configuration.*;
import com.sap.engine.frame.core.configuration.addons.*;
import com.sap.engine.services.configuration.appconfiguration.*;

public void showMeThePasswords(String[] i_ids, String[] i_versions, ResultList o_ids, ResultList o_versions, ResultList o_properties, ResultList o_values, Container container) throws StreamTransformationException
{
	try 
	{   
		javax.naming.Context ctx = new InitialContext();      
		ApplicationConfigHandlerFactory appCfgHdlFctry = (ApplicationConfigHandlerFactory)ctx.lookup("ApplicationConfiguration");
		if (appCfgHdlFctry != null){ 
			ConfigurationHandlerFactory fullFactory = appCfgHdlFctry.getConfigurationHandlerFactory();
			ConfigurationHandler fullHandler = fullFactory.getConfigurationHandler();
			int context_len = i_ids.length;
			String strPath;
			for (int index = 0; index < context_len; index++) {
				strPath = "cluster_config/system/custom_global/cfg/apps/sap.com/com.sap.xi.directory/appcfg/Channel/" + i_ids[index] + "/" + i_versions[index];
				try 
				{			
					Configuration conf = fullHandler.openConfiguration(strPath, 0,true);
					boolean bTryAgain = true;
					Map entries = null;
					while (bTryAgain) {
					  bTryAgain = false;
					  try {
						entries = conf.getAllConfigEntries();
					  } catch (InconsistentReadException ire) {
						bTryAgain = true;
					  } 
					} 
					if (entries != null)
					{
						Object key = null;
						Object value = null;
						for (Iterator iter = entries.keySet().iterator(); iter.hasNext(); ) {
						  key = iter.next();
						  value = entries.get(key);
						  if (key != null && value != null && !"".equals(value.toString())) {
							o_ids.addValue(i_ids[index]);
							o_versions.addValue(i_versions[index]);
							o_properties.addValue(key.toString());
							o_values.addValue(value.toString());
						  }  
						} 
					}else{
						o_ids.addValue(i_ids[index]);
						o_versions.addValue(i_versions[index]);
						o_properties.addValue("");
						o_values.addValue("");					
					}
				}catch (Exception e){  				
					o_ids.addValue(i_ids[index]);
					o_versions.addValue(i_versions[index]);
					o_properties.addValue("");
					o_values.addValue("");
				}
			}
		}
	}catch (Exception e){     
		o_ids.addValue(e.getMessage());
		o_versions.addValue(e.getMessage());
		o_properties.addValue(e.getMessage());
		o_values.addValue(e.getMessage());
	}
}

Well, as you can see in a few lines of code is possible to read all the “secured” data related with the communication channels( passwords ! ) in the system, so I have the following open questions:

  1. How secure is the system for you?.
  2. Should the passwords be better protected?.
  3. Should the configuration of the apps be better protected?.

Knowing that there are 10 years more for SAP PO support I hope to see more security patches to solve these issues( I found at least 3 different ways to get the CCs passwords ).

 

Not forget, be curious! 😉

Best Regards.

Max.

/
6 Comments
You must be Logged on to comment or reply to a post.
  • Impressed. And it is just from a UDF.

    I guess it will be pretty difficult to make something that protects against this. You will need to do a good code review.

  • Hi Max, this is indeed an interesting read, but I think there’s a huge difference between this way to read the passwords and the way you showed us in your last blog. Last time the passwords were exposed via API which isn’t really necessary and I would say that it was a kind of security breach. But this time I’m not sure if I would name it a security risk, because if the passwords were not accessible via code, how should a communication adapter open a connection to a remote system? There has to be access to the passwords otherwise the channels couldn’t work. So even if one would block access via UDF at the end we could use the adapter SDK aka ADK to write a custom adapter because at the end the ADK has to have access to the passwords everytime.

    Long story short, I wouldn’t say that accessing password from code/executed in the runtime is a security risk.

    • /
      • Hi Max,

        I think you didn’t got my point. Or I didn’t get yours. So let’s say there a HTTP receiver channel. To be able to call the target service via BasicAuth the channel has to send the password in plain/base64. So the password stored in the PI has to be “recoverable” otherwise the channel couldn’t work. I think you agree in this point, or don’t you? But then the password has to be accessible via code and yes, maybe the password is too easy reachable via code, but even if it would be in some way capsulated, at the end one could get it via reflection.

        So I think the only really bulletproof solution would be removing all functions in the code base that could recover passwords in clear text. But in that case also the channels couldn’t get the passwords and thus the complete concept of a PI would be broken/useless.

        Or did I oversee something?

        Best regards,

        Raffael

        • I would agree with you Raffael, there is a need for this API for the system to work.

          A security model could be put in place that allowed only the module to give information that it should have access to. I’m not sure it would be possible with the security in Java.

          And with reflection, it is possible to get access to all objects in the JNDI.

           

  • Hi Maximiliano,

    Thank you for posting this useful information. It’s a nightmare when there are lots and old interfaces developed from people that is not available any more.

    We are on the PI 7.4 sp15. (still moving to 7.5) and I have errors in the 7.4 version with the packages:  com.sap.engine.frame.core.configuration.*;
    com.sap.engine.frame.core.configuration.addons.*;
    com.sap.engine.services.configuration.appconfiguration.*;

    Do you know where can I get those packages?

    Thank you in advance

    Jose Villanueva