[置顶]Nexus Repository Manager历史表达式注入漏洞分析

Java表达式注入漏洞危害严重,通常会导致RCE,且在Java框架组件广泛存在。漏洞形成的本质原因是输入外部可控,导致被注入恶意表达式从而导致任意代码执行。Struts,Spring及Elasticsearch均爆出过该类漏洞。我们最近对Nexus Repository Manager(又名NXRM,一款开源的仓库管理应用。)的3个历史表达式注入漏洞进行了调试分析,现记录在此。

CVE-2018-16621

影响版本:

Nexus Repository Manager 3.x OSS / Pro <= 3.14.0

环境搭建:

下载NXRM OSS

https://help.sonatype.com/repomanager3/download/download-archives---repository-manager-3

本文分析调试的版本是3.13.0-01,下载对应的版本,解压,之后./nexus start运行,默认账号密码:admin/admin123;

为了能够让IDE附加调试,在启动脚本nexus-3.13.0-01-mac/nexus-3.13.0-01/bin/nexus里添加参数:

1INSTALL4J_ADD_VM_PARAMS="-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5050"

下载 NXRM源码,并切换至 3.13.0-01 分支:

git clone https://github.com/sonatype/nexus-public.git
git checkout -b release-3.13.0-01 origin/release-3.13.0-01

IDEA导入项目并在Run/Debug Configuration里面配置调试信息:

调试分析:

文章https://securitylab.github.com/research/bean-validation-RCE/指出:

It was soon clear that the root cause of the issue was that one of the properties of a user-controller Java Bean (coming from an HTTP request) was concatenated into a Bean Validation error message, and that this message was later processed and any EL expressions were evaluated and interpolated in the final violation message.

更具体的,在创建用户或角色进行校验时,对于不存在的privilegerole参数会抛出错误,且将privilegerole插入到了报错信息模版中,模版在渲染时会取出其中的表达式并解释执行;对privilegerole的校验分别对应在org.sonatype.nexus.security.privilege.PrivilegesExistValidatororg.sonatype.nexus.security.role.RolesExistValidator中。

漏洞poc如下:

RolesExistValidator#isValid()中调用context#buildConstraintViolationWithTemplate()处下断点,可看到roles参数被放入到报错信息模版中;

回到上层ConstraintTree#validateSingleConstraint(),在调用完RolesExistValidator#isValid()后,接着调用ValidationContext#createConstraintViolations(),参数constraintValidatorContext中包含roles参数;

ValidationContext#createConstraintViolations()继续调用ValidationContext#createConstraintViolation()

跟进ValidationContext#createConstraintViolation(),其调用了ValidationContext#interpolate()messageTemplate包含roles参数;

ValidationContext#interpolate()继续调用ResourceBundleMessageInterpolator#interpolate()

ResourceBundleMessageInterpolator#interpolate()中,其调用ResourceBundleMessageInterpolator#interpolateMessage()message包含roles参数;

继续跟进ResourceBundleMessageInterpolator#interpolateMessage(),调用ResourceBundleMessageInterpolator#interpolateExpression()来处理tokens

ResourceBundleMessageInterpolator#interpolateExpression()调用InterpolationTerm#interpolate()roles参数在expression中;

跟进InterpolationTerm#interpolate(),继续调用InterpolationTerm#interpolateExpressionLanguageTerm()

最后在InterpolationTerm#interpolateExpressionLanguageTerm()中通过valueExpression.getValue()执行表达式;

修复:

对比patch,新增了EscapeHelper#stripJavaEl()对用户输入正则匹配进行清理,将‘${’替换为‘{ ’,不过该修复方案之后被绕过,详见后文;

CVE-2020-10204

影响版本:

Nexus Repository Manager 3.x OSS / Pro <= 3.21.1

环境搭建:

参照CVE-2018-16621,本文分析调试的版本是3.21.1-01

调试分析:

CVE-2020-10204即是对CVE-2018-16621 patch的绕过;绕过的根本原因是stripJavaEl()中的正则不严谨,未考虑到"$"和"{"之间的字符,pwntester@GHSL发现Hibernate message interpolation parser (org.hibernate.validator.internal.engine.messageinterpolation.parser.TokenCollector)存在bug,使得形如FOO$\A{payload}这样的payload可被正常解析执行,但却绕过了该正则。

虽然版本3.21.1-01和3.13.0-01代码有所不同,但NXRM对参数的校验过程总体一致,故这里不再列出具体的执行步骤,可参考CVE-2018-16621调试分析;我们跟踪一下TokenCollector.parse()解析FOO$\A{payload}的过程;

当parser解析到$时,currentParserState类型为MessageState,调用MessageState#handleELDesignator()

由于interpolationTermType==EL,跳过$currentParserState转变为ELState

当parser解析到\\时,currentParserState类型为ELState,调用ELState#handleEscapeCharacter()

跳过\\currentParserState转变为EscapedState

当parser解析到A时,currentParserState类型为EscapedState,调用EscapedState#handleNonMetaCharacter()

A追加到currentTokencurrentParserState转变为前一State,即ELState

当parser解析到{时,currentParserState类型为ELState,调用ELState#handleBeginTerm()

ELState#handleBeginTerm()会将currentToken(为Missing roles: [nx-adminA)加入到tokenList中,并创建空的currentToken,且追加${currentParserState转变为InterpolationTermState

parse结束后,tokenList={"Missing roles: [nx-adminA","${'vulnerability'.toUpperCase()}","]"}

修复:

增强了stripJavaEl()的正则匹配,但显然仍存在问题;

调试3.21.2发现,其使用org.hibernate.validator.messageinterpolation.ParameterMessageInterpolator 来解析处理message,而在3.21.1中用到了org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator;我们尝试找源码中对应的改动,但未找到。

 

CVE-2020-10199

影响版本:

Nexus Repository Manager 3.x OSS / Pro <= 3.21.1

环境搭建:

参照CVE-2018-16621,本文分析调试的版本是3.21.1-01

调试分析:

根据对CVE-2018-16621的分析可知,如果不可信数据被插入到报错信息模版,被当作参数传给了ConstraintValidatorContext.buildConstraintViolationWithTemplate(),那么极可能会被当作Java表达式执行;pwntester据此特征利用CodeQL对NXRM进行数据流分析,发现stripJavaEl()未被应用到类org.sonatype.nexus.validation.ConstraintViolationFactory。所以当用户可控数据流入createViolation(final String path, final String message) ,将会被当作Java EL执行。

跟踪源码发现 org.sonatype.nexus.repository.rest.api.AbstractGroupRepositoriesApiResource#validateGroupMembers() 在校验失败时调用 createViolation() ,并传入参数repositoryName。

AbstractGroupRepositoriesApiResource#validateGroupMembers()则被AbstractGroupRepositoriesApiResource#createRepository()AbstractGroupRepositoriesApiResource#updateRepository()调用;

AbstractGroupRepositoriesApiResource有子类GolangGroupRepositoriesApiResource,其在创建仓库,更新仓库时分别调用了父类的createRepository()updateRepository()

由文章https://www.cnblogs.com/magic-zero/p/12641068.html可知,根据接口文档,可构造出完整URL和数据包如下:

AbstractGroupRepositoriesApiResource#validateGroupMembers()下断点,repositoryName正是构造的payload;

buildConstraintViolationWithTemplate()下断点,发现payload被插入到了错误信息模版;

修复:

同CVE-2020-10204一样,在3.21.2中修复;

参考

https://support.sonatype.com/hc/en-us/articles/360010789153-CVE-2018-16621-Nexus-Repository-Manager-3-Java-Injection-2018-10-17

https://support.sonatype.com/hc/en-us/articles/360044882533-CVE-2020-10199-Nexus-Repository-Manager-3-Remote-Code-Execution-2020-03-31

https://support.sonatype.com/hc/en-us/articles/360044356194-CVE-2020-10204-Nexus-Repository-Manager-3-Remote-Code-Execution-2020-03-31

https://www.cnblogs.com/magic-zero/p/12641068.html

https://paper.seebug.org/1166/

https://securitylab.github.com/research/bean-validation-RCE/

https://securitylab.github.com/advisories/GHSL-2020-020-hibernate-validator/

https://securitylab.github.com/advisories/GHSL-2020-011-nxrm-sonatype/

本文原创,作者:Galaxy,其版权均为Galaxy Lab所有。如需转载,请注明出处:http://galaxylab.pingan.com.cn/nexus-repository-manager%e5%8e%86%e5%8f%b2%e8%a1%a8%e8%be%be%e5%bc%8f%e6%b3%a8%e5%85%a5%e6%bc%8f%e6%b4%9e%e5%88%86%e6%9e%90/

发表评论

*