前言
文章中涉及的敏感信息均已做打码处理,文章仅做经验分享用途,切勿当真,未授权的攻击属于非法行为!文章中敏感信息均已做多层打码处理。传播、利用本文章所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,作者不为此承担任何责任,一旦造成后果请自行承担
又一个前台未授权漏洞爆了出来,而且纵观 Smartbi 的历史漏洞,都是未授权漏洞,看到各个乙方公司的公众号都发了这个漏洞
但是没有一个是有 POC 的
那咋办嘛,只能自己分析咯
环境搭建
没有源码的可以去访问官网
直接申请使用,可以免费体验一个月,不过分析这个漏洞完全够用了
下载下来启动
启动成功后访问环境即可,这个就很爽,无脑起飞,如果需要调试的话,可以在启动里面加参数,不过也不需要
启动后访问 config.jsp
配置后检测一下成功后就去访问 index
登录后如图,代表访问成功
但是这个是最新版本的,我们只需要把去加载老版本的 patch,把新的给替代了就 ok
在系统监控那里
分析思路
当然没有思路,只能从几家的漏洞描述+补丁分析了
先去搞一手补丁
就是这个最新的补丁,早就修复了,但是现在才爆出来
但是这种补丁一般都会加密的
读不了一点
因为打补丁就是使用的这个文件,所以肯定有解密的流程,去寻找一下
参考Smartbi 解密补丁信息 - 火线 Zone-安全攻防社区
解密得到一个 zip 文件,解压后得到明文的 patch 文件和一些更新后的 class 文件
然后我们得到解密的结果
然后加上我们的 class 文件,大概都去看一下
然后加上乙方的一些描述,之后定位到代码
漏洞的根本原因在于系统权限验证机制存在缺陷,攻击者可以通过特定的资源 ID 绕过身份验证,获取公共用户权限。
然后这时候因为对这个系统不了解,直接去搜索
参考https://wiki.smartbi.com.cn/pages/viewpage.action?smt_poid=43&pageId=51942608
然后找到了资源 ID 就是这玩意
http://localhost:18080/smartbi/vision/createresource.jsp?restype=themewizard&resid=THEME.demo2019.CSAC
结合我们的补丁
发现漏洞应该是出现在 share.jsp 文件了
代码中也接收 resid 这个参数
然后尝试能不能未授权访问这个接口
先退出登录
然后访问接口
访问成功了
然后看到
漏洞分析与利用
未授权获取 cookie
然后根据漏洞的描述,有默认的 id,可以返回 cookie,于是接下来的任务就是去寻找 resid
但是这个数据库是内置的,表的结构我们都不太清楚
所以需要先去尝试插入一个 id,看看到哪里去了
成功后查看属性
得到 ID
然后去数据库找这个 ID 是在哪里
发现了这个字段,然后就把其中的 resid 全部提取出来,然后去遍历
遍历后无一例外显示全是
找不到分享记录
如果不熟悉细怎么办?
当然是去翻我们的官方文档了
然后来到界面是空的,反应过来应该是每个资源都可以分享,于是回到自己创建的资源
然后点击分享
这里我没有找到默认的资源 ID
分享成功后我再次使用我的接口去访问
访问成功后我们拿着返回的 cookie 后就可以去访问接口了
代码原理分析
为什么这个 cookie 有效果呢
可以看到只要我们成功访问资源,就会把当前用户切换为 public 用户
跟进 autoLoginByPublicUser
public boolean autoLoginByPublicUser() {
String userName = "public";
if (this.getUserByName(userName) == null) {
return false;
} else {
if (this.stateModule.getSystemId() == null) {
this.stateModule.setSystemId("DEFAULT_SYS");
}
IUser serviceUser = this.getUserById("SERVICE");
if (serviceUser == null) {
throw (new SmartbiException(UserManagerErrorCode.NOT_EXIST_USER)).setDetail("SERVICE");
} else if (this.stateModule.getCurrentUser() != null && this.stateModule.getCurrentUser().getId() == "PUBLIC") {
return true;
} else {
this.stateModule.setCurrentUser(serviceUser);
this.stateModule.removeSessionAttribute("SMARTBIX_STATE");
return this.switchUser(userName);
}
}
}
这里就直接设定用户了,然后跟进 setCurrentUser
public void setCurrentUser(IUser user) {
this.getState().setUser(user);
this.setSessionAttribute("user", user == null ? null : user.getName());
this.updateSessionLocale(user);
}
很明显了
private void updateSessionLocale(IUser user) {
String key = "BOF_Locale";
HttpServletRequest req = this.getRequest();
if (user != null && req != null) {
if (CommonUtil.getInstance().getLocaleByRequestParameter(req) == null && CommonUtil.getInstance().getLocaleByCookie(req) == null) {
String userLocale = null;
try {
userLocale = CommonUtil.getConfigValue("USER_LOCALE");
} catch (Exception var6) {
}
if (!StringUtil.isNullOrEmpty(userLocale)) {
Locale locale = CommonUtil.getLocaleType(userLocale);
if (locale != null && !locale.toString().equals(this.getSessionAttribute(key))) {
this.setSessionAttribute(key, locale.toString());
}
}
}
}
}
这里会直接设置我们有效的 cookie
这就是我们有效的 cookie 呢
后渗透利用
回显构造
当然如果目标不出网怎么办?
所以就需要后渗透的利用了,直接去对应后台的地方
第一想法就是利用 scanner 回显
就是直接把我们命令执行的输出然后放入 scanner 对象,最后输出但是发现回显的话只会显示这种提示信息,于是想到了使用 header 回显
但是个人觉得这样太麻烦了,思考了一下,我直接让这个页面报错不就完事了吗可以发现回显虽然没有我们的命令执行结果
但是思考一个问题,如果我们把这个 asdsd 换成我们的命令执行结果不就可以回显了吗
注入内存马
当然一个简单的回显并不如内存马方便了,这里直接打上渗透测试最爱的内存马
借助 spring 的工具类的反射功能,首先获取到我们的关键的类,也就是当前线程的 loader,准备去加载我们的字节码,但是字节码传入的话是二进制,所以我们需要使用 base64,方便传入
最后
文章中涉及的敏感信息均已做打码处理,文章仅做经验分享用途,切勿当真,未授权的攻击属于非法行为!文章中敏感信息均已做多层打码处理。传播、利用本文章所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,作者不为此承担任何责任,一旦造成后果请自行承担
2918

被折叠的 条评论
为什么被折叠?



