[GXYCTF2019]BabySQli 解题思路&过程

本题页面十分简洁,查看源代码也没有提示项。因为题目名为babysqli,先按照SQL注入的流程试一试。
[GXYCTF2019]BabySQli 解题思路&过程_第1张图片
[GXYCTF2019]BabySQli 解题思路&过程_第2张图片

可以看到显示密码错误,试着修改用户名为其他字符,果真得到用户名错误的显示,因此可以判断,数据库中存在名为admin的用户名的记录。同时源代码中注释了一段字符串,将该字符串经base32解码、base64解码后得到SQL语句。
select * from user where username = '$name',因此判断用户名处存在SQL注入。
对用户名处进行fuzz,得到如下被过滤名单:
[GXYCTF2019]BabySQli 解题思路&过程_第3张图片
按照SQL注入来解此题,本应是注出数据库,但是一筹莫展,根据writeup,使用sqlmap可注出数据库,其中密码为md5加密,且flag并未在数据库中。

因为是本地环境,直接通过查看源码来学习此题的逻辑。

<!--MMZFM422K5HDASKDN5TVU3SKOZRFGQRRMMZFM6KJJBSG6WSYJJWESSCWPJNFQSTVLFLTC3CJIQYGOSTZKJ2VSVZRNRFHOPJ5-->
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
<title>Do you know who am I?</title>

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."'";
// 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!");
		}
	}
}

?>

通过源码可以发现对输入的用户名中的()=or进行检测。若不存在上述内容则执行sql查询,判断返回的数组中第二个(下标为1)是否为“admin”,若为admin则判断输入密码的md5值是否等于查询结果的第三个,若相等则打印flag。这个流程是存在问题的,因为对username处用户输入的过滤的不严格,用户可以自由地使用联合查询。通过下面的例子来具体分析。

首先看一下当前user表中的结构:
[GXYCTF2019]BabySQli 解题思路&过程_第4张图片
当我们执行类似题目中的查询时:SELECT * FROM user WHERE uname='user'
[GXYCTF2019]BabySQli 解题思路&过程_第5张图片
可以看到此时的返回是没有问题的,按照题目的逻辑,将提取该返回中的第三个数据即passwd(这里是明文存储的123456,题目中以md5形式存储)来与输入的password字段的md5值进行比较,若相等则用户认证成功。

那么使用联合查询呢?
[GXYCTF2019]BabySQli 解题思路&过程_第6张图片
接下来将第一个参数改为数据库中不存在的值
[GXYCTF2019]BabySQli 解题思路&过程_第7张图片
因为aaa并不存在数据库中,该查询仅返回连个查询的第二个查询,可以看到,这里的passwd字段是我们可控的,而用户输入的password也是我们可以控制的,于是对上述认证过程进行了绕过。

acquisition:
1.通常base64加密常用,一筹莫展时也要积极尝试其他解密方式,或联合使用例如本例的先进行base32解密,再通过base64进行解密。
2.积累了一种有漏洞的用户认证方式。

你可能感兴趣的:(CTF刷题,数据库)