ctfshow web由一道题的思路实现通杀

ctfshow萌新计划

根据web1的几个解法思路我实现了对后面几道题的通杀,仔细想想感觉对于我这样的新手来说这几题还不错

题目一:web1 代码很安全,没有漏洞

ctfshow web由一道题的思路实现通杀

打开题目很显然这一题考察的是代码审计,我们把代码粘贴下来审计一波

<html>
<head>
    <title>ctf.show萌新计划web1</title>
    <meta charset="utf-8">
</head>
<body>
<?php
# 包含数据库连接文件
include("config.php");
# 判断get提交的参数id是否存在
if(isset($_GET['id'])){
    $id = $_GET['id'];
    # 判断id的值是否大于999
    if(intval($id) > 999){
        # id 大于 999 直接退出并返回错误
        die("id error");
    }else{
        # id 小于 999 拼接sql语句
        $sql = "select * from article where id = $id order by id limit 1 ";
        echo "执行的sql为:$sql<br>";
        # 执行sql 语句
        $result = $conn->query($sql);
        # 判断有没有查询结果
        if ($result->num_rows > 0) {
            # 如果有结果,获取结果对象的值$row
            while($row = $result->fetch_assoc()) {
                echo "id: " . $row["id"]. " - title: " . $row["title"]. " <br><hr>" . $row["content"]. "<br>";
            }
        }
        # 关闭数据库连接
        $conn->close();
    }
    
}else{
    highlight_file(__FILE__);
}

?>
</body>
<!-- flag in id = 1000 -->
</html>

大部分地方题目都有注释,所以我们来了解一些函数作用

1.isset()函数:根据题目注释我们大概可以知道isset函数就是检测用来检测变量是否存在

ctfshow web由一道题的思路实现通杀

2.intval():这里实际上就用到了intval函数的特性

我们写如下这样一段代码

<?php
	$id=$_GET['id']; //定义一个GET传参的变量
	var_dump($id);   //使用var_dump函数输出这个变量长什么样
	echo "<br />";   //换行,方便区分
	var_dump(intval($id));  //用var_dump函数输出经过intval函数处理以后的变量长什么样
?>

我们传参?id=1000,输出结果如下:

ctfshow web由一道题的思路实现通杀

 我们再传参?id='1000',输出结果如下:

ctfshow web由一道题的思路实现通杀

可以看到:

$id=$_GET['id'] 

我们传参'1000'给变量id,直接输出的还是'1000';

但是:

var_dump=intval($id)

可以发现经过intval函数处理后输出的就是int(0)

我把代码更改一下
 

<?php
	$id=$_GET['id'];
	var_dump($id);
	echo "<br />";
	var_dump(intval($id));
	if(intval($id)>999)
	{
		echo "true";
	}
	else 
	{
		echo "false";
	}
	
?>

拓展:这个地方我拓展一下知识

intval函数处理的时候,如果

1.传参里面有字符的时候,函数会直接返回0

ctfshow web由一道题的思路实现通杀

2.当传参里面前面是字符后面是数字,返回的也是0,例如:abc123

ctfshow web由一道题的思路实现通杀

3.当传参前面是数字后面是字符的时候,返回前面的数字而后面的字符置0

 

ctfshow web由一道题的思路实现通杀 解法一:根据这个特性再加上题目的提示 flag in id = 1000

我们尝试构造payload:

?id='1000'

顺利得到flag:

ctfshow web由一道题的思路实现通杀

ctfshow{85577894-0cb1-4d0d-9fa2-f7f1b03d77c2}

 如果这里我们直接使用?id=1000的话,那么ctfshow web由一道题的思路实现通杀

根据题目的这句话就会直接返回错误

 解法二: 既然题目已经出现了回显,那么根据回显提示我们是否可以尝试使用SQL注入来找到flag呢?

那我们尝试构造:

?id=100 or id=1000

ctfshow web由一道题的思路实现通杀

返回后我们发现这样也可以获得flag,这是因为,我们输入id=100 or id=1000的时候,if语句中首先是100和999进行比较,然后查询id=1000里面的东西,实现了绕过

解法三:  搜索了一些大佬的文章,我发现还有一种构造方法,那么就顺便学习一下:

我们可以构造取反:

?id=~~1000

我来讲讲原理:

假设我们拿10来举例:

10的二进制表示是:1010

化成32位二进制就是:0000 0000 0000 0000 0000 0000 0000 1010

按位取反就是:           1111 1111 1111 1111 1111 1111 1111 0101

然后我们知道第一位的0/1表示的是正负,所以有:

 -111 1111 1111 1111 1111 1111 1111 0101

负数是用补码表示的,然后补码是原码取反加1,所以我们把补码减1再取反

-111 1111 1111 1111 1111 1111 1111 0100

-000 0000 0000 0000 0000 0000 0000 1011

计算得到:-11

这个地方我们要取反两次,因为最后要查询的数据是1000里面的数,所以经过两次取反后还是1000,但是这样做可以绕过前面的限制

解法四:

我们还可以构造payload:

?id=100%2B900

我们知道数据库是可以做计算的,所以我们构造100+900,但是要注意不能直接注入+号,因为在url里面+号会直接被PHP解析成空格

题目二:web2 

第二题和第一题还是一样,不同的地方在于加了一个正则过滤

    if(preg_match("/or|\+/i",$id)){
            die("id error");
    }

 这个正则表达式过滤了or 和 + ;后面的符号i标记这是一个大小写不敏感的搜索

有不理解的小伙伴建议可以看看正则表达式的知识

正则表达式 – 匹配规则 | 菜鸟教程

这么一看上面的第二种解法就不能用了,但是其他解法照用不误,只要不出现被过滤的关键字就可以,而且上面的第四种解法我们把+号改成*号照样可以绕过

构造payload:

?id='1000'

ctfshow web由一道题的思路实现通杀

 

题目三:web 3

    if(preg_match("/or|\-|\\|\*|\<|\>|\!|x|hex|\+/i",$id)){
            die("id error");
    }

好家伙,这次过滤的更多,实际上这里过滤掉了or 和+ - * / !,但是,我们构造payload:

?id='1000'

照样可以使用

ctfshow web由一道题的思路实现通杀

 

题目四:web4

    if(preg_match("/or|\-|\\\|\/|\\*|\<|\>|\!|x|hex|\(|\)|\+|select/i",$id)){
            die("id error");
    }

这次又过滤了更多,但是不影响payload:

?id='1000'

ctfshow web由一道题的思路实现通杀

 

题目五:web5

    if(preg_match("/\'|\"|or|\||\-|\\\|\/|\\*|\<|\>|\!|x|hex|\(|\)|\+|select/i",$id)){
            die("id error");
    }

这一次终于把' "过滤了,那么我们试试取反:

?id=~~1000

 

ctfshow web由一道题的思路实现通杀

成功绕过

题目六:web6

    if(preg_match("/\'|\"|or|\||\-|\\\|\/|\\*|\<|\>|\^|\!|x|hex|\(|\)|\+|select/i",$id)){
            die("id error");
    }

 构造payload:

?id=~~1000

ctfshow web由一道题的思路实现通杀

 

题目七:web7

    if(preg_match("/\'|\"|or|\||\-|\\\|\/|\\*|\<|\>|\^|\!|\~|x|hex|\(|\)|\+|select/i",$id)){
            die("id error");
    }

哦豁,我们发现这里把~符号过滤了,看来只能想其他方法了,思考了一下,根据前面我们使用二进制取反实现绕过,那么我们能不能直接使用二进制表示1000从而实现绕过呢?

构造payload:

?id=1111101000

ctfshow web由一道题的思路实现通杀

发现不行,想了一下,加上标识符:

?id=0b1111101000

 ctfshow web由一道题的思路实现通杀

 绕过成功

有兴趣的小伙伴可以看看这篇文章

CTFSHOW 萌新计划 web 1-8_羽的博客-CSDN博客_ctfshow萌新web

上一篇:企业证书系列之Citrix


下一篇:前端系列——vue2+高德地图web端开发(poi搜索两种方式)