汇总一下konga的代码审计流程
▶️ 代码是javascript写的,基于Sails进行部署开发,所以也是我第一次意义上的审计javascript后端项目
项目地址:GitHub - pantsel/konga: More than just another GUI to Kong Admin API
先上一下历史ISSUE以及PR中提到的问题
1、privilege escalation: Fix priviledged escalation · pantsel/konga@af43bee · GitHub
2、xss vuln: Merge branch ‘fix/xss-vuln’ into next · pantsel/konga@16e36e8 · GitHub
3、multiple registed: Prevent admin users to be registered multiple times via the /register… · pantsel/konga@37fce1c · GitHub
上述三个为公开的漏洞,但是没有CVE编码,外网公开的还有一个Secret的问题,但是其实出现的概率很多,只有没有设置TOKEN_SECRET的时候才会出现密钥泄漏,最后导致可自定义构造JWT进行任意用户登陆,但是感觉用处也比较少
后台nodemailer组件+配置修改->RCE
这一步有点运气,主要是看到dependency-check那边报了组件问题nodemailer在send()函数存在可命令执行的地方,前提是需要覆盖两个参数或者进行原型污染
可以参考来自这篇文章:D^3CTF 8-bit-pub - byc_404’s blog
问题主要是以下代码处:lib/sendmail-transport/index.js,在SendmailTransport类中的send()方法,在发送之前会调用this._spoawn(this.path, args)
,其中const spawn = require('child_process').spawn;
,所以会进行命令执行
this.path以及args是在初始化(new SendmailTransport)的时候进行赋值,也就是说,只要控制了this.path以及args,就可以达成命令执行
可以来看下konga中怎么实现的,有三个关键的文件如下,这三个文件都会调用到邮件来进行发送,三个文件的导出函数都一样,所以这里用其中的一个来讲即可
1 | konga-0.13.0/api/events/node-health-checks.js |
其中关注点为导出函数createTransporter以及notify
createTransporter为创建一个transport,也就是邮件发送的方式,其中transport为可控,也就是我们传进去的参数
可以看到下面的图,当options.sendmail为true的时候,会new一个SendmailTransport,我们这里可以构造transport.settings其中一个参数的值为:sendmail:true
,即可以进入到SendmailTransport的构造方法
其实我们也不难发现,options参数,也就是transport.settings参数也会被带入到SendmailTransport中,也就以为着参数中存在path以及args即可以造成RCE,此处完整payload如下
"settings":{"sendmail":"true","path":"/bin/bash","args":["-c","echo 1 > /tmp/44.txt"]}
当创建好了SendmailTransport的时候,就需要用到发送的函数,在konga中是notify,在notify中会直接调用sendmail函数,也就是在发送邮件的时候会造成RCE
mailer.sendMail()会继续调用到this.transporter.send(),而this.transporter.send()为SendmailTransport.send()
数据包为如下:
当default_transport为smtp或者mailgun的时候,即可以造成RCE,这里有一个比较可惜的一个点,这个default_transport的设置需要管理员,不然普通用户通过api的接口也可以实现RCE
1 | 这里发送邮件有三种方式,当一个node或者api下线或者掉线的时候会发送邮件(node及时发生,api需要经过15分钟),或者当一个用户singup的时候,也会发送邮件,其中api下线或者掉线都可以通过普通用户权限来实现 |
最后给以下完整的流程
先开启其中一个
接着配置邮件
可以抓到包,替换一下payload,替换的是data字段
数据库也被成功写入
设置api或者node下线或者掉线又或者用户注册的时候,即可以实现RCE
下图为成功进行用户注册
成功写入文件
这里要提一下,之前有人提过nodemailer的这个问题,不过是注入邮件,来自如下链接:Command Injection in nodemailer | CVE-2020-7769 | Snyk
官方的修复手法是添加校验发送地址以及接收地址是否存在,所以我更愿意觉得这个spawn()是nodemailer的一个特性,最新一版依旧可以利用
▶️ 思考:是否可以通过原型污染的方式来覆盖settings[0].data.default_transport
的方式来实现低权限用户RCE?
signup接口的crash服务
漏洞原理很简单,也是无意间测试出来的,路径:konga-0.13.0/api/controllers/AuthController.js
在注册的时候会对protocol进行赋值
而protocol的参数又是必须的,路径:konga-0.13.0/api/models/Passport.js
所以会导致当注册的时候不存在参数passports.protocol的时候,会直接带出异常,又因为是在赋值的是时候抛出的异常,还没进入到create()函数中,所以没有进行异常处理,最后导致服务crash掉,直接引用GPT的解释
正常的注册包
删除参数后的注册包
贴一下konga和kong的部署
1 | docker run -d --name kong-database \ |