一道有趣的go语言CTF
xiaoqiuxx 发表于 江西 CTF 1556浏览 · 2024-02-26 11:49

前言

这道题做起来并不是很难,但是因为go的话出的也不多,里面涉及的点也是比较有意思的,所以写一下。

路由分析

这个题目是gin+gorm写的一个web服务
路由主要为以下几个

router.GET("/user", UserHandler)   获取用户信息
router.POST("/login", LoginHandler)  登录
router.POST("/upload", cookieCheckMiddleware(), UploadHandler)  上传文件需要登录
router.POST("/move", IpSecurityCheck(), SubmitMoveHandler)   移动文件检测ip
router.POST("/download", cookieCheckMiddleware(), DownloadHandler)  下载文件

upload、move、download是存在中间件进行校验的。
做题的时候肯定是需要找重点去看的,这里因为代码量并不多,所以可以仔细看看。

gorm问题

首先看/user这个路由
具体代码如下

p牛曾经在星球里面说过这个问题,由于Go这门语言本身对于“零值”的设计,他是无法区分某个结构体中某个字段是否有被赋值过。如下代码,如果id参数不传值的话,这条SQL语句直接帮我们把where条件去掉了,这里实际上就产生了安全问题。

就是这段代码,如果token不传值的话,实际上执行sql语句的时候token也是不会在where条件内的,

所以直接查询就可以获得表的第一条数据了。

中间件问题

接下来进入重点,也是解决题目的地方。
在这个函数内是存在命令执行的功能点的,而且这里是采取拼接处理,不存在关键字过滤等防护。如果可以调用到这个函数的话就可以进行RCE了。

而move路由的话就是调用的该函数进行处理,那么只需要访问move路由然后传入文件名即可。但是这个路由是存在一个中间件防护的。

这个中间件会对IP进行检查,但是ip又不能伪造,那怎么办呢
仔细看这段代码其实是存在逻辑问题的,gin的中间件其实有点类似java的filter,放行的话就需要写c.Next(),拦截就是c.Abort(),但是这里是没有c.Abort()的,所以就出问题了,然后这里有一个return,但是代码还是继续往后执行了,因为没有被拦截。所以这个中间件其实是没有起到防护作用。


这样才是正确写法。
所以解题思路很明确了,直接传值即可,因为是无回显,这里借助dnslog平台进行解题

结语

在进行代码审计的时候,我们也需要重点关注一些代码逻辑产生的问题,这个问题有点像以前出现很多的php系统相关的重装漏洞,做了判断但是并没有exit()程序,导致代码逻辑还是在往下跑。

1 条评论
某人
表情
可输入 255