1. 从一次“意外”的发现说起:当Symfony的Debug模式成为攻击入口
那天下午,我像往常一样对目标进行常规的资产探测和目录扫描。目标是一个看起来挺常规的企业应用,直到我的扫描器在响应中返回了一个熟悉的路径:/app_dev.php。我心里咯噔一下,这个文件名对熟悉Symfony框架的开发者来说,就像一把双刃剑。访问它,页面清晰地显示着“Symfony 2.8.34”和“Debug mode: ON”,旁边甚至还有个方便的“PHP info”链接。那一刻,我知道,这次测试可能不会太“常规”了。
对于不熟悉Symfony的朋友,这里简单打个比方。Symfony是一个功能强大的PHP Web应用框架,而它的Debug模式,就像是汽车维修时的“诊断接口”。开发者在开发阶段打开它,可以实时看到详细的错误信息、SQL查询日志、性能数据,一切尽在掌握,调试效率极高。但问题在于,如果这个“诊断接口”在车辆上路(应用上线)后忘记关闭,并且暴露在了公网上,那就相当于把汽车的引擎盖敞开,还把维修手册和扳手留在了座位上。任何人路过,都能窥探内部结构,甚至尝试“操作”一番。
我遇到的正是这种情况。目标运行着Symfony 2.8.34,PHP版本是5.6.40,一个已经停止维护的旧版本组合。Debug模式不仅开着,还通过app_dev.php这个前端控制器直接暴露。这立刻触发了我的警觉,因为历史经验告诉我,Symfony的Debug模式在特定配置下,可能隐藏着通往服务器深处的“快捷方式”。接下来的故事,就是如何找到并利用这些“快捷方式”的过程。这不仅仅是执行一个已知漏洞利用脚本那么简单,它更像是一次在既定规则下寻找突破口的侦探游戏,充满了曲折和需要临场发挥的技术细节。
2. 初探漏洞:默认密钥与神秘的 /_fragment 端点
发现Debug模式开启后,我的第一反应是去寻找与Debug模式相关的已知风险点。很快,我回忆并搜索到了关于Symfony /_fragment 端点的利用方式。这个端点在开启Debug模式时通常可用,设计初衷是用于内部调试和性能分析,但它需要一个密钥(secret)来对请求进行签名验证,防止被随意调用。
关键在于,在Symfony 3.4.43及更早的版本中,存在一个硬编码的默认密钥:ThisTokenIsNotSoSecretChangeIt。是的,你没看错,密钥的名字就叫“这个令牌不那么秘密请更改它”,但很多开发者在部署时偏偏就忘了改。这就像你家门锁的默认密码是“123456”,还贴了张纸条写着“请修改密码”,但很多人视而不见。
我立刻尝试构造请求。根据找到的资料,需要向 /_fragment 发送一个POST请求,其中包含一个名为 _path 的参数,其值经过URL编码,并且整个请求需要携带一个正确的 _hash 签名。这个签名由密钥、请求的URI(比如 http://target.com/app_dev.php/_fragment)通过HMAC-SHA256算法生成,再经过Base64编码。
我信心满满地用Python写了个脚本生成哈希:
import base64, hmac, hashlib
secret = b'ThisTokenIsNotSoSecretChangeIt'
uri = b'http://target.com/app_dev.php/_fragment'
hash_value = base64.b64encode(hmac.HMAC(secret, uri, hashlib.sha256).digest())
print(hash_value.decode())
拿着生成的哈希值附加到请求中,满心期待地发送出去,结果服务器返回了一个冰冷的 403 Forbidden。
“密钥被改过了?” 这是我当时的第一个念头。毕竟安全意识强的管理员确实会修改这个默认值。如果密钥未知,/_fragment 这条路基本就走不通了,因为HMAC签名无法伪造。但我没有立刻放弃,因为Debug模式往往不止一个“后门”。我转而寻找其他可能暴露配置信息的接口。
3. 柳暗花明:利用 /_configurator 接口泄露关键配置
果然,在翻阅旧版本Symfony的代码和文档时,我发现了另一个在Debug模式下存在的接口:/_configurator。这个接口本是用于Web界面化配置应用的,但在生产环境中暴露则极其危险。我尝试访问了 http://target.com/app_dev.php/_configurat

90

被折叠的 条评论
为什么被折叠?



