CG CTF-Web-/x00

前言

这题是很有意思的一题,涉及到了代码审计和PHP的危险函数,而且解题方法不止一种。

方法一

首先还是进行代码审计。

if (isset ($_GET['nctf'])) {
        if (@ereg ("^[1-9]+$", $_GET['nctf']) === FALSE)
            echo '必须输入数字才行';
        else if (strpos ($_GET['nctf'], '#biubiubiu') !== FALSE)   
            die('Flag: '.$flag);
        else
            echo '骚年,继续努力吧啊~';
    }

逻辑是你输入的nctf必须只有数字,但是又要有#biubiubiu。
这时候我们具体查一查ereg()函数。
在这里插入图片描述
了解完函数的用法好像没什么漏洞,但其实是有的。
erep()这个函数有%00截断这个漏洞。遇到%00则默认为字符串的结束。
因此,我们可以构造这样的payload:

?nctf=1%00%23biubiubiu

首先有数字1,然后%00进行了00截断,这样ereg在判断的时候只有1,而没有后面的%23biubiubiu,这样成功绕过。#要写成%23的原因是#是URL中的特殊字符,#是用来指导浏览器动作的,对服务器端完全无用。所以,HTTP请求中不包括#。因此直接传递#,不仅是#本身传递不了,连#后面的也无法传递给nctf。写成%23,再加上URL本身会经过一次解码,就成功的把#biubiubiu传递了进去。因此得到flag.

方法二

ereg的第二个漏洞是,ereg()只能处理字符串的,遇到数组做参数返回NULL。因此如果我们让nctf是一个数组,它会返回NULL。我们再看源代码:

if (isset ($_GET['nctf'])) {
        if (@ereg ("^[1-9]+$", $_GET['nctf']) === FALSE)
            echo '必须输入数字才行';
        else if (strpos ($_GET['nctf'], '#biubiubiu') !== FALSE)   
            die('Flag: '.$flag);
        else
            echo '骚年,继续努力吧啊~';
    }

这里使用的是===。它不像PHP的弱类型比较, == =只要类型不同,也会返回flase。因此NULL===FALSE返回的是FALSE,可以绕过。
再看下面的strpos。strpos()的参数同样不能为数组,否则返回NULL,而判断用的是 != = ,所以这里的条件同样成立。
因此构造这样的payload:

?nctf[]=1

同样会得到flag。不过使用第二种方法,strpos函数会返回一个Warning,因为ereg前面使用了@,但是strpos没有使用@,因此会返回Warning。

后记

00截断是文件上传方面的知识点,因为有段时间没做文件上传的题目了,有些遗忘,看来需要时常温故而知新。
使用数组来绕过对我来说是一个新的姿势。php的手册上关于这些函数遇到数组的时候都没有提到(也可能是我没看到),这样的话对于一些看似不危险的函数,自己以后也应该多留个心眼,是不是存在数组来绕过?这样的话自己以后做题的思维会更加开阔一些。

猜你喜欢

转载自blog.csdn.net/rfrder/article/details/108429914
今日推荐