0 x01 preface
The reason for writing this article is actually quite magical. The reason is that in an actual penetration, I successfully took down a user with low permission through a weak password and entered the background, searched for function points in the background and located the target system through packet capture and analysis. SQL injection existed in the background of the system. I found that the developer of this system is xx company, and CNVD did not include this product, so I wondered if I could get a CNVD certificate.
Due to the poor information retrieval ability, only a handful of urls were collected, and none of these systems had weak passwords to enter the background. Because they could not enter the background, they guessed that the functions of the background could not be used, and the vulnerability could not be reproduced. Therefore, I only submitted a few urls when I knew it would not pass (I remember correctly that the general vulnerability requires at least 3 successful verification cases). As a result, it was rejected by me in the third instance.
Unwilling, the case can not find out, I put the code audit again is not good? So I packaged a code through Webshell (because it is a.net site, I only packaged the bin package down), and then there is this article.
0x02 Vulnerability exploited
Let’s talk briefly about how SQL injection takes down the Intranet. (A previous actual combat, no screenshot, imagine, forgive me)
Vulnerability point packet capture
Try directly sqlMap down — OS-shell, suffering from no absolute path, try Baidu to see if there are any other vulnerabilities, but there is almost no online information, when to give up from Baidu library to find a ray of hope, found the use of the system instructions. The mysql database installation path and the Web path are in the same directory, so use — sqL-shell
select @@datadir
Copy the code
Get the mysql installation directory, and also get the web directory, and finally you can directly — OS-shell.
Get os-shell first taskList, do not kill soft, do not need to kill; Ping the server to find the network, basic operation certutil download MSF immediately online, first use MSF to upload a web shell to the site directory (feel relieved after getting the Web shell). Look at the permissions, system, don’t mention the rights; See systemInfo 08 machine, load kiwi module, read clear text password; Netstat Check port 3389. If port 3389 is not enabled, use the registry to enable it. MSF socks proxy, remote connection to MSTSC. Net View shows that there is no domain, and fScan is uploaded to scan Intranet assets. At the same time, WinScp software is found on the desktop, and several Intranet servers are saved in it. All of them have root permission. Here I put an asterisk in the password viewer, trying to get their plaintext password, and it failed. You can change the WinScp configuration to an INI file and decrypt the password. Then, dump the configuration to the local PC and use the tool to get the password.
On the other side, fscan found the weak passwords of two servers, and there are several servers with unauthorized vulnerability of Redis, which can be logged in with private keys.
In addition, the account password of another platform was found in the SQL backup file.
0x03 Code Audit
By locating the vulnerability file default. ashx from webshell’s file manager, you can see that the userinfo.default class is called.
Find the corresponding DLL file in the bin package, use dnSpy decompile to get the source code, and start auditing.
The structure is as follows:
A global search for the session keyword is not found. A further search for the session keyword in all external references is not found, which is a good sign that the session may not be authenticated.
At line 20, we define the ProcessRequest method and pass in the HTTP request body as an argument to the method. At line 22, we define the httpCookie variable to store the data in the current cookie with the key name “wcms.user”. As you can see at line 23, the program makes only three judgments. Cookie is not empty, the UserID in the cookie is not empty and the RoleID is not empty
As long as the above three conditions are met, the program continues to process the request. Otherwise, 204 is returned with an error.
Because identity verification is not strict, the attacker can perform related operations without the permission of the background administrator. After the audit, I was excited, because I was worried that the system would judge the session and did not reproduce the other sites, which led to the rejection of THE CNVD submission. However, there is no need to worry now, because the system does not verify the session at all. You only need to modify the host parameter in the HTTP request to realize the batch exploitation of vulnerability.
But the audit is not over here, we continue to analyze the causes of SQL injection vulnerability.
In line 32, we check the action parameter, and we follow up with the GetData() function based on the Read value of the payload
From line 190, you can see that the function does not filter the arguments, only whether they are null
In line 197 of the code, the program also verifies the RoleInfoID. It is worried that the id existing in the server may be required to provide, leading to identity authentication failure. Let’s focus on the analysis here
Define a text variable to receive the result. If RoleInfoID does not exist in the HTTP form, call GetRoleID() in the Lib.CommonFunction class to obtain the result. The cookie is returned null only if it does not exist, causing line 198 to be judged false and the API to return null
If a cookie exists, DESDec() is called to DES decrypt the value of RoleID in the cookie and save the result for later use. Here I according to the source code in c # rewrite the decryption process, RoleID used for decryption of content, and the result was finally is garbled (maybe I didn’t write the code to the pot…)
Then I decrypted it with the online DES tool again correctly… (Living in Bengbu, THE code I write is shit.)
Then we go back to the GetData() function, creating the DBHelper object with the CreateUserInfo() function in the lib.factory class at line 186 and calling the GetItems() function at line 205
Through analysis, it is found that IDBHelper interface is implemented by mysql.dbHelper, and then the GetItems() function of DBHelper is analyzed
Line 302 uses a for loop to iterate over the values in the previous text variable to construct an SQL statement that qualifies the query results with the where in syntax. At the same time, we noticed that the search keyword keyword has not been filtered at all so far, and subsequent analysis revealed that the developer has not used preprocessing and parameterization globally, leaving the keyword parameter vulnerable to attack.
To sum up, although RoleID will be used to obtain the sub-account ID, it does not matter if there is no user with this RoleID in the database, because our attack method is blind injection based on time. Even if the database query returns empty, it does not prevent us from attacking through time comparison. Therefore, it can be concluded that the vulnerability can be exploited without authorization.
The whole process is shown in the figure below:
0 x04 team
Careful careful careful!