【BurpSuite】插件开发学习之J2EEScan(上)-被动扫描

【BurpSuite】插件开发学习之J2EEScan(上)-被动扫描

前言

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

【BurpSuite】插件开发学习之Log4shell
【BurpSuite】插件开发学习之Software Vulnerability Scanner
【BurpSuite】插件开发学习之dotnet-Beautifier
【BurpSuite】插件开发学习之active-scan-plus-plus

J2EEScan

https://github.com/PortSwigger/j2ee-scan.git
逻辑代码在

|____src
| |____main
| | |____java
| | | |____burp
| | | | |____HTTPMatcher.java
| | | | |____J2EELFIRetriever.java
| | | | |____SoftwareVersions.java
| | | | |____WeakPasswordBruteforcer.java
| | | | |____j2ee
| | | | | |____PassiveScanner.java
| | | | | |____Confidence.java
| | | | | |____annotation
| | | | | | |____RunOnlyOnce.java
| | | | | | |____RunOnlyOnceForApplicationContext.java
| | | | | |____Risk.java
| | | | | |____passive
| | | | | | |____SessionFixation.java
| | | | | | |____ApacheStrutsS2023Rule.java
| | | | | | |____JettyRule.java
| | | | | | |____HttpServerHeaderRule.java
| | | | | | |____SqlQueryRule.java
| | | | | | |____PassiveRule.java
| | | | | | |____strutstoken
| | | | | | | |____StrutsTokenCracker.java
| | | | | | | |____ReplayRandom.java
| | | | | | |____ApacheTomcatRule.java
| | | | | | |____SessionIDInURL.java
| | | | | | |____JSPostMessage.java
| | | | | | |____ExceptionRule.java
| | | | | |____IssuesHandler.java
| | | | | |____lib
| | | | | | |____TesterAjpMessage.java
| | | | | | |____SimpleAjpClient.java
| | | | | |____issues
| | | | | | |____impl
| | | | | | | |____OracleEBSSSRF.java
| | | | | | | |____OracleEBSSSRFLCMServiceController.java
| | | | | | | |____ApacheStrutsS2032.java
| | | | | | | |____NodeJSRedirect.java
| | | | | | | |____ApacheRollerOGNLInjection.java
| | | | | | | |____ApacheStrutsDebugMode.java
| | | | | | | |____ApacheAxis.java
| | | | | | | |____HTTPWeakPassword.java
| | | | | | | |____HTTPProxy.java
| | | | | | | |____PrimeFacesELInjection.java
| | | | | | | |____WeblogicUDDIExplorer.java
| | | | | | | |____ApacheStrutsS2052.java
| | | | | | | |____JBossWebConsole.java
| | | | | | | |____EL3Injection.java
| | | | | | | |____XXEParameterModule.java
| | | | | | | |____UndertowTraversal.java
| | | | | | | |____LFIModule.java
| | | | | | | |____ApacheStrutsS2043.java
| | | | | | | |____FastJsonRCE.java
| | | | | | | |____OracleReportService.java
| | | | | | | |____SnoopResource.java
| | | | | | | |____JBossJMXReadOnly.java
| | | | | | | |____WebInfInformationDisclosure.java
| | | | | | | |____XInclude.java
| | | | | | | |____JavaServerFacesTraversal.java
| | | | | | | |____Seam2RCE.java
| | | | | | | |____WeblogicConsole.java
| | | | | | | |____RESTAPISwagger.java
| | | | | | | |____JettyRemoteLeakage.java
| | | | | | | |____JBossJMXInvoker.java
| | | | | | | |____OASConfigFilesDisclosure.java
| | | | | | | |____JacksonDataBindCVE20177525.java
| | | | | | | |____XXEModule.java
| | | | | | | |____WeblogicCVE20192725.java
| | | | | | | |____WeblogicWebServiceTestPageCVE20182894.java
| | | | | | | |____JKStatus.java
| | | | | | | |____WeblogicCVE201710271.java
| | | | | | | |____LFIAbsoluteModule.java
| | | | | | | |____ApacheStrutsS2016.java
| | | | | | | |____ApacheStrutsShowcase.java
| | | | | | | |____ApacheStrutsWebConsole.java
| | | | | | | |____ApacheStrutsS2020.java
| | | | | | | |____StatusServlet.java
| | | | | | | |____UTF8ResponseSplitting.java
| | | | | | | |____TomcatHostManager.java
| | | | | | | |____SpringBootRestRCE.java
| | | | | | | |____PivotalSpringTraversalCVE20143625.java
| | | | | | | |____Htaccess.java
| | | | | | | |____JBossjBPMAdminConsole.java
| | | | | | | |____ELInjection.java
| | | | | | | |____NodeJSPathTraversal.java
| | | | | | | |____ApacheStrutsS2017.java
| | | | | | | |____ApacheSolrXXE.java
| | | | | | | |____OASSqlnetLogDisclosure.java
| | | | | | | |____NodeJSResponseSplitting.java
| | | | | | | |____URINormalizationTomcat.java
| | | | | | | |____JBossWS.java
| | | | | | | |____SpringCloudConfigPathTraversal.java
| | | | | | | |____InfrastructurePathTraversal.java
| | | | | | | |____AJPDetector.java
| | | | | | | |____JBossAdminConsole.java
| | | | | | | |____SSRFScanner.java
| | | | | | | |____SpringDataCommonRCE.java
| | | | | | | |____JavascriptSSRF.java
| | | | | | | |____ApacheWicketArbitraryResourceAccess.java
| | | | | | | |____SpringBootActuator.java
| | | | | | | |____IDocInjection.java
| | | | | | | |____TomcatManager.java
| | | | | | | |____NextFrameworkPathTraversal.java
| | | | | | | |____OracleCGIPrintEnv.java
| | | | | | | |____JBossJuddi.java
| | | | | | | |____AJP_Tomcat_GhostCat.java
| | | | | | | |____SpringWebFlowDataBindExpressionCVE20174971.java
| | | | | | |____IModule.java
| | | | | |____CustomScanIssue.java
| | | | |____J2EELocalAssessment.java
| | | | |____WeakPassword.java
| | | | |____HTTPParser.java
| | | | |____CustomHttpRequestResponse.java
| | | | |____BurpExtender.java

这个代码是基于java写的

BurpExtender

老样子,继承BurpExtender

class BurpExtender(IBurpExtender):

基本信息也和java差不多

public void registerExtenderCallbacks(final IBurpExtenderCallbacks callbacks) {
        // keep a reference to our callbacks object
        this.callbacks = callbacks;
        this.callbacks.registerExtensionStateListener(this);
        // obtain an extension helpers object
        helpers = callbacks.getHelpers();
        // obtain our output stream
        stdout = new PrintWriter(callbacks.getStdout(), true);
        stderr = new PrintWriter(callbacks.getStderr(), true);

        // set our extension name
        callbacks.setExtensionName("J2EE Advanced Tests");

然后创建了一个临时数据库文件并连接了

j2eeDBState = File.createTempFile("burpsuite-j2eescan-state", ".db");
            stdout.println("Using temporary db state file: " + j2eeDBState.getAbsolutePath());
            stdout.println("This internal state is used to avoid duplicate infrastructure security "
                    + "checks on the same host, improving the scan performance");

            connectToDatabase(j2eeDBState.getAbsolutePath());

初始化的数据库表executed_plugins

String fields = "plugin, host, port";

        conn.createStatement().executeUpdate("CREATE TABLE IF NOT EXISTS executed_plugins ("
                + " plugin TEXT PRIMARY KEY,"
                + " host TEXT,"
                + " port INTEGER,"
                + " UNIQUE(" + fields + "))");

doPassiveScan

重写了被动扫描,在PassiveScanner这个类里。

PassiveScanner.scanVulnerabilities(baseRequestResponse, callbacks);

遍历如下规则进行扫描

static PassiveRule[] PASSIVE_RULES = {
            new ApacheTomcatRule(),
            new ExceptionRule(),
            new HttpServerHeaderRule(),
            new SqlQueryRule(),
            new ApacheStrutsS2023Rule(),
            new JettyRule(),
            new SessionIDInURL(),
            new JSPostMessage(),
            new SessionFixation()
    };

一个一个看,

ApacheTomcatRule
【1】tomcat版本发现

Risk.Low

Pattern.compile("Apache Tomcat/([\\d\\.]+)"
【2】tomcat远程jvm虚拟机

Risk.Information

Pattern.compile("\"><small>(1\\.\\d\\.[\\w\\-\\_\\.]+)<"
ExceptionRule
【3】Apache Struts 测试页面

判断struts是开发环境还是dev环境
Risk.Low

"<title>Struts Problem Report</title>".getBytes();
【4】Apache Tapestry 异常错误展示

Risk.Low

            byte[] tapestryException = "<h1 class=\"t-exception-report\">An unexpected application exception has occurred.</h1>".getBytes();
【5】Grails 异常错误展示

Risk.Low

            byte[] grailsException = "<h1>Grails Runtime Exception</h1>".getBytes();

【6】GWT 异常错误展示

Risk.Low

            byte[] gwtException = "com.google.gwt.http.client.RequestException".getBytes();
【7】java 常见的应用异常错误展示

Risk.Low

List<byte[]> javaxServletExceptions = Arrays.asList(
                    "javax.servlet.ServletException".getBytes(),
                    "οnclick=\"toggle('full exception chain stacktrace".getBytes(),
                    "at org.apache.catalina".getBytes(),
                    "at org.apache.coyote.".getBytes(),
                    "at org.jboss.seam.".getBytes(),
                    "at org.apache.tomcat.".getBytes(),
                    "<title>JSP Processing Error</title>".getBytes(),  // WAS
                    "The full stack trace of the root cause is available in".getBytes());
                    "<pre><code>com.sun.facelets.FaceletException".getBytes(),
                    "Generated by MyFaces - for information on disabling".getBytes(),
                    "<title>Error - org.apache.myfaces".getBytes(),
                    "org.primefaces.webapp".getBytes());

HttpServerHeaderRule

http 头泄露应用版本号

【8】Java&Jetty &GlassFish&Weblogic
Pattern.compile("java\\/([\\d\\.\\_]+)"
Pattern.compile("Jetty.([\\d\\.]+)"
Pattern.compile("GlassFish Server Open Source Edition ([\\d\\.]+)"
Pattern.compile("WebLogic (:?Server )?([\\d\\.]+)"
【10】 oracle
ORACLE_APPLICATION_SERVER_RE.add(Pattern.compile("Oracle Application Server Containers for J2EE 10g \\(([\\d\\.]+)\\)", Pattern.DOTALL));
ORACLE_APPLICATION_SERVER_RE.add(Pattern.compile("Oracle.Application.Server.10g\\/([\\d\\.]+)", Pattern.DOTALL));
ORACLE_APPLICATION_SERVER_RE.add(Pattern.compile("Oracle Application Server\\/([\\d\\.]+)", Pattern.DOTALL));
ORACLE_APPLICATION_SERVER_RE.add(Pattern.compile("Oracle9iAS\\/([\\d\\.]+)", Pattern.DOTALL));
【11】nodejs
if (xPoweredByHeader.trim().equals("Express")) {

SqlQueryRule

【12】SQL exception
SQL_QUERIES_RE.add(Pattern.compile("select ", Pattern.CASE_INSENSITIVE | Pattern.DOTALL | Pattern.MULTILINE));
SQL_QUERIES_RE.add(Pattern.compile("IS NOT NULL", Pattern.CASE_INSENSITIVE | Pattern.DOTALL | Pattern.MULTILINE));

ApacheStrutsS2023Rule

【13】StrutsTokenCracker

提取token

    private final Pattern TOKEN_FIELD_PATTERN = Pattern.compile("<input type=\"hidden\" name=\"token\" value=\"([^\"]+)\"");

转int,按固定长度切割

 int[] tokenInts = bytesToInt(bigIntToByte(token));

根据int找到seed

        long seed = findSeed(reverseByteOrder(tokenInts[1]), reverseByteOrder(tokenInts[2]));

根据种子预测随机数,和就token匹配,如果能匹配上,说明种子是对的,也就是说明token可预测。

int[] nextInts = new int[4];
        for(int i=0;i<nextInts.length;i++) {
            nextInts[i] = reverseByteOrder(random.nextInt());
        }

        boolean match1 = tokenInts[2] == nextInts[0];
        boolean match2 = tokenInts[3] == nextInts[1];
        boolean match3 = tokenInts[4] == nextInts[2];

JettyRule

【14】Jetty发现
    private static final Pattern JETTY_PATTERN = Pattern.compile("><small>Powered by Jetty", Pattern.DOTALL | Pattern.MULTILINE);

SessionIDInURL

【15】Session Token in URL
    private static final List<String> SESSIONIDs = new ArrayList<>(Arrays.asList(";jsessionid"));

JSPostMessage

【16】JSPostMessage函数

js的跨域信息通信的函数。

POSTMESSAGE_PATTERNS.add(Pattern.compile(".addEventListener\\(\"message", Pattern.CASE_INSENSITIVE | Pattern.DOTALL | Pattern.MULTILINE));
POSTMESSAGE_PATTERNS.add(Pattern.compile("window\\).on\\(\"message", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE));
POSTMESSAGE_PATTERNS.add(Pattern.compile(".postMessage\\(", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE));

SessionFixation

【17】session fixation attack(固定会话攻击)

先检查url,这个检查很粗糙,直接判断后缀,还是黑名单,没有后缀就默认通过

isJavaApplicationByURL(curURL)

在这里插入图片描述

然后条件是请求包有JSESSIONID且返回包含有账号等信息

if (requestCookie != null && requestCookie.contains("JSESSIONID")) {
            String reqBodyLowercase = reqBody.toLowerCase();

if (reqBodyLowercase != null
                    && (reqBodyLowercase.contains("password") || reqBodyLowercase.contains("pwd") || reqBodyLowercase.contains("passw"))
                    && (reqBodyLowercase.contains("user") || reqBodyLowercase.contains("uid") || reqBodyLowercase.contains("mail"))) {

并且返回包没有setcookie(说明固定了会话),或者setcookie字段里包含JSESSIONID
这种校验比较粗糙,注释也说了

Due to the nature of the vulnerability, this check is prone to False Positives and must be manually confirmed
在这里插入图片描述

后话

主动扫描有点多,放在一个文章显得有点重,拆成两个。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值