-
-
[原创] 第三题 统一门派非预期题解
-
发表于: 2021-5-13 15:59 5720
-
应该是非预期解...在找到flag后虽然尽力去找正常解, 但并没找出来, 只能说说在找解的过程中发现的信息
首先说非预期解
挂好burp代理访问题目地址, 在一番探索后发现请求了 /static/js/2.js
这个文件, 审计了一番之后想着是不是还有1.js, 3.js什么的, 试了下真有, 然后就...
然后说说发现的信息
首先从登录页面可以发现是ruoyi管理系统, 而且下面版权信息只到2020年, gitee上找到的源码2021年还在更新, 所以使用的应该是旧版. 一个思路是找2021年它修复了哪些bug, 看了下主要修复是涉及fastjson, mybatis等的反序列化相关漏洞, 后来发现6379端口有个redis, 有可能是redis缓存+反序列化, 但是这个方式最后也没试出来.
从源码可以审计出除了登录页面还有其它几个可以访问的地方:
/dev-api/druid/index.html
是alibaba的druid系统, 但是ruoyi-vue不使用session作为登录凭证所以无法从session监控偷到cookies, sql监控也只记录了执行的模板, 所以最后发现这里好像除了uri监控能看看其它选手都在干啥以外没其他用处...
/dev-api/swagger-ui.html
这里是一个api文档页面, 但是里面描述的一系列/test/user
下的api只能登陆后才能访问, 从这里也没找到其它更多信息.
/dev-api/common/download[/resource]
和/profile/**
这里的接口即使是2020年的旧版, 存在过的任意文件读取漏洞也已经被修复过. checkAllowDownload禁止了..
且只允许一些特定扩展名, RuoYiConfig.getProfile()
默认返回/home/RuoYi/UploadPath
,访问/dev-api/profile/*
也是访问这个目录下的文件, 在不知道这个目录下有什么文件的情况下没能获得更多的信息.
在翻redis时发现有时候存在login_token, 通过审计ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/TokenService.java
发现客户端验证方式是通过jwt信息附带在请求头中, 请求头以及jwt密钥配置在ruoyi-admin/src/main/resources/application.yml
里, 算法是HS512.
尝试使用如下代码伪造jwt:
放在请求头里:
Authorization Bearer eyJ0eXA...
然并卵, 或许并没有使用默认的jwt secret, 这样的话这个思路也不正确.
分析到这里还有两种方法, 一是爆破用户密码, 在能访问redis的情况下能直接拿到验证码. 二是反序列化漏洞.
然而它们建立在能够访问redis的基础上, 此时redis已经被多人运动玩坏了...
想着flag也已经拿到了就到此为止吧, 等着看看其他解题思路(绝对不是因为我懒)
/
*
*
*
获取用户身份信息
*
*
@
return
用户信息
*
/
public LoginUser getLoginUser(HttpServletRequest request)
{
/
/
获取请求携带的令牌
String token
=
getToken(request);
if
(StringUtils.isNotEmpty(token))
{
Claims claims
=
parseToken(token);
/
/
解析对应的权限以及用户信息
String uuid
=
(String) claims.get(Constants.LOGIN_USER_KEY);
/
/
"login_user_key"
String userKey
=
getTokenKey(uuid);
LoginUser user
=
redisCache.getCacheObject(userKey);
return
user;
}
return
null;
}
/
*
*
*
获取请求token
*
*
@param request
*
@
return
token
*
/
private String getToken(HttpServletRequest request)
{
String token
=
request.getHeader(header);
/
/
"Authorization"
if
(StringUtils.isNotEmpty(token) && token.startsWith(Constants.TOKEN_PREFIX))
{
token
=
token.replace(Constants.TOKEN_PREFIX, "
"); // "
Bearer "
}
return
token;
}
private String getTokenKey(String uuid)
{
return
Constants.LOGIN_TOKEN_KEY
+
uuid;
}
/
*
*
*
从令牌中获取数据声明
*
*
@param token 令牌
*
@
return
数据声明
*
/
private Claims parseToken(String token)
{
return
Jwts.parser()
.setSigningKey(secret)
.parseClaimsJws(token)
.getBody();
}
/
*
*
*
获取用户身份信息
*
*
@
return
用户信息
*
/
public LoginUser getLoginUser(HttpServletRequest request)
{
/
/
获取请求携带的令牌
String token
=
getToken(request);
if
(StringUtils.isNotEmpty(token))
{
Claims claims
=
parseToken(token);
/
/
解析对应的权限以及用户信息
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!