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

相关