CTFCTF学习HGAME-WP
fulian23Computer cleaner

先查看端口占用,发现本地开启了80端口,但是页面里并没有什么信息

在网站目录下的upload日志文件中找到了攻击者使用一句话木马查看了~/Documents/flag_part3,里面是第三部分的flag

在攻击者上传的shell.php中找到了第一部分的flag
由于题目中说第二部分是需要对攻击者进行简单溯源,所以想到攻击者ip,在日志中找到攻击者的ip

访问找到第二部分的flag
1
| hgame{y0u_hav3_cleaned_th3_c0mput3r!}
|
Level 24 Pacman

找到初始分数,直接就改成10000分

base64解码后是
1
| haeu4epca_4trgm{_r_amnmse}
|
由于所有的字符都有,所以猜测栅栏密码

1
| hgame{u_4re_pacman_m4ster}
|
Level 69 MysteryMessageBoard

打开猜测要爆破shallot的密码

爆破出密码888888
根据源码,用户访问/admin后admin会访问/也就是留言板
所以可以用xss攻击,让admin访问到/flag返回

在xss平台自定义执行代码
访问/admin目录让admin查看留言板

成功带着flag访问目标地址
1
| hgame{W0w_y0u_5r4_9o0d_4t_xss}
|
Level 47 BandBomb
这题一开始以为是重命名文件能注入命令,做了好久没做出来,之后学长提示是ejs的模板注入
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| app.post('/rename', (req, res) => { const { oldName, newName } = req.body; const oldPath = path.join(__dirname, 'uploads', oldName); const newPath = path.join(__dirname, 'uploads', newName);
if (!oldName || !newName) { return res.status(400).json({ error: '请提供旧文件名和新文件名' }); }
fs.rename(oldPath, newPath, (err) => { if (err) { return res.status(500).json({ error: '重命名失败: ' + err.message }); } res.json({ message: '文件重命名成功' }); }); });
|
漏洞来自于在重命名文件时没有检查./符号导致目录穿越漏洞

将mortis页面移动到public目录下,访问static目录下载
得到mortis.ejs,添加<%= Object.getOwnPropertyNames(this);%>查看当前对象的所有属性,看看有什么可以利用的函数

可以找到有process这个全局对象,由于ejs是运行在浏览器环境里,不能执行系统命令,所以选择查看系统变量
注入<%=JSON.stringify(process.env)%>查看所有环境变量

得到flag:
1
| hgame{AVe_mUJIcA_hAS-6ROK3N_uP-but-W3-HavE_umlTaK116}
|
Computer cleaner plus

查看进程发现ps命令没有权限执行

由于这个文件所有者为root,为当前用户,所以直接添加可执行权限

添加完后执行ps发现报错,得到木马文件名字,也可知/bin/ps不是二进制文件,而是一个脚本
HoneyPot
分析代码,找到命令注入漏洞
1 2 3 4 5 6 7 8 9
| command := fmt.Sprintf("/usr/local/bin/mysqldump -h %s -u %s -p%s %s |/usr/local/bin/mysql -h 127.0.0.1 -u %s -p%s %s", config.RemoteHost, config.RemoteUsername, config.RemotePassword, config.RemoteDatabase, localConfig.Username, localConfig.Password, config.LocalDatabase, )
|
这里直接拼接命令,导致命令注入
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
| config.RemoteHost = sanitizeInput(config.RemoteHost) config.RemoteUsername = sanitizeInput(config.RemoteUsername) config.RemoteDatabase = sanitizeInput(config.RemoteDatabase) config.LocalDatabase = sanitizeInput(config.LocalDatabase)
...
func validateImportConfig(config ImportConfig) error { if config.RemoteHost == "" || config.RemoteUsername == "" || config.RemoteDatabase == "" || config.LocalDatabase == "" { return fmt.Errorf("missing required fields") }
if match, _ := regexp.MatchString(`^[a-zA-Z0-9\.\-]+$`, config.RemoteHost); !match { return fmt.Errorf("invalid remote host") }
if match, _ := regexp.MatchString(`^[a-zA-Z0-9_]+$`, config.RemoteUsername); !match { return fmt.Errorf("invalid remote username") }
if match, _ := regexp.MatchString(`^[a-zA-Z0-9_]+$`, config.RemoteDatabase); !match { return fmt.Errorf("invalid remote database name") }
if match, _ := regexp.MatchString(`^[a-zA-Z0-9_]+$`, config.LocalDatabase); !match { return fmt.Errorf("invalid local database name") }
return nil }
|
这两处校验中都没有对RemotePassword处理,所以在RemotePassword处注入命令/writeflag,写入flag

访问/flag页面,即可得到flag
1
| hgame{8b7c14d6-be92-66b2-97c2-ab20e9417d9c}
|