web

ctfshow大牛杯web_checkin

noob
2021-05-06 / 0 评论 / 223 阅读 / 正在检测是否收录...

很蠢的一次经历,先上源码:

 <?php
error_reporting(0);
include "config.php";
//flag in /

function check_letter($code){
    $letter_blacklist = str_split("abcdefghijklmnopqrstuvwxyz1234567890");
    for ($i = 0; $i < count($letter_blacklist); $i+=2){
        if (preg_match("/".$letter_blacklist[$i]."/i", $code)){
            die("xi nei~");
        }
    }
}

function check_character($code){
    $character_blacklist = array('=','\+','%','_','\)','\(','\*','&','\^','-','\$','#','`','@','!','~','\]','\[','}','{','\'','\"',';',' ','\/','\.','\?',',','<',':','>');
    for ($i = 1; $i < count($character_blacklist); $i+=2){
        if (preg_match("/".$character_blacklist[$i]."/", $code)){
            die("tongtong xi nei~");
        }
    }
}

$dir = 'sandbox/' . md5($_SERVER['REMOTE_ADDR']) . '/';
if (!file_exists($dir)) {
    mkdir($dir);
}
if (isset($_GET["code"])) {
    $code = substr($_GET["code"], 0, 12);
    check_letter($code);
    check_character($code);

    file_put_contents("$dir" . "index.php", "<?php ".$code.$fuxkfile);
    echo $dir;
}else{
    highlight_file(__FILE__);
} 

查看源码可以知道此处的code参数是可控的,然后当时看到file_put_contents()的处理的时候,第一反应是直接将一句话写入index.php,然后文件包含,但是后来看到前面绕过了很多参数,然后后来的尝试也失败了,并且限制了code参数的长度要小于13,所以加上绕过基本无法实现,于是就尝试其他的做法:直接进行命令执行。看到上面的黑名单,这里的for循环实际上是只过滤了其中一半的字符,当时真的没仔细看,大体一过,认为这里是对code进行了一半的检查,然后过滤单数位置的字母数字,后来看到for循环里的blacklist是上面的字母数字的参数,就直接无语了...我是笨b...后面的特殊字符也一样,于是进行命令执行的时候就可以有很多没有被过滤的字符,被放出来的字母和数字有:bdfhjlnprtvxz24680,特殊字符中奇数位的特殊字符被释放出来:=、/、、%、)、^、$、、!等一些,其实到了这里基本上就有思路了,利用nl命令拿flag,payload:?code=?><?=nl%09/`,这里payload的构造是因为首先闭合前面的<?php,然后写入命令并执行,字母里只有nl和pr被放了出来,通配符的原因是在源码中只存在index.php,所以直接写入,然后访问给出的目录获取flag就可以了。
总结:我是笨b。

8

评论 (0)

取消