BUUCTF-[GXYCTF2019]BabySQli
BUUCTF-[GXYCTF2019]BabySQli WriteUp
知识点
-
利用联合查询临时插入数据
在这里并没有将数据插入到表里面,只是这样子可以查询到(返回)一列,返回的列就是union后面插入的数据,在php里面就是可以查询到这一列(虽然不是直接在表格里面查询的,但是php会接收到这一列数据)至于他是怎么接收的,看最下面的源码
-
明白密码是以md5的形式储存
题解
-
打开之后是一个登录页面。先随便输入些试试。将数据通过POST请求发送到search.php里面。查看网页源代码发现
-
将其通过base32解码,再通过base64解码。base32特征是大写字母和数字或者后面有三个"=",base64是大写字母、小写字母和数字或者后面有一两个"="。
-
解码之后是
select * from user where username = '$name'
。通过这个sql语句,猜测查询的时候返回了一整列,只通过查询了一个username名。返回一列,通过比对密码,再判断是否密码正确。 -
返回了wrong user! 用户名不正确
-
说明用户名正确,密码不正确。 开始注入
-
有过滤,用大小写绕过试试(后来才只知道绕过了or)
-
通过大小写绕过,先猜字段数,字段数为3;但是,我们怎么知道那个字段名是username呢?因为利用联合查询插入临时数据时,要把用户名密码查到正确的位置,然后在php里面通过返回的数组,比如索引数为2可以匹配到正确的数。
-
也可以通过用联合查询插入临时数据的方法来判断那个段时username,上面显示wrong user! 说明第一个不是username;
-
可以知道第二个字段时username,现在可以插入一个密码;但是还有一个问题,即使密码是通过md5加密的,我看了源码才知道的,这就当时经验积累吧
-
所以,查询这一句
-admin' union select 123,"admin","202cb962ac59075b964b07152d234b70"#
-
'123' 的md5加密就是 "202cb962ac59075b964b07152d234b70" 。
-
最后一起研究一下源码
$name = $_POST['name']; $password = $_POST['pw']; $t_pw = md5($password); $sql = "select * from user where username = '".$name."'"; // echo $sql; $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{ // echo '
'; $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!"); } } }