进入题目一个登录框

[GXYCTF2019]BabySQli_联合查询

 

对登录框做了一些常规的sql注入和fuzz发现都无果。然后在等级登录后跳转的search.php页面查看源代码发现一段编码。

[GXYCTF2019]BabySQli_字段_02

MMZFM422K5HDASKDN5TVU3SKOZRFGQRRMMZFM6KJJBSG6WSYJJWESSCWPJNFQSTVLFLTC3CJIQYGOSTZKJ2VSVZRNRFHOPJ5

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

[GXYCTF2019]BabySQli_php_03

c2VsZWN0ICogZnJvbSB1c2VyIHdoZXJlIHVzZXJuYW1lID0gJyRuYW1lJw==

然后base64解码

 

 

 [GXYCTF2019]BabySQli_php_04

select * from user where username = '$name'

所以知道了sql语句为select * from user where username = '$name',然后用联合查询进行测试字段数。

[GXYCTF2019]BabySQli_php_05

 

 两个字段发现报错

[GXYCTF2019]BabySQli_CTF_06

 

 

三个字段不报错,证明sql查询一共又三个字段。

[GXYCTF2019]BabySQli_数据_07

 

 

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

测试1' union select 'admin',2,3#发现user错误

[GXYCTF2019]BabySQli_php_08

 

 

测试1' union select 1,'admin',3#,发现是pass密码错误,所以知道第2个字段为user字段

[GXYCTF2019]BabySQli_联合查询_09

 

 

然后这里卡了好久,不知到search.php到底是怎么写的,然后直接看了下search.php的源代码,做题的时候源代码应该是看不到的,这里是buuctf为标明题目出处放在这的。

<!--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!");
        }
    }
}
 
?>

然后发现password有被MD5进行加密,他喵的,这题目出的,一点提示也没有。

if($arr[1] == "admin"){
    if(md5($password) == $arr[2]){
        echo $flag;
    }
    else{
        die("wrong pass!");
    }
}
else{
    die("wrong user!");

知道了MD5加密了password后,那就是将查询出来的passwd和输入的密码的md5值比较,相等则登录得到flag不相等则wrong pass。

就是我们的sql语句执行时,password字段中的内容要==md5(我们密码栏输入的password)。接下里就是要绕过密码的md5验证,需要把我们输入的值和数据库里面存放的用户密码的md5值进行比较,那要怎么绕过呢?可以用联合查询语句用来生成虚拟的表数据。

学到了联合注入有个技巧。在联合查询并不存在的数据时,联合查询就会构造一个 虚拟的数据。 举个例子:

最初users表中只有一行数据,
[GXYCTF2019]BabySQli_数据_10
我们通过union select查询就可以构造一行虚拟的数据,
[GXYCTF2019]BabySQli_联合查询_11
如上图,我们在users表中利用联合查询创建了一行虚拟的数据。
[GXYCTF2019]BabySQli_联合查询_12

我们的思路就来了,我们可以利用联合查询来创建一行admin账户的续集数据,混淆admin用户的密码,将我们自定义的admin用户的密码(123)加进去,这样我们不就可以登录admin用户了吗。

在用户名登录框输入1' union select 1,'admin','202cb962ac59075b964b07152d234b70'#其中202cb962ac59075b964b07152d234b70为123的MD5值,然后在密码登录框中输入123即可登录。

[GXYCTF2019]BabySQli_数据_13

 

 

 

 

__EOF__

[GXYCTF2019]BabySQli_CTF_14
作者: 随风kali