SAP Java Secure Storage
As we have already discussed ABAP Secure Storage in our blog, now it’s time to talk about Java Secure Storage. In general, the realization of Secure Storage in the Java stack resembles the ABAP’s one. It comes in two different types: Java Secure Storage in the file system and Java Secure Storage.
Why can it be interesting?
Imagine that a strong multi-layer security of the SAP system can be evaded by obtaining just 2 files. Moreover, it leads to losing control not only of the target system but all connected systems and mail services. Want to know where this golden key to open any door is stored? In SAP systems, it is Secure Storage. This article will show you where it is located, how it’s used and how to prevent disastrous consequences of a hacker’s attack.
What can be done by getting access to SAP Java Secure Storage?
Java Security Storage contains a lot of key data which can be used by attackers to escalate their privileges. The most important examples are:
- RFC destinations stores credentials to connect to satellite systems
- HTTP destinations – users and passwords to connect to satellite systems
- Mail destinations – users and passwords to connect to mail services
- Exchange Infrastructure (XI) contains details of connections with satellite systems connected by the SAP XI platform
As you know, getting credentials is one of the most common and effective ways to compromise a service. Eventually, if one can get the usernames and passwords from RFC destinations, he or she can use them to access the external SAP system. An account used for remote function calling usually has special privilege permissions and it’s essential to identify these connections as the system is as secure as the least protected element.
How can we get access to Java secure storage?
Java Secure Storage in file system
Java Secure Storage is a well- known term, nevertheless, let’s refresh our knowledge.
The AS Java stores security-relevant information encrypted in the file system. There are two most important files in the SAP system: SecStore.key and Secstore.properties. They are located in the “\usr\sap\
What can we find here? We have prepared some examples below:
#SAP Secure Store file - Don't edit this file manually!
#Thu Feb 04 19:19:13 PST 2016
$internal/version=Ny4wMC4wMDAuMDAx
$internal/mode=encrypted
jdbc/pool/M13=2261rTZ2pITmqgaR1/UB1iIMr03nbOke3UHjwgib7LTBkoXC2Hugj7DfC7NTK4Rq\r\npapvuV8fQj6NybzKM/BF1VdAAAxdZni9QT/xfzUUB3C2cQQxcx+LWNSqRmDTwHY6\r\nNyYGBVWge6YwdrNp6KwxfNdmX6oXyQQEc9nVwV9O5WtdZKImzYcAYNumbZMb5QGL\r\nLyjB5psGf8QIqqAie7asj6vLleT3JhjSn9vx8CztVnkDSRg1xkc4bPa+us0T/J5z\r\n8aks4APMjxD8YK32FGuBhQ\=\=
$internal/check=hbKoCd5BpzTsKGvOySEX2ZS+LMFqGNKz
00000000: 372e 3030 2e30 3030 2e30 3031 7c1a 84bc 7.00.000.001|...
00000010: abc1 a9d7 6340 ....c@
As you can see, there is encrypted Database connection information in the SecStore.properties file.
It is quite easy to reverse Java applications as we could decompile them and receive a readable code. Some of debugging functions in SAP NetWeaver AS Java were helpful. We found the “com.sap.security.core.server.secstorefs” package with an interesting class “KeyHandler” responsible for key manipulations. After a lot of checks, private method decryptKey is called.
1 2 3 4 5 6 7 8 9 10 11 |
private String decryptKey(byte[] ciphertext) throws InvalidStateException, NoHashException { byte[] plaintext = this.xor(ciphertext); String keyPhrase = null; try { keyPhrase = new String(plaintext, "UTF-8"); return keyPhrase; } catch (UnsupportedEncodingException arg4) { throw new InvalidStateException("security.class_secStoreFS_0017", arg4); } } |
Therefore, the “xor” method, as the name implies, makes XOR between a static hardcoded value and significant bytes from Secstore.key.

The result is the keyPhrase in clear text. As a rule, this keyPhrase is also an admin password.
What about SecStore? In the same package “com.sap.security.core.server.secstorefs”, there is Crypt class with the Crypt() method:
1 2 3 4 5 6 7 8 9 10 11 |
Crypt() { try { Cipher ex = Cipher.getInstance("PbeWithSHAAnd3_KeyTripleDES_CBC", "IAIK"); KeyHandler localKh = new KeyHandler(); localKh.setKeyForSession("xxx"); PBEKeyBMP key = localKh.getEffectiveKey(1); byte[] salt = new byte[16]; salt[0] = salt[1] = salt[2] = salt[3] = salt[4] = salt[5] = salt[6] = salt[7] = salt[8] = salt[9] = salt[10] = salt[11] = salt[12] = salt[13] = salt[14] = salt[15] = 0; byte count = 0; this.pbeParamSpec = new PBEParameterSpec(salt, count); ex.init(1, key, this.pbeParamSpec); |
The “PbeWithSHAAnd3_KeyTripleDES_CBC” algorithm is used to encrypt and decrypt secure data. The encryption uses the TripleDES algorithm in CBC mode via a secret key derived from keyPhrase with the SHA hash algorithm.
As for salt, it’s «0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0».
We have all we need to decrypt secure data. We also wrote a simple tool to decrypt all data from SAP Java AS Secure Storage (that will be released soon):

Java Secure Storage
As you may know, ABAP Secure Storage is introduced as the database table called RSECTAB, which stores information about passwords from:
- RFC destinations
- Exchange Infrastructure (XI)
- LDAP system users
- SAPphone
- SAPconnect
- CCMS (Generic Request and Message Generator)
When we started our research, our objective was to understand how RFC destination works, where it’s stored and how we can get it in Java Stack system. In total, we discovered a remarkable place with a lot of encrypted data like passwords, logins for SAP Destinations (HTTP, RFC, etc.), JavaMail Client Service, etc. So, let’s start from the beginning.
It’s not a secret that an SAP system can be linked with others, for example, using RFC connections. No need to say that it’s necessary to setup credentials of the external system in the destination to establish the connection. One may ask where and how the credentials are stored.
Of note, we were worked with SAP NetWeaver AS Java 7.50 and all we have found works on SAP NetWeaver AS Java 7.30 and further versions.
We created and configured our destination in SAP NetWeaver as Administrator of SAP System. We searched for the destination’s name in the database and discover a table titled “J2EE_CONFIGENTRY”, which contains near 1 million rows.

Every object has its own list of parameters with pre-installed secure and non-secure flag. Every raw determines one parameter of the object. The table consists of 10 columns:

The fields “CID”, “NAME”, “VSTR” and “VBYTES” attracted our attention.
- “CID” provides a unique ID of the object in a specific format like “-9223372036854775700”. All parameters of a certain object have the same “CID”.
- “NAME” is a name of the object’s parameter. It begins with special symbols like “#~” for the RFC destinations.
- “VSTR” and “VBYTES” are the value of the parameter. If the value has no secure flag, it’s stored in clear text in the “VSTR” column and in “VBYTES” one in case it has. Data in VBYTES value is encrypted.
We have collected the full parameter list of RFC Destinations:
Parameter | Secure Flag |
---|---|
#~jco.destination.repository_destination | No |
#~jco.client.snc_qop | No |
#~jco.client.snc_mode | No |
#~AUTHENTICATION_MODE | No |
#~jco.client.cpic_trace | No |
#~POOL_MODE | No |
#~destination.name | No |
#~jco.client.ashost | No |
#~jco.client.sysnr | No |
#~jco.client.trace | No |
#~jco.client.client | No |
#~jco.destination.expiration_time | No |
#~jco.client.passwd | Yes |
#~jco.client.r3name | No |
#~jco.destination.pool_capacity | No |
#~QOP_TEXT | No |
#~jco.client.abap_debug | No |
#~jco.client.lang | No |
#~jco.client.type | No |
#~jco.client.user | No |
#~jco.destination.max_get_client_time | No |
#~jco.destination.peak_limit | No |
#~CONNECTION_MODE | No |
The destination’s name was found in a VSTR column. The parameter’s called “#~destination.name”. We got all parameters with the same CID and discovered “#~jco.client.passwd” and “#~jco.client.user”. It’s the credentials of the external system, but the password is encrypted.
Parameter | Secure Flag |
---|---|
#~jco.client.passwd | 01 01 1C CA 38 1D FB 8C 83 4E 5C B2 06 04 B6 BC 1F 2D 7B B0 10 15 4A 0F 82 BF C8 C1 AD 88 10 60 CC 37 |
Since the password is used to connect to external systems, the value of the encrypted data could not be hashed. Nonetheless, we cannot be completely sure. To check it, we created several other destinations with different passwords and logins.
What did we reveal? The data is not a value’s hash, it does not depend on user name, system time, or anything else. The same passwords have the same encrypted appearance. It’s an interesting fact that the ciphertext consists of the static and dynamic parts. You can see our attempts in the table below:

As we have already mentioned, reversing Java applications is easy enough as it’s possible to decompile them and receive a readable code. We started analyzing the Java code to find where the data became encrypted. At last, we got it. One variable looked so familiar:

Yes, it’s a static part of ciphertext. More steps were taken, and we detected the algorithm «PbeWithSHAAnd3_KeyTripleDES_CBC» we have described before.
Let’s check our findings. We have a ciphertext, and know an algorithm, but the key remains undisclosed. When secure data from database was being decrypted, such methods as “getSecretKey” was called from “com.sap.security.core.server.secstorefs” and “com.sap.engine.core.configuration.impl.security” packages. It seems that our system tried to access our Java Secure Storage file and attain the Secret Key.

Our assumptions turned out to be correct, the key for Java Secure Storage in the file system and the key for encrypted data in “J2EE_CONFIGENTRY” table are the same.
Now we can decrypt every required value from this table. Do you remember the static part of the ciphertext? It`s always the same: «ABCDEFGHIJKLMNOP ».

Eventually, we got the credentials and now can use them to access the external SAP system. An account used for remote function calling usually has special privilege permissions. It’s significant to keep in mind these connections, since an attacker can compromise a peripheral system and get access to the main system by-passing its secure options. As they say, the system is as secure as the least protected element.
We wrote a special tool:

Subscribe to our mailing list below this article and do not miss the release of the tool.
Defense
- Restrict access to the individual key file SecStore.key and SecStore.properties. Once an attacker gains access to this file, they will know the encryption key that allows decrypting Secure Storage data.
- Don’t store any credentials in SAP RFC Destinations. In case it is impossible, create a special user in the target system with low-level privileges to make a connection. This actions prevent the damage and reduce the potential loss.
- Monitor your SAP system regularly for various vulnerabilities and misconfigurations to prevent attackers from accessing your database.