Share a set of audit ideas for .net system code
Pay attention to web.config and global.asax first, and confirm that it is the .net mvc architecture
Drag into dnSpy to decompile and find that the code is confused
Use de4dot deobfuscation to get the source code
Because it is the mvc mode, focus on the controller layer, derive a base class controller BaseController and the remaining three other controllers
It is found that BaseController needs authentication, so it will be put on hold for now
Turn to the Login controller with potential unauthorized vulnerabilities, and find the back-end login verification method GetLogin()
First simply filter the input, and then query the corresponding account set information. If the account set information is judged correct, the 55th line of the code calls the DAL layer interface to judge the user information. If the result set count is greater than 0, it proves that the user information is also correct
At this point, the code logic seems to be fine until line 62 of the code.
The system uses Forms Authentication as the authentication module. When the client tries to access the background page without authorization, the system will redirect the user to the /Login/V_Login page for identity authentication. If the user enters the correct account password and passes the verification, the system will encrypt and save the authentication credential FormsAuthenticationTicket to the client cookie, and then the client will automatically carry the authentication cookie to access the resources that it wanted to access before.
Follow up to the FormsAuthen() method on line 62 of the code
Splice the incoming parameters using the $ symbol, add a randomly generated guid at the end to form the original ticket of the authentication cookie, and finally use the FormsAuthentication.Encrypt() method to encrypt the above ticket to generate an authentication cookie, and finally add this cookie to the response packet in line 213 of the code to confirm that it is the method used to generate the authentication cookie, but then look at where it is called
The current class, which is LoginController, is a public modifier, which means it is a public method on the Login controller. Since the Login controller is a controller that can be accessed anonymously, we can directly call this method externally to generate an authentication cookie.
Look through the MSDN documentation to confirm
On the controller, the public method has no [NoAction] annotation, all three conditions are met, and the parameters of the FormsAuthen() method are all string types, which must be verified by model binding
First verify whether it can be called externally. If it succeeds, the returned cookie value is empty because no parameters have been passed in yet.
Change to a POST request and pass in fake parameters
The cookie is successfully returned, and then we use a background interface for verification
Failed to open the database? I didn’t report an error when logging in to capture packets before, why is it now reporting an error? This "test" database seems to be a parameter name that we forged before. Did the background controller verify these parameters?
Going back to the background controller code, it is found that information such as user name and database name will be obtained from the base class controller for query
The base class controller will obtain the information from the credentials and save it to the member variable of the controller, which is convenient for its subclass controllers to use
So if the parameters we construct are made up, even if the credentials are forged successfully, they cannot be used normally
This has to analyze the meaning of each parameter of the FormsAuthen() method, and summarize a table by combining the database corresponding to the source code
parameter | meaning |
---|---|
id | The ID of the logged-in user, superuser is 00001 or 00000 |
name | The username of the logged-in user needs to be url-encoded when the front-end is passed in |
editionName | System version name |
dBName | The name of the database to connect to |
ztcode | Account set code |
pwd | User password, the backend has not been verified, so it can be forged arbitrarily, such as 123456 |
LimitGroupID | Menu permission id, usually empty |
LimitAutoSync | Unknown parameter, usually empty |
systype | System type, generally 1 |
However, the values of many parameters are still unknown, such as database name, account code, etc. How to obtain them has become a difficult problem
Fortunately, through the global search parameter name, I found a method in the Login controller that can be obtained without authorization.
Burp constructs the request to get it
Finally, construct the request, fill in the obtained parameter values and send the package to successfully obtain the authentication cookie
The browser plug-in changes the cookie, visits the background home page, successfully enters, and all functions are in normal use