【代码审计】一次权限绕过思路
流程分析
某次朋友突然丢给我一个系统,让我帮忙看看能不能找点漏洞打进去。通过指纹在fofa一看是一个几百站点的通用。后来经过我一顿摸索找到了源码。是采用spring开发,鉴权采用的是jwt方法。因为目标是要进去所以关注点变成了鉴权的机制,和未授权的接口。
因为采用的是jwt鉴权,所以很自然的想到了硬编码。果然采用了硬编码,本来到了这一步本就该结束了吧。但是并不是。
因为鉴权的机制并没有结束,像我平时遇到的项目好多都是采用jwt+redis的方法进行登录验证,前端返回的token只是redis的键。
虽然这个是采用jwt认证,但是jwt认证后会继续获取jwt中的一个token。拿着token去查询数据库。相关的代码我整理了关键代码的一个例子如下:
String token = request.getHeader("token");
JWT jwt = JwtUtil.readBody(token);
String pwdMd5 = (String) jwt.getPayload("pwdMd5");
UserModel userModel = new UserModel();
userModel.setPassword(pwdMd5);
// 后续就是通过userModel通过orm查询数据库。
所以问题就变成了如果绕过这段检测。
其实也很简单,上面的逻辑就是获取token中的一个值,然后设置到user的对象中,然后利用这个对象去查询数据库中的值。我们能控制的只有pwdMd5这个值。Sql注入是不可能的,成熟的数据库查询框架这方面不存在这个漏洞。
我们可以了解下在Java中各个类型的默认值都是什么。而Strng属于引用类型在java中引用类型的默认值都是null。
byte: 0
short: 0
int: 0
long: 0L
float: 0.0f
double: 0.0d
char: '\u0000'
boolean: false
String: null
所以很明显当我们将pwdMd5的值赋值为null。那么userModel将会是相当于空。在后续使用orm查询数据库时候很自然的就会将where语句给置空了。那么就相当于select * from user。所以很简单的就饶过了这个鉴权机制。
举个例子如下(例子):
鉴权机制很简单的绕过了。后续就是后台一把梭了,因为是运维平台,所以命令服务器啥的都一把嗦了。
其实这个问题在golang中也遇到过。golang中常用的数据中gorm库,我在审计时候就遇到过很多个确实值判断导致最后where语句被置空了的查询。
上面哪个jwt的工具在线链接是(个人感觉不错推荐下):https://jwt.io/