Single

[CTF.SHOW]web101 min read

登录输入任何东西无果qwq,fuzz了一下运气好index.phps试出来了源码,夸夸自己:

<?php
		$flag="";
        function replaceSpecialChar($strParam){
             $regex = "/(select|from|where|join|sleep|and|\s|union|,)/i";
             return preg_replace($regex,"",$strParam);
        }
        if (!$con)
        {
            die('Could not connect: ' . mysqli_error());
        }
		if(strlen($username)!=strlen(replaceSpecialChar($username))){
			die("sql inject error");
		}
		if(strlen($password)!=strlen(replaceSpecialChar($password))){
			die("sql inject error");
		}
		$sql="select * from user where username = '$username'";
		$result=mysqli_query($con,$sql);
			if(mysqli_num_rows($result)>0){
					while($row=mysqli_fetch_assoc($result)){
						if($password==$row['password']){
							echo "登陆成功<br>";
							echo $flag;
						}

					 }
			}
    ?>

分析代码,过滤了select|from|where|join|sleep|and|空白字符|union,且不区分大小写。过滤空白字符好说,可以用/**/代替。

正常情况下:

return preg_replace($regex, "", $strParam);

把名单内替换为空,可以用双写绕过,但是这道题:

if(strlen($username)!=strlen(replaceSpecialChar($username))){
			die("sql inject error");
		}

它会检查用户输入值和替换黑名单后的长度是否一致,所以不能双写绕过。

再往下看,获取flag的条件是$password==$row[‘password’],然而并不知道什么密码呀,查询资料学到了这里可以用WITH ROLLUP绕过:

with rollup:   要配合 group by 一块儿使用,”group by password with rollup”,简单说一下,就是使用with rollup 查询以后,查询结果集合里面会多一条NULL 记录,这一题利用NULL 和空字符相等,而后获得flag。所以我们就是要通过with rollup使sql语句查询结果为null,然后不输入password使password为null

payload:‘or/**/1=1/**/group/**/by/**/password/**/with/**/rollup#

⚪参考:

https://www.cnblogs.com/chalan630/p/12676944.html