Analysis of CVE 2022 vulnerability 36804 in Bitbucket

Tram Ho

Once again Bitbucket’s CVE . Don’t ask me why I do this guy. It’s simply easy to set up.

1. Read description

Here is Atlasssian’s description of this CVE image.png

The vulnerability can be exploited via HTTP Request with read 1 repo permission. In addition, the bug fix version is 7.6.17, so I installed on local version 7.6.16 for easy diff.

2. Error location

Bitbucket uses the built-in command git on the server to run API-related APIs, including the archive API that calls the git archive command on the system.

The archive API is an API to download the zipped code file of the repo.

API: rest/api/latest/projects/<prj key>/repos/<repo name>/archive

3. Analysis

All API calls to the built-in command git are handled by the DefaultGitScmCommandBuilder in lib/bitbucke-git.jar . In which, the code trigger archive is image.png

The DefaultGitArchiveBuilder class can take format and prefix parameters in the API: image.png

image.png As we can see above, the git archive command has args –format and –prefix and in this case will get the format and prefix values ​​that I added on the server and push it here. Of course, it already has default values, so even if you don’t add it, the API will still work properly.

Note to perform inserting 2 parameters, format and prefix, requires the code to have one, ie the repo must not be empty, otherwise it will look like this: image.png

The other program does not check the format and prefix values ​​before it is inserted into the command, so we can insert the following command: git archive –format=< format> –prefix=< prefix> … something to make it run.

However, I cannot exploit the format value, because it already has an enum that only allows one of the following formats: image.png

At first I thought just insert prefix=abcd || whoami || or something like that, it will jump into the git command and execute the whoami command at the same time, but I try and it doesn’t work.

When I searched, I discovered 1 thing, this prefix guy still takes all strings (including ||whoami|| always) to put in the prefix, not insert it into the command directly. However, the system string can be escaped by string Null. Like string = “haha u0000 hehe” then if put in terminal it will be split into “haha” and “hehe”.


String null in terminal is u0000 and on URL is * %00*.

In short, I will have to insert prefix =%00 ;whoami; %00. I will try again like this image.png

The command is still not executed. It has a “/” at the end, probably because the bitbucket set for prefix always has a / to separate the prefix and the file content. So I have to think about using another parameter that can use this / as part of it.

The git archive command has a parameter of –remote only the repo needs to be accessed, this –remote value can be combined with the / character to get the repo, because the repo here is the path to the folder: image.png

Now let’s put prefix=a ;whoami; –remote=hehe, the result is: image.png

At this point, I think, 1 must be a valid remote, 2 is the fact that the command has already been executed, but I don’t know, so I tried curling to my server port 8000, but trying curl failed. I tried a valid remote, the result is: image.png

*** Means if a string has no argument in front, the command will accept that string as ref (default ref is HEAD), without ref ;whoami; this, so I had to add another argument before the ;whoami;***, and I tried –output , the result was image.png

Still not working, while I try on terminal, the result is: image.png

So the sign ** ;** may not be reasonable in this case (because I’m a chicken, I can’t distinguish when to use ; | && || ). I tried all the cases on the terminal first and found that only using , the output will create a file with the name = whoami command: image.png

At this point, I think: the sign will take the value of the result of the statement running inside it as a string, so it is completely possible to insert the statement here and execute it. I tried on bitbucket: image.png

Honestly, until this point, I still don’t understand why it doesn’t run :v I think it still receives output= whoami .

But when I change from –output to –exec , it runs fine, and the result prints an error: image.png

With bkcs as the result of his whoami command.

I figured out that the git command actually built by bitbucket had no errors, the fault was in the terminal’s mechanism. If the terminal where it printed the output contains <cmd> , it will also execute this cmd. image.png

In short, the key to exploiting this error is to make the terminal print the line ** <cmd> ** and it will execute the command inside.

And only * –exec* can let it show that error (although I honestly don’t know the effect of this argument, I’ll probably find out later). To –exec to display this error, I must first make sure the API doesn’t jump into another exception first, so I need to bypass the prefix and –remote as above.

What I learned through this hole:

Terminal will parse the string via string null u0000

Terminal will execute the command if the command is enclosed in when printing to the console

Share the news now

Source : Viblo