Hole state IAST automatically detects S2-001 vulnerability

Posted by daok on Fri, 18 Feb 2022 20:08:14 +0100

1, Use Dongtai Iast to detect S2-001 vulnerability

1. Start the online shooting range

Log in to the online shooting range: http://labs.iast.huoxian.cn:8081 , start the 'S2-001' environment. After waiting for the environment to start, click the * * access range * * button to go to the range environment. This environment comes from 'vulhub' and 'vulapps'`

2. Log in to * * cave IAST * * website: http://iast.huoxian.cn : 8000 /, view vulnerability detection results

3. Enter the search function and analyze the complete stain call graph

3.1 Source point

First, at org apache. struts2. dispatcher. mapper. In the DefaultActionMapper#handleSpecialParameters () method, the getParameterMap method of the Servlet interface is called to obtain the external parameters to form the initial stain.


3.2 Propagator method

After a series of treatment, the stain is finally displayed on COM opensymphony. xwork2. util. In the OgnlUtil#compile method, call Ognl.. The Ognl#parseexpression method propagates the tainted data into an Ognl expression object

3.3 Sink method

Finally, in Ognl In the Ognl#getvalue method, use the getValue method of the Ognl expression object to obtain the value of the Ognl expression

2, S2-001 vulnerability manual analysis

First, use the struts 2 tag to define the form

<%@ page language="java" contentType="text/html; charset=UTF-8"
<%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<h2>S2-001 Demo</h2>
<p>link: <a href="https://struts.apache.org/docs/s2-001.html">https://struts.apache.org/docs/s2-001.html</a></p>

<s:form action="login">
    <s:textfield name="username" label="username" />
    <s:textfield name="password" label="password" />

After the above form is submitted, struts 2 will parse the form, parse the values of username and password in the form, and then display them. It includes constructing ognl expression% {username} to obtain user input. The back-end code is as follows:

Class valueClazz = this.getValueClassType();
if (valueClazz != null) {
    if (this.value != null) {
        this.addParameter("nameValue", this.findValue(this.value, valueClazz));
    } else if (name != null) {
        String expr = name;
        if (this.altSyntax()) {
            expr = "%{" + name + "}";

        this.addParameter("nameValue", this.findValue(expr, valueClazz));
} else if (this.value != null) {
    this.addParameter("nameValue", this.findValue(this.value));
} else if (name != null) {
    this.addParameter("nameValue", this.findValue(name));

At org apache. struts2. components. In the UIBean#evaluateParams method, we use the Ognl syntax to splice the parameter names, and then call the findValue method to find the value of the ognl expression. The findvalue method finally calls com opensymphony. xwork2. util. Textparseutil#translatevariables method, the code is as follows:

public static Object translateVariables(char open, String expression, ValueStack stack, Class asType, TextParseUtil.ParsedValueEvaluator evaluator) {
    Object result = expression;

    while(true) {
        int start = expression.indexOf(open + "{");
        int length = expression.length();
        int x = start + 2;
        int count = 1;

        while(start != -1 && x < length && count != 0) {
            char c = expression.charAt(x++);
            if (c == '{') {
            } else if (c == '}') {

        int end = x - 1;
        if (start == -1 || end == -1 || count != 0) {
            return XWorkConverter.getInstance().convertValue(stack.getContext(), result, asType);

        String var = expression.substring(start + 2, end);
        Object o = stack.findValue(var, asType);
        if (evaluator != null) {
            o = evaluator.evaluate(o);

        String left = expression.substring(0, start);
        String right = expression.substring(end + 1);
        if (o != null) {
            if (TextUtils.stringSet(left)) {
                result = left + o;
            } else {
                result = o;

            if (TextUtils.stringSet(right)) {
                result = result + right;

            expression = left + o + right;
        } else {
            result = left + right;
            expression = left + right;

In the translateVariables method, check whether there is an ognl expression in the current expression. If so, call stack The findValue (VaR, astype) method searches the result of the ognl expression, reconstructs the ognl expression on the result, and then loops through the above steps until there is no ognl expression in the result of findValue and returns data. The key of the above method is the findValue method. Therefore, follow up the method, and the code is as follows:

public Object findValue(String expr, Class asType) {
    Object var4;
    try {
        Object value;
        if (expr == null) {
            value = null;
            return value;

        if (this.overrides != null && this.overrides.containsKey(expr)) {
            expr = (String)this.overrides.get(expr);

        value = OgnlUtil.getValue(expr, this.context, this.root, asType);
        if (value != null) {
            var4 = value;
            return var4;

        var4 = this.findInContext(expr);
    } catch (OgnlException var9) {
        var4 = this.findInContext(expr);
        return var4;
    } catch (Exception var10) {
        this.logLookupFailure(expr, var10);
        var4 = this.findInContext(expr);
        return var4;
    } finally {

    return var4;

In the above method, first check whether the ognl expression needs to be rewritten, and replace the ognl expression if necessary; Then use ognlutil The getValue method obtains the value of the ognl expression expr. The code is as follows:

public static Object getValue(String name, Map context, Object root, Class resultType) throws OgnlException {
    return Ognl.getValue(compile(name), context, root, resultType);

In the above methods, first call the compile method to parse the value of the Ognl expression and obtain the Ognl object. The code is as follows:

public static Object compile(String expression) throws OgnlException {
    synchronized(expressions) {
        Object o = expressions.get(expression);
        if (o == null) {
            o = Ognl.parseExpression(expression);
            expressions.put(expression, o);

        return o;

Then call Ognl.. The getValue method uses the ognl object and context to get the value of the expression. At this point, the ognl expression parsing is triggered, and the ognl expression is controllable by the user.

Account Application


  • For the overall open source joint development of the cave IAST partner program, please scan the QR code below for the application method


  • If you need to join the technical discussion group, scan the QR code, add wechat and note "cave IAST - add group", and the staff will pull you into the group