昨天打了第四届上海市大学生网络安全大赛,这里记录下四道web的解题过程。

web1

题目描述:what are you doing?
这题说实话比较脑洞。。
进来之后,页面没什么东西,注释有提示robots.txtflag.php应该是放flag的,直接看source.php有什么还是注释有提示,根据注释,添加header:X-Client-IP:127.0.0.1以及post admin=1就可以看到下一步关键提示按照提示post过去给了一个图片的链接,访问一下发现是没东西的一开始以为是要拼速度啥的,写了脚本,发现不是。回头再来看有没有被遗漏的点。发现url这个参数的解析符合parse_url的特征可以看这篇文章parse_url的特性讲解。从而想到有可能是SSRF,尝试一波这里要想一下回显可能在哪里,自然地想到很可能就是在图片那了。访问图片,发现确实打到了东西然后直接构造url=file://@www.ichunqiu.com/var/www/html/flag.php,再访问图片即可读到flag。

web2

题目描述:Can you hack me?
进来之后同样是一个没东西的页面这次注释也没东西,那么直接扫一波目录,发现有.index.php.swp,下载下来,用vim -r复原所有代码如下:

<?php
error_reporting(0);
class come{    
    private $method;
    private $args;
    function __construct($method, $args) {
        $this->method = $method;
        $this->args = $args;
    }
    function __wakeup(){
        foreach($this->args as $k => $v) {
            $this->args[$k] = $this->waf(trim($v));
        }
    }
    function waf($str){
        $str=preg_replace("/[<>*;|?\n ]/","",$str);
        $str=str_replace('flag','',$str);
        return $str;
    }           
    function echo($host){
        system("echo $host");
    }
    function __destruct(){
        if (in_array($this->method, array("echo"))) {
            call_user_func_array(array($this, $this->method), $this->args);
        }
    } 

}

$first='hi';
$var='var';
$bbb='bbb';
$ccc='ccc';
$i=1;
foreach($_GET as $key => $value) {
        if($i===1)
        {
            $i++;
            $$key = $value;
        }
        else{break;}
}
if($first==="doller")
{
    @parse_str($_GET['a']);
if($var==='give'){
    if($bbb==='me'){
        if($ccc==='flag'){
            echo "<br>welcome</br>";
            $come=@$_POST['come'];
            unserialize($come);
        }
    }
    else{
        echo "<br>think about it</br>";
    }
}
else{
    echo "no";
}
}
else{
    echo "can you hack me?";
}
?>

前面是一个类的声明,然后看这个部分它只能进行一次变量覆盖,我们看后面的代码,有一个parse_str,那时候再进行其它变量的覆盖也不迟,所以这里首先处理$first,传入first=doller,然后是一个parse_str,只需要把想改变值的变量传进a就可以了,注意&要进行url编码,最终到达内层的payloadfirst=doller&a=var=give%26bbb=me%26ccc=flag然后就是一个反序列化,我们来看看这个类首先可以看到,__wakeup()里面对$args进行了一个foreach的操作,每个$v都要进行waf(trim($v))的处理,这里很明显,$args得是一个数组。
然后再看,waf函数禁用了一些东西,但是好像本来就没打算用得上,还把flag替换为空,简单双写即可绕过。
再看echo函数,调用了system(),而且参数可控,明显可以命令注入。
最后看__destruct,这里限定了传进去的$method只能是echo,然后用echo函数对$args数组进行处理。
所以,我们可以这么构造然后传入再构造一次,读flag即可

web3

题目描述:GOOD JOB
代码审计题

<?php
    //error_reporting(0);
    //$dir=md5("icq" . $_SERVER['REMOTE_ADDR']);
    $dir=md5("icq");
    $sandbox = '/var/sandbox/' . $dir;
    @mkdir($sandbox);
    @chdir($sandbox);

    if($_FILES['file']['name']){
        $filename = !empty($_POST['file']) ? $_POST['file'] : $_FILES['file']['name'];
        if (!is_array($filename)) {
            $filename = explode('.', $filename);
        }
        $ext = end($filename);
        if($ext==$filename[count($filename) - 1]){
            die("emmmm...");
        }
        $new_name = (string)rand(100,999).".".$ext;
        move_uploaded_file($_FILES['file']['tmp_name'],$new_name);
        $_ = $_POST['hehe'];
        if(@substr(file($_)[0],0,6)==='@<?php' && strpos($_,$new_name)===false){
            include($_);
        }
        unlink($new_name);
    }
    else{
        highlight_file(__FILE__);
    }

这题刚拿到手,还以为是今年HITCON的one-line-php-challenge的升级版,吓得我都打开了各种wp待命,后面仔细看了才发现其实没啥关系。首先我们需要绕过这个这个东西,记性好的一秒钟就想到网鼎杯的那道上传题了,这里也一样,用数组即可绕过然后再看下面的部分这两行代码首先把文件名拼接,然后上传,这里通过构造拼接的文件名为../../../../../../tmp/comrade.php就可以把文件传到/tmp目录下。再看下面这里首先限定了上传的文件开头6位必须是@<?php,我们知道这文件内容现在是完全可控的,并没有什么实现难度,然后要求$_中不能有$new_name,这个也没什么难度。然后就include($_)
我们知道,可以把文件传到/tmp目录下,然后这里$_又是可控的,事情就变得很简单了。像这样构造数据包然后,读flag。

web4

题目描述:GOOD LUCK.

SQL注入

进来之后有一个id输入框,还有个登录框第一时间测测SQL注入,发现id是存在注入的。id=sd' or 1#:id=sd' or 0#:这里有个值得注意的地方,就是这句$content=str_replace($value,"",$content),很明显它在提示我们,后台很有可能把某些关键词替换为空了。fuzz一下,发现load_fileunioninformation_schema.???(手动测的)系列都被ban了想了一下,觉得首先要找到它把什么替换为空了才能突破。进行了漫长的测试后,发现fromselect都被替换为空。id=sd' or (selselectect 1)#:id=sd' or (selselectect 1 fromfromfrom)#:知道了这两个词被替换为空,那么能不能把他们插入到被ban的关键词中,从而实现绕过呢?id=unifromon:没有报get out hacker!!,说明是可以的。然后进行注入,发现这是令人愉悦的有回显的注入(其实是后面才想起来,一开始完全就是当布尔盲注做的-_-0)
id=sd' unifromon selselectect (seselectlect database()),2#:id=sd' unifromon selselectect (seselectlect group_concat(table_name)frfromom information_schemafrom.tables where table_schema='web'),2#:id=sd' unifromon selselectect (seselectlect group_concat(column_name)frfromom information_schemafrom.columns where table_name='user' and table_schema='web'),2#:id=sd' unifromon selselectect (seselectlect group_concat(username,':',password)frfromom web.user),2#:注出admin的密码的md5,拿去解密然后登录

"文件上传"

登录进来之后看到一个文件上传的表单尝试传点东西,发现不能直接传php,看看数据包发现无论传过去的文件名是什么,后台都会在最后面加个.txt,而且提示说要upload to ./flag.php,而且这是个假的上传,访问返回的链接是没有东西的。这里首先发现,最终的文件名是uploaddirfileField的文件名共同组成的,两者配合可以弄出一个php的后缀。剩下的问题就只有如何去掉这个.txt,第一感觉当然就是截断了,尝试了#,00截断都不行。卡住了好久好久,甚至回到sql注入那里看看能不能load_file读读后台到底是怎么写的,但是不行。最后还是觉得要截断,试了几个常见的,%0a,%09,都不行,实在是没办法了,打算把不可见字符都试一遍,试到%02的时候,成了。??

源链接

Hacking more

...