CTFshow-Web-源码泄露与SQL注入

一、靶场:ctfshow web10
二、解题步骤:
步骤一:打开靶场,发现还是一个登陆页面,测试sql注入发现和web9一样没有任何回显或变化,但发现多了一个取消按钮,点击后发现下载了一个文件

image1

image2

里面貌似是登录页面的源码

步骤二:代码审计

<?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;

        }

    }

}

?>

分析上面的代码可以得知:

1、创建了一个过滤函数将一些常用sql注入语句被拉入了黑名单,将sql语句进行了正则替换,直接过滤了;

2、在执行sql语句前会将username和password的值放到过滤函数中,将黑名单中的语句进行过滤,并且过滤后的长度要与我们输入的内容一致;

3、用户名和密码没有要求长度;

4、过滤完成之后就直接执行了查询语句,使用mysqli_fetch_assoc() 函数从结果集中取得一行作为关联数组,即将查询结果中的密码与输入的密码进行校验

解题方法:此处只能用WITH ROLLUP的进行绕过,首先学习一下WITH ROLLUP:

with rollup 可以对 group by 分组结果再次进行分组,并在最后添加一行数据用于展示结果( 对group by未指定的字段进行求和汇总,而group by指定的分组字段则用null占位),使用 with rollup,此函数是对聚合函数进行求和,注意 with rollup是对 group by 后的第一个字段,进行分组求和。

例:

现在有这样一张学生表,里面的数据如下所示。

image3

如果想对根据学生,对科目,分数求和,可以这样写。

image4

如果想在这个的基础上,求出学生的总分数,应该这么做:

image5

步骤三:构建payload:1'/**/or/**/true/**/group/**/by/**/password/**/with/**/rollup/**/#

注解:poc当作用户名输入后,而密码又没有要求一定要有内容,所以会通过前面的所有判断语句,然后到达sql查询语句,拼接替换后得到:

$sql="select * from user where username = '1'/**/or/**/true/**/group/**/by/**/password/**/with/**/rollup/**/#'";

可以看到拼接后的语句变了,username处由于or语句和后面的true直接通过,然后执行了group by分组语句,对密码进行分组,然后是with rollup对密码进行求和,然而由于with rollup语句的特殊性,返回结果的最后一行用null来填充password, 这样一来我们的返回结果 $result 中就有了一个值为null的password,而登录时并没有输入密码,那就是null,null==null成功登录,成功拿到flag

image6

posted @ 2025-12-03 09:31  shinianyunyan  阅读(19)  评论(0)    收藏  举报