漏洞挖掘之命令注入漏洞
漏洞简介
受影响的 Bitbucket Server 和 Data Center 版本存在使用环境变量的命令注入漏洞,具有控制其用户名权限的攻击者可以在系统上执行任意命令。
影响范围
Bitbucket Server 和 Data Center 的 8.0 至 8.4 版会受到此漏洞的影响• 7.0 to 7.5 (all versions)• 7.6.0 to 7.6.18• 7.7 to 7.16 (all versions)• 7.17.0 to 7.17.11• 7.18 to 7.20 (all versions)• 7.21.0 to 7.21.5• 8.0.0 to 8.0.4• 8.1.0 to 8.1.4• 8.2.0 to 8.2.3• 8.3.0 to 8.3.2• 8.4.0 to 8.4.1
调试环境设置
需要设置 jvm 参数,在启动文件 start-bitbucket.sh 中并没有发现相关参数,注意到这里加载了_start-webapp.sh
在其中找到了 JAVA_OPTS 参数并在最后加上:
①网络安全学习路线
②20 份渗透测试电子书
③安全攻防 357 页笔记
④50 份安全攻防面试指南
⑤安全红队渗透工具包
⑥网络安全必备书籍
⑦100 个漏洞实战案例
⑧安全大厂内部视频资源
⑨历年 CTF 夺旗赛题解析
执行 service atlbitbucket stop、service atlbitbucket start 重启 Bitbucket,观察进程发现带上了后面加的 jvm 参数
然后配置 idea 并调试启动
漏洞分析
根据漏洞影响范围下载了 8.4.2 和 8.4.1 版本进行对比后发现差异太大了,于是又下载了 7.6.19 和 7.6.18 版本。根据两个修复版本之间共同的差异最终锁定安全更新的部分为两个 jar 包:bitbucket-process-.jar 和 nuprocess-.jar 反编译后进一步对比发现 bitbucket-process-*.jar 中 DefaultNioProcessConfigurer.java、NioProcessParameters.java、RemoteUserNioProcessConfigurer.java 中的差异符合官方漏洞描述:有权控制其用户名权限的攻击者能够利用环境变量进行命令注入在\com\atlassian\bitbucket\internal\process\DefaultNioProcessConfigurer.java 中将环境变量的设置改为了 NioProcessParameters.environmentPutIfAbsent 函数
这个函数是\com\atlassian\bitbucket\internal\process\NioProcessParameters.java 中新增的,其中调用的函数对 key 进行了非空判断,对 key 和 valve 都进行了空字节的检测
在\com\atlassian\bitbucket\internal\process\RemoteUserNioProcessConfigurer.java 中发现了官方描述的用户名环境变量:REMOTE_USER
通过回溯相关类及其继承类的调用找到了路由入口,如:com.atlassian.stash.internal.rest.content.FileListResource 联想到 Bitbucket 也是用于 Git 代码管理,猜测这里会执行 git 命令
创建仓库后根据路由访问:
跟进看一下命令在哪里执行的以及环境变量用来干什么在 RemoteUserNioProcessConfigurer 中的 configure 方法成功命中断点,这里发现已经传入了 git 命令,但是漏洞描述说的是使用用户名环境变量造成的注入,所以只需关注环境变量部分
调用 DefaultAuthenticationContext.getCurrentUser 方法后生成 user,其中包含注册的用户名:test
其 getName 方法主要逻辑就是返回注册信息中的用户名
随后赋值给环境变量 REMOTE_USER
返回之后回到 NuNioProcessHelper.run 方法
然后调用 NuProcessBuilder.run 方法,prepareEnvironment 方法进行格式转换,取出环境变量中的 key 和 value 以’=’拼接放入字符数组
一直跟入后发现在 LinuxProcess.prepareProcess 方法中环境变量经过 toEnvironmentBlock 方法处理
该函数主要逻辑就是将环境变量数组中的全部环境变量转化为字节后赋值给新的 block 字节数组并返回。其中每次拷贝一个环境变量字节后新的拷贝位置会加一,以实现环境变量间的分隔。根据漏洞修复方式,在环境变量中使用空字节后,在这里空字节后面部分就是一个新的环境变量,猜测可能是注入了一个恶意环境变量
返回赋值给 envBlock 后调用LibJava10.Java_java_lang_ProcessImpl_forkAndExec
方法,这里通过调用 java native 方法实现命令执行
这里并没有发现环境变量如何造成任意命令执行,回看其它地方也没有发现环境变量引入到命令执行触发点。相关的历史漏洞都是 git 参数注入
才意识到是 git 环境变量:
简单来说就是执行 git 命令时会自动调用相关的环境变量,而某些环境变量可以执行命令如上面的 GIT_EXTERNAL_DIFF 根据文章描述该环境变量是在执行 git diff 时用到的,而上面的 git 命令用不到该环境变量按照描述注册一个用户名为:’test GIT_EXTERNAL_DIFF=touch /tmp/test’,然后去仓库执行 diff 操作
根据路由,调用到 CommitDiffResource. streamDiff 函数。后续流程和上面一样了,只是现在执行的 git diff 命令,会用到注入的 git 环境变量‘GIT_EXTERNAL_DIFF‘造成命令执行
漏洞复现
注册一个带有环境变量的用户名,然后 burp 拦截将空格改为 %00
然后进入仓库进行 diff
成功在/tmp 目录下创建 test 文件
评论