apacheunomi漏洞介绍及代码分析

Posted kali_Ma

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了apacheunomi漏洞介绍及代码分析相关的知识,希望对你有一定的参考价值。

Apache Unomi介绍

Apache Unomi具有隐私管理、用户/事件/目标跟踪、报告、访客资料管理、细分、角色、A/B测试等功能,可以作为Web CMS、个性化服务、原生移动应用的分析服务、具有分段功能的集中配置文件管理系统、授权管理中心。

漏洞介绍

CVE-2020-13942是CVE-2020-11975的绕过
该漏洞描述的是Unomi针对MVEL表达式(和OGNL表达式)的未进行敏感函数的过滤,直接解析,导致任意代码执行

本文主要对MVEL这条利用链做代码层面的分析

poc请求包

漏洞利用时相关的Poc请求包如下,后续代码分析会涉及到

【一>所有资源获取<一】
1、200份很多已经买不到的绝版电子书
2、30G安全大厂内部的视频资料
3、100份src文档
4、常见安全面试题
5、ctf大赛经典题目解析
6、全套工具包
7、应急响应笔记
8、网络安全学习路线

分析思路

MVEL表达式解析的模式有两种,分别是

  • 解释模式MVEL.eval(expression, vars)
  • 编译模式MVEL.compileExpression(expression) + MVEL.executeExpression(compiled, vars)

具体可以参考:MVEL解析表达式

倒推分析

通过在源码中搜索关键字script::MVEL.executeExpression(可以初步定位出现问题的代码位于源码的如下位置

unomi-unomi-root-1.5.1\\persistence-elasticsearch\\core\\src\\main\\java\\org\\apache\\unomi\\persistence\\elasticsearch\\conditions\\ConditionContextHelper.java

我们构造的恶意表达式就是通过这条代码进行解析从而导致RCE的

基于此方法向上回溯,找调用它的地方

继续向上回溯

看到condition.getParameterValues()基本可以确定我们的思路是正确的

接下来主要找入口点,即往/context.json这个路径下发送数据是如何一步一步到ConditionContextHelper#getContextualCondition()

向上回溯getContextualCondition()有三处调用到

几个方法分别是buildFilter()count()eval(),因为看到poc里有关键字filter,所以先跟入buildFilter(),看看是不是从这里进来的

接着向上回溯,看buildFilter()的调用位置

最终回溯到的位置(即入口位置)位于ElasticSearchPersistenceServiceImpl重写的excute()方法中

看完buildFilter(),然后接着看eval()count()方法作用不大,忽略)
eval()最终回溯到的位置(即入口位置)位于ElasticSearchPersistenceServiceImpl重写的testMatch()方法中

然后只需要找出调用如下两个方法的位置就可以找到完整的调用链

ElasticSearchPersistenceServiceImpl#excute()
ElasticSearchPersistenceServiceImpl#testMatch()

正推分析

接下来我开始从请求的入口处开始进行分析
在docker环境中找到了如下jar包

unomi-wab-1.5.1.jar

这个jar包包含了处理web的逻辑,其对应着的源码包是

unomi-unomi-root-1.5.1/wab

里面的contextServlet.class对应着我们请求的/context.json
该类继承了HttpServlet类,且无doGet()doPost()方法,但是有用于处理请求的service()方法

注:service()此方法是接收http-request请求的原始方法,请求会发送到这个方法然后才会向doGet()doPost()分发

这里的contextRequest就是我们poc传入的body(可以根据getSessionId等方法以及响应数据判断出来)

接着这里会将contextRequest作为参数传入handleRequest()

接着看到355行

在执行getFilters()后,拿到的应该是如下部分

之后进入for循环,比较重要的是有一个personalizedContent对象,这个类的数据结构如下:

正好对应着我们上图传入的内容

然后跟进359行的personalizationService.filter()方法

注:personalizationService是interface,我们知道,接口不可以实例化。但是接口对象可以指向它的实现类对象。

所以这里的filter()应该是其Impl类的filter()方法,所以我们跟进位于源码包

unomi-unomi-root-1.5.1\\services\\src\\main\\java\\org\\apache\\unomi\\services\\impl\\profiles\\ProfileServiceImpl.java

filter()方法

然后跟进67行的profileService.matchCondition()也在同一个源码包下

在781行出现了最关键的persistenceService.testMatch(),而上半段分析的ElasticSearchPersistenceServiceImpl正好是persistenceService唯一的实现类

至此,整个调用链已经打通,我们整理一下调用链

调用链整理

org.apache.unomi.web.ContextServlet#service() -> org.apache.unomi.web.ContextServlet#handleRequest() -> org.apache.unomi.services.impl.personalization.PersonalizationServiceImpl#filter() -> org.apache.unomi.services.impl.profiles.ProfileServiceImpl#matchCondition() -> org.apache.unomi.persistence.elasticsearch.ElasticSearchPersistenceServiceImpl#testMatch() -> org.apache.unomi.persistence.elasticsearch.conditions.ConditionEvaluatorDispatcher#eval() -> org.apache.unomi.persistence.elasticsearch.conditions.ConditionContextHelper#getContextualCondition() -> org.apache.unomi.persistence.elasticsearch.conditions.ConditionContextHelper#parseParameter() -> org.apache.unomi.persistence.elasticsearch.conditions.ConditionContextHelper#executeScript()

最终被executeScript()

MVEL.executeExpression(mvelExpressions.get(script), context);

解析执行

以上是关于apacheunomi漏洞介绍及代码分析的主要内容,如果未能解决你的问题,请参考以下文章

安全测试 web安全测试 常规安全漏洞 可能存在SQL和JS注入漏洞场景分析。为什么自己没有找到漏洞,哪么可能存在漏洞场景是?SQL注入漏洞修复 JS注入漏洞修复 漏洞存在场景分析和修复示例(代码片段

SMB远程代码执行漏洞(CVE-2020-0796)分析验证及加固

齐博分类系统漏洞分析

静态代码检测工具Wukong对log4J中的漏洞检测分析及漏洞修复

Redis CSRF漏洞分析及云Redis安全措施介绍

Log4j2高危漏洞CNVD-2021-95914复现及分析