0x00 前言
这篇文章依然是关于Nexus Repository Manager3的漏洞,依然是RCE😋,因为太菜找不到RCE只能来分析历史漏洞了。本篇包含以下元素:
- CVE-2018-16621(是一个EL的RCE,最后触发处和CVE-2020-10199相同)
- CVE-2020-10204(其实是对CVE-2018-16621修复后的绕过)
0x01 CVE-2018-16621
漏洞简介
在Nexus的3.x-3.13的版本中,在User的信息处,如果填入的roles不存在,则会进行一个EL表达式的渲染,大概是用来返回错误信息,但是又因为没有过滤,导致了RCE。(其实这和CVE-2020-10199类似,那里是因为不存在名字匹配的Repository,而去拼接一个报错信息,最后也会进行EL的渲染)需要注意的是,这个漏洞需要你有管理员账号,因为貌似只有管理员才能更新用户信息。
环境的搭建
依然是先从Github上clone下来,然后再checkout切换分支:
git clone https://github.com/sonatype/nexus-public.git
git checkout -f -b release-3.13.0-01 remotes/origin/release-3.13.0-01
然后使用我们的祖传docker命令:
docker run -d -p 8081:8081 -p 8000:8000 --name nexus -e INSTALL4J_ADD_VM_PARAMS="-Xms2g -Xmx2g -XX:MaxDirectMemorySize=3g -Djava.util.prefs.userRoot=${NEXUS_DATA}/javaprefs -Dstorage.diskCache.diskFreeSpaceLimit=1024 -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=8000" sonatype/nexus3:3.13.0
漏洞复现
首先用管理员账号登录,然后找到设置中的User处,如下图:
随便改改LastName,这里从User改为了User1,然后抓包如下:
把roles的内容改为EL表达式,重放之后,可以看到被渲染了:
漏洞定位
看到上面的“Missing roles”,我们可以利用这个来定位一下:
可以看到总共有两处,仔细观察之后还会发现,第二处就是就是第一处中@Constraint所指定的类,所以我们下面就直接跟进RolesExistValidator类处。
(org/sonatype/nexus/security/role/RolesExistValidator.java)
漏洞分析
不过找到了上面的切入点也没啥用…我还是不能一步步分析中间过程,只能用CVE-2020-10199(点我看详情)中我们最后调试的结果,反正这就是Nexus中EL渲染的最终处:
(org/hibernate/validator/internal/engine/messageinterpolation/ElTermResolver.java)
private String interpolateExpressionLanguageTerm(MessageInterpolator.Context context) {
String resolvedExpression = expression;
SimpleELContext elContext = new SimpleELContext();
try {
ValueExpression valueExpression = bindContextValues( expression, context, elContext );
resolvedExpression = (String) valueExpression.getValue( elContext );
}
catch ( PropertyNotFoundException pnfe ) {
log.unknownPropertyInExpressionLanguage( expression, pnfe );
}
catch ( ELException e ) {
log.errorInExpressionLanguage( expression, e );
}
catch ( Exception e ) {
log.evaluatingExpressionLanguageExpressionCausedException( expression, e );
}
return resolvedExpression;
}
在这里EL表达式会被渲染,中间过程太多了,不知道大佬们是怎样一步步追踪到这里的,或者他们也没追踪….
漏洞修复
漏洞修复在3.14.0版本对我们漏洞定位处先进行了过滤,再传入buildConstraintViolationWithTemplate进行渲染,如下:
其中stripJavaEl代码如下(org/sonatype/nexus/common/template/EscapeHelper.java):
public String stripJavaEl(final String value) {
if (value != null) {
return value.replaceAll("\\$+\\{", "{");
}
return null;
}
只进行了简单的过滤,这导致了后面CVE-2020-10204的绕过。
0x02 CVE-2020-10204
漏洞简介
如上文所说,这个漏洞是因为CVE-2018-16621的修复不严格,而导致的绕过。存在于Nexus <= 3.21.1版本中
绕过方法
虽然替换了“${”,但是使用“$\x”的格式即可绕过,并且仍然可以成功执行EL表达式,其中x可以是任意字符,如大家常用的:”$\\A{6*6}”。
漏洞复现
docker重新部署3.14.0版本的Nexus,这时候发现使用”${“会不成功
但是使用”$\\x{“则依然可以成功:
漏洞修复
漏洞在3.21.2中被修复,和CVE-2020-10199修复时间相同,网上流传的修复如下(其实可能这只是部分修复):
public String stripJavaEl(final String value) {
if (value != null) {
return value.replaceAll("\\$+\\{", "{").replaceAll("\\$+\\\\A\\{", "{");
}
return null;
}
看着只新增过滤了”$\\A{“,那岂不是还是可以绕过?
拉取3.21.2版本,重新测试:
发现并不能成功执行,应该还在其他地方进行了修复,可以调试看看,但是某名奇妙文件变成只可读了…下次再来调试
0x03 参考
Nexus Repository UserComponent远程代码执行漏洞浅析(CVE-2018-16621&CVE-2020-10204) - 先知社区 (aliyun.com)