Hello everyone, my name is Vahagn Vardanyan (there is no typo here, as many people think :)), I work in DSec as a security researcher for SAP systems, and in this short article I will talk about a bunch of vulnerabilities in SAP, which can lead to compromise of the system and how the result is access to critical business information.
With each new version of SAP NW, applications are becoming more secure, and vulnerabilities do not compromise the system completely. But there are situations when several security problems used together still allow attackers to achieve their goals. Today we will talk about how to compromise SAP NW using a bunch of vulnerabilities.
In the article, we first talk about the possibility of obtaining information from the system, the exploitation of vulnerabilities based on information leakage, then - on the escalation of privileges. All vulnerabilities were found in the latest (at the time of the study) versions of SAP (SAP NW AS JAVA 7.4). Well, it started.
Introduction
The SAP AS JAVA server has many standard applications that are stored in the folder C: \ usr \ sap \% SID% \ J00 \ j2ee \ cluster \ apps \ sap.com, where% SID% is the SID of the SAP system. So, our test system has a SID DM0.
From the screenshot below, it can be understood that in the standard assembly of SAP NW there are more than 1,400 components (if you install the complete assembly, more than 2,000 components will be released), which can be caused by SAP users with different permissions.
Each component that can be called has some level of access, described in web.xml files, portalapp.xml. In total there are 4 types of access rights to components:
Naturally, we will be interested in servlets, applications and components that have no_safety rights, or those that do not have predefined rights, because they are accessible from the outside, and any unauthorized user can access them.
We turn to the first vulnerability.
Information Disclosure Vulnerability
After searching the configuration files, the file descriptors, in which there is a description of access rights
<property name="SafetyLevel" value="no_safety"/>
or it is completely absent. A webdynpro component tc ~ rtc ~ coll.appl.rtc ~ wd_chat was found. Here is its configuration file:
This service can be accessed at the following address:
http: / SAP_IP: SAP_PORT / webdynpro / resources / sap.com / tc ~ rtc ~ coll.appl.rtc ~ wd_chat / Chat #
Open the page and see some functionality for sending messages. Among other things, it has the ability to add recipients (users):
By clicking on the record add participant , we can see a window that offers to search for a user without authorization.
It is very interesting that in the list a user was found with the name Jon Snow and login J.Snow.
Hmmm ... It looks like using this vulnerability, you can get a list of logins of SAP users. However, this is not enough to compromise the system, because after entering the wrong password 3–5 times, the account will be blocked. So let's look for other vulnerabilities.
SQL injection
The next anonymous service in which the vulnerability was found is the UDDISecurityService .
On the SAP server, this service is located at: C: \ usr \ sap \ DM0 \ J00 \ j2ee \ cluster \ apps \ sap.com \ tc ~ uddi \ servlet_jsp \ UDDISecurityService \
As can be seen from the configuration file, the service is also available anonymously:
The servlet-class tag indicates that access to this servlet can be obtained using SOAP requests. Now we face the task of finding the structure of a SOAP request. It is known that the structure of requests can be found by finding the wsdl file, which describes this service. It turns out that we need to find the wsdl file containing the UDDISecurityImplBean entry. Using the total commander, run the search.
On the server there was a file containing the information we need. Since it has a wsdl structure, you can convert it to a SOAP request using a special utility. We found out that in this file 2 methods are described: applyPermission and deletePermissionById.
Select the second method (deletePermissionById), generate a SOAP request and send it to the SAP server.
In the answer we get:
The answer returned the 200th code, but the logic of processing the sent data is incomprehensible. To “get acquainted” with the full functionality of this program, you need to find on the server the JAVA code that processes the SAOP request. And we find a jar-file in which there is a description of processing this request, and located on the server at:
C: \ usr \ sap \% SID% \ J00 \ j2ee \ cluster \ apps \ sap.com \ tc ~ uddi \ EJBContainer \ applicationjars \ tc ~ esi ~ uddi ~ server ~ ejb ~ ejbm.jar
After decompiling the file, we can see the following classes:
The request itself is processed in the UDDISecurityBean class.
When we send a deletePermissionById request, you can see how the PermissionsDao () constructor appears, which calls the deletePermision function. Moving to the PermissionsDao class.
Data transmitted via a SOAP request is used to access the SAP server database without filtering. We can assume that there is a SQL injection. To be sure of this, you need to send a special request for SQL injection and see the SAP server database logs. The database log files are located by default in the folder C: \ usr \ sap \% SID% \ J00 \ j2ee \ cluster \ server0 \ log \ system \ and are called by default database_NN.N.log, where N is a number from 0 to 9 inclusive.
Send the following request:
In response, we also get the 200th code:
But in the database logs you can notice the following:
Now we can say for sure that we have an anonymous SQL injection into the SAP database. Remove the logs from the server and send the following request. If there are no errors in the logs on the server, the structure of the SQL query is correct.
No errors.
Now a new task is to find a query that will help retrieve critical data from the SAP database, for example, Jon Snow password hash. From the SAP NW AS JAVA documentation it is known that user data (login, name, password hashes) are stored in the UME_STRINGS table.
The request to retrieve all data from UME_STRINGS is as follows:
As you can see, this SQL injection vulnerability is not error based, but an adapter that is used in this servlet and does not support the sleep () function. We will use the table multiplication method to increase the query processing time and turn this vulnerability into time-based SQL injection. To do this, you need to find a table that will always contain data in all SAP servers. Such a table is J2EE_CONFIG , which stores component configuration information.
Let's make the following request:
When receiving a request, the server tries to extract data from the database by multiplying 2 tables - UME_STRINGS and J2EE_CONFIG . Since large data is stored in tables, a temporary load on the server will occur.
And we get the answer after 32 seconds. And - ready: time-based SQL injection.
Getting admin hash
As mentioned above, hashed passwords are stored in the UME_STRINGS table, which has the following structure:
The UME_STRINGS.PID table stores user names.
UME_STRINGS.ATTR = 'j_password' indicates that the user is created and is present in the SAP AS JAVA stack.
UME_STRINGS.VAL stores password hashes from users whose logins are recorded in UME_STRINGS.PID .
It turns out that you need to pick up the data contained in the field UME_STRINGS.VAL. The basic SQL query for injection looks like this:
SELECT COUNT(*) FROM J2EE_CONFIG, UME_STRINGS WHERE UME_STRINGS.ATTR='j_password' AND UME_STRINGS.PID LIKE '%J.Snow%' AND UME_STRINGS.VAL LIKE '%'
It is known that the password is stored in the SAP database in a hashed form, the hashing algorithm can be as follows:
Sapsha
SSHA
SHA
SHA-512
Those. In the password hash there can be such characters:
1234567890QWERTYUIOPASDFGHJKLZXCVBNM*.,{}#+:-=qwertyuiopasdfghjklzxcvbnm/{SPACE}
We will iterate through them, and if the character we have chosen matches the hash character from the password, we will have a delay in the request.
The response will be delayed for 1 second.
By automating this process, we get a hash from user Jon Snow.
{SHA-512, 10000, 24}YXNkUVdFMTIzzbAIcuqnw5RzpmdgZ38PWjhBeaGzHkV6XINN7ZDqxqgr0nYxfCaE5ncdK7kzzkzryJAn42qv9YlY034Llr4b8Rv1534chnIf1i8jZE6ylzTV5XuzvUlaXQ==
As you can see, the password is hashed by the SHA-512 algorithm. On this study would have ended, if not a third vulnerability.
Cryptographic error, privilege escalation
This vulnerability was found by chance :-)
Using SQL injection, we got the password hash of Jon Snow user:
{SHA-512, 10000, 24}YXNkUVdFMTIzzbAIcuqnw5RzpmdgZ38PWjhBeaGzHkV6XINN7ZDqxqgr0nYxfCaE5ncdK7kzzkzryJAn42qv9YlY034Llr4b8Rv1534chnIf1i8jZE6ylzTV5XuzvUlaXQ==
Hmmm As you can see, at the end of the hash there are characters ==. And what will happen if we make base64decode?
What? How? Password? There is only one way to check if this is really Jon's password - go to the portal using J.Snow login and asdQWE123 password.
Hooray! I am the administrator! But how? It is necessary to figure out what is connected with the fact that the password is in base64 format in the database.
As a result of the search, we found the file sap.com ~ tc ~ sec ~ ume ~ core ~ ​​impl.jar , which is located in the folder: C: \ usr \ sap \ DM0 \ J00 \ j2ee \ cluster \ bin \ ext \ com.sap .security.core.sda \ lib \ private . It contains functions that are responsible for hashing users' passwords, checking their validity, blocking users, etc. One of the main classes is PasswordHash . Consider this class in more detail.
It has 2 constructors, one of which
public PasswordHash(String user, String password) { this._user = user; this._password = password; this._extra = null; }
As we can see, it initializes the internal user and password variables.
To get a hash from the password, another getHash function of the PasswordHash class is used.
As can be seen from line 114, this function calls the createHashWithIterations function, which takes a random entry value as a salt to generate the hash. Go to the createHashWithIterations (salt) function .
On line 184, the output variable is stored, storing the bytes of the entered user password.
In line 185, a new variable, pass_n_salt , is created , consisting of password bytes and a random salt generated in line 112.
Next, in line 191, the hashWithIterations function is called , which takes 2 parameters as input: output and pass_n_salt . Note that the output stores the password asdQWE123 in bytes.
So interesting. Consider each line separately:
Line 238 initializes the output variable, in which data from the data variable is written (the first bytes of the data variable are the password asdQWE123).
Line 241 initializes the md variable of the MessageDigest class, which will be responsible for hashing the data.
Line 243 starts a hash loop, _iterations = 10,000.
Lines 244-245 hash the data using the SHA-512 algorithm and are written to the data variable.
Line 246, the output variable is reset.
Line 247, the output variable records the data from the pass variable (asdQWE123).
Line 248, data from data is written to the end of the output variable.
It turns out that the output variable will have the following structure:
All this logic will be executed 10,000 times, and in the last step of the cycle, the password will be added to the beginning of the output variable, after the password the hashed data will be added. Thus, the first bytes of the output variable will consist of an unansheaded password.
Block diagram of the vulnerable code:
pass = plain_pass
output = [plain_pass] + [random_byte]
i = 0
data = sha_512 (output)
output = [NULL]
output = [plain_pass] + [data]
for (i) i = i + 1
if i == 10,000
exit_from_loop
output == "asdQWE123blablabla"
The error of the programmers was that they did not hash the data in the last step of the for loop. This vulnerability is now closed, and the fix looks like this:
pass = plain_pass
output = [plain_pass] + [random_byte]
i = 0
output = [plain_pass] + [data]
data = sha_512 (output)
for (i) i = i + 1
if i == 10,000
exit_from_loop
As we can see, SAP reversed the order of steps, now it first initializes the output variable and then hashes the variable data.
Conclusion
So let's see what security notes SAP has released to correct these vulnerabilities.
The disclosure of users, logins - SAP nota 2255990 , the vulnerability was fixed on the 8th of May 2016. It already has a CVE-shku CVE-2016-3973 (CVSS v3 7.5).
List of vulnerable versions of SAP:
SAP security note 2101079 was released to correct SQL injection, it was fixed on February 9th, 2016, CVE-2016-2386 (CVSS v3 9.1).
List of vulnerable versions of SAP:
Vulnerability with incorrect implementation of password hashing is treated with note 2191290 . The note was released on January 12, 2016, CVE-2016-1910 (CVSS v3 5.3).
List of vulnerable versions of SAP:
Of course, one of you may say, they say, they installed some kind of “server curve” and found bugs, but for this purpose there is statistics only on disclosing the SAP user list. Scanning was carried out on 7348 SAP servers that are accessible via the Internet.
Statistics for each port
In total, it turns out that about 1013 servers (~ 14%) are vulnerable to information disclosure vulnerabilities
Well, another sign on the statistics of ACCESSIBILITY of a servlet in which there may be a SQL injection vulnerability (if a patch has not yet been installed)
Total - 2174 servers, which is ~ 30%
So what needs to be done?
It is necessary to patch, comrades administrators.
Yes, and finally: if you want to work with us and find even more cool bugs - send your resume here
Source: https://habr.com/ru/post/303500/
All Articles