Ravens PHP Scripts: Forums
 

 

View next topic
View previous topic
Post new topic   Reply to topic    Ravens PHP Scripts And Web Hosting Forum Index -> Security - PHP Nuke
Author Message
Audioslaved
Regular
Regular



Joined: Nov 15, 2003
Posts: 53
Location: Hawaii and the Fan Forum

PostPosted: Mon Jun 21, 2004 4:54 pm Reply with quote

Hey guys, I think I have made a script to replace the whole "the html blah blah is not allowed" stuff.

It works like this:

There are certain known good html character types, so instead of using the whole block the "bad" only approach (more reactive and less restrictive) I have taken the opposite approach, allow known good and weed everything else.

This script does not parse an error upon encountering a bad tag or specific chars that are potentially dangerous such as document.cookie document.location, etc, alert, parenthesis, script, iframe, meta, etc. instead, all entities surrounding the word or characters in the word are replaced with their html special character equivalents.

One thing I noticed on the one that existed is that the URL was not decoded before processing checks on it, this was dangerous as when the URL got to where it needed to be, it could be uncoded then blamo! xss attack. This method uncodes the URL, stripslases, does checks and replaces, addslashes back to the variable and replaces all instances of that variable in the many arrays available in php:
Code:


$GLOBALS
$_REQUEST
$_GET
$_POST
$HTTP_GET_VARS
$HTTP_POST_VARS


I always thought that $_GET and $HTTP_GET_VARS were identical
**edit** while working with them inside of a script, more or less, thinking that changing of one would automatically propagate to the other. **/edit**, I proved myself wrong, all you have to do to see exactly what is what is print the $GLOBALS array **edit** after changing the value of one global variable inside your script **/edit** , which provides you with everything and lets you see what PHP is carrying around on every script execution. When conducting this research and building this script, it dawned on me that all instances in each of these arrays need to be replaced to do any good.

To print the $GLOBALS array, do the following in the top of your mainfile.php or header.php
Code:


echo "<pre>";
print_r($GLOBALS);
echo "</pre>";


If you think that $_GET[username] is the same as $username **edit** while inside of the script, not at initial execution **/edit**, you are sadly mistaken, when printing $GLOBALS, you will see the following are all seperate variables
Code:


$GLOBALS['username']; //this is actually $username
$_REQUEST['username']; //is not the same as $username global
$_GET['username']; //is not the same as $username global
$_HTTP_GET_VARS['username']; //is not the same as $username global


For $username to be the same as $_GET['username'] or $HTTP_GET_VARS['username'], it would have to be declared like:
Code:


$username = $_GET['username']; ||
$username = $HTTP_GET_VARS['username'];


With all of that in mind: I crafted the script, it also does extra stuff like close or repair certain tags based on bad coding before the $_GET or $_POST. The following type's of tag errors will be corrected
Code:


<> //no contents in tag
<    < //no closing tag
>    > // no closing tag
<       // no end tag


This should put a limit to the damage that can be done by purposely submitting bogus tags in the hopes of doing cosmetic damage.

The real pie of this is trying to implement common sense into daily activities.

For instance, throughout this whole time, we have never really stopped to think who needs to do what:

For the most part (There may be weird circumstances), but a normal site user will never ever have to call to script, meta, iframe, or even call javascript within image, hrefs, etc. A webmaster on the other hand may still decide to do so because he knows what he wants to offer his visitors.

We do still want to allow our users the ability to use standard html, and we want to give them the ability to use parenthesis, (I love them personally) Smile

If they try to be brave, there will be no damage done as instead because their braveness will only be echoed to the screen, instead of receiving an error that does not appear to be related to the website they are on.

The code is running on nuke69.audioslaved.com, I will post it later, I am constantly trying to exploit myself, (pretty interesting), maybe waraxe will stop by and let me know if this stops his ability to find xss holes in nuke! Wink That is the idea anyway!

If anyone is interested in applying this to help test for bugs, that would be deeply appreciated, once completed, I am going to push this to everyone I know! So the quicker and more people that help test, the faster it is developed and the less "I've been HACKED!" threads we will see. Appreciate everyone getting this far, PM me if you are interested, I will shoot you the code.

**edited for clarity**
-Bill (Audioslaved)

_________________
The Audioslave Fan Forum
For the Fans, By the Fans [ Only registered users can see links on this board! Get registered or login! ]

Last edited by Audioslaved on Mon Jun 21, 2004 11:02 pm; edited 2 times in total 
View user's profile Send private message Send e-mail Visit poster's website AIM Address MSN Messenger
Raven
Site Admin/Owner



Joined: Aug 27, 2002
Posts: 17088

PostPosted: Mon Jun 21, 2004 9:16 pm Reply with quote

Bill,

I need you to check something. These statements may be in error.
AudioSlaved wrote:
I always thought that $_GET and $HTTP_GET_VARS were identical, I proved myself wrong, all you have to do to see exactly what is what is print the $GLOBALS array, which provides you with everything and lets you see what PHP is carrying around on every script execution. When conducting this research and building this script, it dawned on me that all instances in each of these arrays need to be replaced to do any good.


Consider this test
Code:
<?

echo '$_GET[\'username\'] = '.$_GET['username'];
echo "<br /><br />";
echo '$HTTP_GET_VARS[\'username\'] = '.$HTTP_GET_VARS['username'];
echo "<br /><br />";
echo '$GLOBALS[\'username\'] = '.$GLOBALS['username'];
?>
Now save this as whatever you want (as.php) and invoke it like this
Code:
http://your_domain.com/as.php?username=Gaylen
This is what you will see which is as it should be
Quote:
$_GET['username'] = Gaylen

$HTTP_GET_VARS['username'] = Gaylen

$GLOBALS['username'] = Gaylen
 
View user's profile Send private message
Audioslaved







PostPosted: Mon Jun 21, 2004 10:33 pm Reply with quote

no that is correct,... I am talking about reassigning the variable, for instance

In your script, if you rename
Code:


$_GET['username'] = Gaylen

To

$_GET['username'] = Bill

And then print all of the arrays, you should see

$_REQUEST['username'] = Gaylen
$GLOBALS['username'] = Gaylen
$HTTP_GET_VARS['username'] = Gaylen
$_GET['username'] = Bill


That is what I am referring to, at first execution of the script, all of those Globals start off the same, but changing one internally, does not propagate that change to the other Global arrays.

So in this scripts case, it does a loop through the $_REQUEST global and does all the leg work weeding out the bad tags, upon time to change the value of the variable, it has to be reassigned in the each GLOBAL array so that old value is taken out completely and replaced with the new one for all possible instances of the variable.

So changing $_GET['username'] to Bill does not automatically propagate to the $username global ($GLOBAL['username'] = Gaylen), it has to be done in the script.

in address bar pressed as.php?username=Gaylen
Code:


foreach($_GET as $key => $val) {
 if ($key == "username") {
 $_GET[$key] = "Bill";
 }
}

echo "<pre>";
print_r($GLOBALS);
echo "</pre>";

Should see:
$_REQUEST['username'] = Gaylen
$GLOBALS['username'] = Gaylen
$HTTP_GET_VARS['username'] = Gaylen
$_GET['username'] = Bill


Again, I am only talking of them being treated as seperate arrays within the script, not upon actual execution of the $_GET or $_POST method. I guess I should have spelled that out more clearly. I thought it was someone interested in what I did! What a fool! Very Happy
 
Raven







PostPosted: Mon Jun 21, 2004 11:23 pm Reply with quote

You're not a fool! And I am interested, otherwise I would not have replied Smile. It's now obvious that I did not understand where you were coming from and I have to be sure. Thanks.
 
Audioslaved







PostPosted: Tue Jun 22, 2004 4:54 am Reply with quote

How could I be a fool, I learned everything I know from you, CS, and humpa, fool I am not, thanks for reminding me. Wink

BTW, just finishing it up for public viewing, shouldn't be too long now! Smile
 
Audioslaved







PostPosted: Tue Jun 22, 2004 6:39 am Reply with quote

OK folks, here it is, would appreciate any suggestions you may have. I am only about 98% on the regex, there may be faster/easier approaches I am just not seeing from my angle. If you have questions on certain portions, please ask. I have not been able to test this for performance, but considering the context it is used, I don't see it being that intensive at all. The community needs something similar to this I believe, hence why I spent my whole weekend reading and trying to hack myself, if this is a feasible alternative, I would like to look into adding sql injection patterns and cookie decode checks for user/admin vars. That way we may be able to stop them from the get go and have all of our main checking code in one location or function vise having it split in multiple files.

Location to attempt to exploit is [ Only registered users can see links on this board! Get registered or login! ] if you are successful, don't be a dick about it, like deleting all my db's, something like that is really uncalled for. Simply posting an admin article or something similar is enough to let me know there is still a hole. Please do keep in mind also that this is primarly xss attacks based on html, not those based on sql injection. If you are able to get in, make sure you write down what you did so I can incorporate that in. Thx.

Code:


     $speedHackAdminBypass = 0; //Set to 1, will say that admins don't have to do, use html freely again! :)

     if (($speedHackAdminBypass == 1 && !is_admin($admin)) || ($speedHackAdminBypass == 0 && (! is_admin($admin) || is_admin($admin)))) {
          if (isset($_REQUEST)) {
               foreach ($_REQUEST as $key => $secvalue) {
               $secvalue = urldecode($secvalue);
               $secvalue = stripslashes($secvalue);
               //Following code examines contents in between <> tags, if tag is not commonly used
               //replace all instances of < > ( ) # and script with html equivalent characters
               //tags not meeting common criteria will be present on the page as they are no longer
               //properly formatted tags.
               //Do initial check on tags to see how they are, if they are formatted wrong,
               //attempt to help out. Affects tags which <> are empty, >   > have no beginning tag,
               // <      < missing an end tag, <     have no end tag
               $sloppytags = array("'([\r\n])[\s]+'", "'^(>|\">)'", "'(<\s*>)'m", "'((?:\<)(\s*?\/?\s*?[^>]*\/?\/?\s*?)(?:\<))'mi", "'((?:\>)(\s*?\/?\s*?[^<]*\/?\/?\s*?)(?:\>))'mi", "'((?:\<)(\s*?\/?[^><]+\/?\s*))$'mi", "'(<\s*>)'s");
               $bettertags = array("", "", "", "\\2<", ">\\2", "<\\2>", "");                   
               $secvalue = preg_replace($sloppytags, $bettertags, $secvalue);
               //Grabs all remaining HTML Tags (Empty tags should have been deleted above)
               preg_match_all("/(<\s*?\/?\s*?[^>]*[^<]*\/?\/?\s*?>)/im", $secvalue, $urlblah);               
               $blah = array();
               $countblah = 0;
                    foreach($urlblah[0] as $url) {
                    $the_reg = '/(<\s*\/?\s*(b|br|em|li|ul|i|pre|tt|citestrong|blockquote|dl|dt|dd|ol|center|a|(hr|font|p)(\s*(align|size|color)(\=(\"|\'|\s*)[a-z0-9\%px\;]*)\7|\s*?noshade)?)\s*?\/?\s*>)/si';
                         if(! preg_match($the_reg, $url)) {
                         $do = 1;
                              if (eregi("src=", $url)) {
                              $do = 0;
                              $img_reg = '/(src=(\"|\'|\s*)[^\"\'\?\&]*(\.gif|\.jpg|\.png)\2)/i';
                                    if (! preg_match($img_reg, $url)) {
                                    $do = 1;
                                    }
                              }
                              if (eregi("href=", $url)) {
                              $do = 0;
                              $loc_reg = '/(href=[^>]*(location|\([^>]*[^)]*\)|\#|\.js|\.vbs|\.css|alert|document\.?|cookie)[^>]*)/i';
                                    if (preg_match($loc_reg, $url)) {
                                    $do = 1;
                                    } else {
                                    $do = 0;
                                    }
                              }
                         } else {
                         $do = 0;
                         }     
                         if ($do == 1) {
                         $dead = array("'#'", "'<'", "'>'", "'\('", "'\)'", "'\/'", "'script'i", "'alert'i", "'document'i", "'location'i", "'cookie'i");
                         $live = array("&#35;", "&#60;", "&#62;", "&#40;", "&#41;", "&#47;", "s&#99;r&#105;pt", "&#97;l&#101;rt", "&#100;ocum&#101;nt", "lo&#99;&#97;tion", "&#99;ooki&#101;");
                         $blah[$countblah] = preg_replace($dead, $live, $url);
                         } elseif($do == 0) {
                         $blah[$countblah] = $url;
                         }
                    $blah[$countblah] = $blah[$countblah];
                    $do = 0;
                    $countblah++;
                    }
               $secvalue = str_replace($urlblah[0], $blah, $secvalue);
               //Lets do a final sweep on everything not within the <> tags. xss attacks
               //using document,location,alert,cookie,and parenthesis, having fun now?
               $morebad = array("'alert'i", "'document'i", "'location'i", "'cookie'i", "'\('", "'\)'");
               $moregooder = array("&#97;l&#101;rt", "&#100;ocum&#101;nt", "lo&#99;&#97;tion", "&#99;ooki&#101;", "&#40;", "&#41;");
               $secvalue = preg_replace($morebad, $moregooder, $secvalue);
               $_REQUEST[$key] = "$secvalue";
                    if (isset($GLOBALS[$key])) {
                    $GLOBALS[$key] = $secvalue;
                    }
                    if(isset($_GET[$key]) || isset($HTTP_GET_VARS[$key])) {
                    $_GET[$key] = $secvalue;
                    $HTTP_GET_VARS[$key] = $secvalue;
                    } elseif(isset($_POST[$key]) || isset($HTTP_POST_VARS[$key])) {
                    $HTTP_POST_VARS[$key] = $secvalue;
                    $_POST[$key] = $secvalue;
                    }
               }
          }
     }   
 
Display posts from previous:       
Post new topic   Reply to topic    Ravens PHP Scripts And Web Hosting Forum Index -> Security - PHP Nuke

View next topic
View previous topic
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You can attach files in this forum
You can download files in this forum


Powered by phpBB © 2001-2007 phpBB Group
All times are GMT - 6 Hours
 
Forums ©