exploit the possibilities
Home Files News &[SERVICES_TAB]About Contact Add New


Posted Oct 29, 2007
Authored by Nexus | Site playhack.net

Whitepaper discussing the prevention of cross site request forgery attacks.

tags | paper, web, csrf
SHA-256 | f175ac2a874a9f1415a57c6ed31b6044ef783497e4f88ea01d77445b1856299e


Change Mirror Download
---------------------------------[ PLAYHACK.net ]---------------------------------

-[ INFOS ]-----------------------------------------------------------------------
Title: "Preventing CSRF"
Author: Nexus
Website: http://nexus.playhack.net
Date: 2007-10-25 (ISO 8601)

-[ SUMMARY ]---------------------------------------------------------------------
0x01: Hello World
0x02: Introduction
0x03: About Authentications
\_ 0x03a: Cookies Hashing
\_ 0x03b: HTTP Referer
\_ 0x03c: CAPTCHA Image
0x04: One-Time Tokens
0x05: Conclusions

---[ 0x01: Hello World ]
Welcome to a fresh new inaugural paper for the new season of the Playhack.net
Project! :) I'm really happy to see you back again and make our c00l project
be back!

Hope you'll enjoy this new short paper and i invite you to visit the whole new
project at:

Intake: actually nothing.. just a pair of cigarettes! :\

Shoutouts: all my shoutouts goes to my playhack m8s null, omni, god and emdel,
ofc to str0ke! NEX IS BACK!

---[ 0x02: Introduction ]
I already dealt with the Cross Site Request Forgery topic, but not too deep
regarding the possible solutions that web developers should adopt.
In these days i've been deeply involved in this topic during the coding of a
distributed web application which should warrant a good level of security for
user and most of all for the system's administrators (who are not that smart
though their tasks :P).
Considering this situation i had to consider each aspect and each possible
attack attempts that the applications could eventually suffer.

The one that gave me most problems to apply has been the Session Riding
(or CSRF, call it as you prefere) because there is no 100% certain way to
prevent that due to the concept that the attack fully stands on the users'

If you don't really know what Session Riding is you should read the previous
paper reachable at the following link:

---[ 0X03: Possible Solutions ]
Ok, from here i must assume that you quite deeply know how a Session Riding
attack should work out :P
Let's just have a little and fresh resume..

Consider that a trusted user is logged into a website which permits him to
accomplish some important or confidential actions, an attacker wants to get
over a possible login attack (which often will be voided) and disfrut the
opened session of the user in order to realize some crafted actions.

The attacker in order to hijack the user's session will craft an appropriate
web page which will hide a javascript function that re-create an original
form but with fixed values, then he'll make the victim visit that page which
on load will submit the form to the remote action page which will accomplish
the request secretely (without the victim's aknowledge) confying on the user's
trusted credentials.

This is a as quick as simple explaining of how a Session Riding attack would
work out, the important question now is
"How do i prevent my users to be victims of that?".

Now you would probably consider the following solutions:
- Check some cookies credentials
- Check the HTTP Referer

With some tryouts you'll realize that these are not the most proper solutions
to adopt, let's see why one by one.

------[ 0x03a: Cookies Hashing ]
This first one could be a very simple and quick solutions to this problem
because the attacker should not be aware of the victim's cookies contents,
and cannot craft then a proper workaround.

An implementation of this solutions would work out in a way like following.
In some login file we create the Cookie related to the current session:
<!-- login.php -->
// Cookie value
$value = "Something from Somewhere";
// Create a cookie which expires in one hour
setcookie("cookie", $value, time()+3600);
<!-- EOF -->

We use an hashing of the Cookie to make the form verified
<!-- form.php -->
// Hash the cookie
$hash = md5($_COOKIE['cookie']);
<form method="POST" action="resolve.php">
<input type="text" name="first_name">
<input type="text" name="last_name">
<input type="hidden" name="check" value="<?=$hash;?>">
<input type="submit" name="submit" value="Submit">
<!-- EOF -->

And the action script would be something like following:
<!-- resolve.php -->
// Check if the "check" var exists
if(isset($_POST['check'])) {
$hash = md5($_COOKIE['cookie']);
// Check if the values coincide
if($_POST['check'] == $hash) {
} else {
echo "Malicious Request!";
} else {
echo "Malicious Request!";
<!-- EOF -->

Actually this would be a fine solution to CSRF if we wouldn't consider the
fact that the user's cookie are a way easy to retrieve disfruting some XSS
flaw in the website (that we previousy saw they are not a rarity :D).
It would be more secure if we create and destroy a random cookie for each
form request that the user makes, but it wouldn't be very comfortable.

------[ 0x03b: HTTP Referer ]
The easiest way to check if the incoming requests are trusted and allowed, is to
disfrut the HTTP Referer and check if they come from the same website or from
a remote malicious page: this would be a great solution, but it falls due to
the possibility to spoof the referers and make them appear to be corrects.

Let's see why it's not a proper solution..
The following code shows an implementing example of HTTP Referer:
<!-- check.php -->
if(eregi("www.playhack.net", $_SERVER['HTTP_REFERER'])) {
} else {
echo "Malicious Request!";
<!-- EOF -->

This check can be easily bypassed forging a fake HTTP Referer from the attacker's
script using something like:
header("Referer: www.playhack.net");
Or any other way to forge the Headers to be sent from the malicious script.

Since the HTTP Referer is sent by the browser and not controlled by the server
you should never consider this variable as a trusted source!

------[ 0x03c: CAPTCHA Image ]
Another idea that came out in order to solve this issue is to use a random CAPTCHA
image in every form which require the user to type in a textbox the generated string
and with that verify the integrity of the submitted datas and the credentials of
the user.

This solutions has been discarded some time ago due to the possibility to retrieve
the captcha image using the so called MHTML bug, which affected several versions of
Microsoft Internet Explorer.

You can find all the specific informations about this vulnerability from the Secunia

Here's an extract from the Secunia's explanation of the bug:
"The vulnerability is caused due to an error in the handling of redirections for URLs
with the 'mhtml:' URI handler. This can be exploited to access documents served from
another web site."

In the same page you can find also a web test made from Secunia Staff.

Actually this bug is known to be solved with several patches released by Microsoft
for Windows XP and Windows Vista and with the release 6.0 of their own browser
Internet Explorer.

Even if actually it appears to be secure, the times brought to others possible
and theoretically more reliable solutions.

---[ 0x04: One-Time Tokens ]
Now let's explain the final solution i decided to adopt for my job: after having
dealt with all of these unreliable techniques i tried to write something different
and probably more effective.

In order to make the webforms safe from Session Riding (CSRF) i decided to make the
checking free from any kind of item that could be spoofed, retrieved or faked.
So i needed to create some one-time tokens that cannot be guessed or retrived in
any way and that after having accomplished their task would have been destroyed.

Let's start from the token value generation:
<!-- start function -->
function gen_token() {
// Generate the md5 hash of a randomized uniq id
$hash = md5(uniqid(rand(), true));
// Select a random number between 1 and 24 (32-8)
$n = rand(1, 24);
// Generate the token retrieving a part of the hash starting from
// the random N number with 8 of lenght
$token = substr($hash, $n, 8);
return $token;
<!-- EOF -->

The uniqid() PHP function allows the web developer to get a unique ID from the
current time in microseconds, which is quite good in order to retrieve a value
that won't be repeated again.

We retrieve the MD5 hashing of that ID, and then we select 8 characters from that
hashing starting from a random number <=24 (strlen($hash)-8).

The returned $token variable will retrieve an 8-long randomized token.

Let's now generate a Session Token which will be used later for the last check:
<!-- start function -->
function gen_stoken() {
// Call the function to generate the token
$token = gen_token();
// Destroy any eventually Session Token variable
// Create the Session Token variable
<!-- EOF -->

With this function we call the gen_token() function and use the returned token
to copy his value into a new $_SESSION variable.

Now let's see the function that will start the whole mechanism and that generates
the hidden input for our form:
<!-- start function -->
function gen_input() {
// Call the function to generate the Session Token variable
// Generate the form input code
echo "<input type=\"hidden\" name=\"" . FTOKEN_NAME . "\"
value=\"" . $_SESSION[STOKEN_NAME] . "\">\n";
<!-- EOF -->

As we can see this function just call the gen_stoken() function and create the
HTML code for the hidden input that will be included in the web form.

Let's now take a look to the function that make the check of the Session Token
with the submitted hidden input:
<!-- start function -->
function token_check() {
// Check if the Session Token exists
if(is_stoken()) {
// Check if the request has been sent
if(isset($_REQUEST[FTOKEN_NAME])) {
// If the Form Token is different from Session Token
// it's a malicious request
} else {
// If it isn't then it's a malicious request
} else {
// If it isn't then it's a malicious request
} else {
<!-- EOF -->

This function check the existance of the $_SESSION[STOKEN_NAME] and of
$_REQUEST[FTOKEN_NAME] (i used the $_REQUEST method in order to accept both GET
and POST methods from the form) and check if their values are the same: if they
are the submitted form is authorized.

The important point of this function is that at every concluding step the tokens
get destroyed and will be recreated only at next webform page call.

The use of these functions is really simple we just need to just add some additional
PHP nstructions.

This is the webform:
<!-- form.php -->
<form method="POST" action="resolve.php">
<input type="text" name="first_name">
<input type="text" name="last_name">
<!-- Call the function to generate the hidden input -->
<? gen_input(); ?>
<input type="submit" name="submit" value="Submit">
<!-- EOF -->

And this is the resolving script:
<!-- resolve.php -->

// Call the function to make the check

// Your code
<!-- EOF -->

As you can see is really simple to implement such a check and it should protect
your users from being hijacked by attackers and avoid to get your datas

---[ 0x05: Conclusions ]
Let's conclude this short paper saying that there is no 100% way to be secure
that your web application is completely safe, but you can start avoiding the
most common attacking techniques.

Another point that i'd like to make you focus on is that a web developer SHOULD
NOT forget of general applications faults (like XSS Browser Bugs ecc..), it
would be a great mistake not considering them as a potential threat for your
users: you should always keep in mind everything that could compromise your
application's integrity, security and interoperability.



(The above PHP codes were taken from the Seride project, hosted at

Login or Register to add favorites

File Archive:

April 2024

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Apr 1st
    10 Files
  • 2
    Apr 2nd
    26 Files
  • 3
    Apr 3rd
    40 Files
  • 4
    Apr 4th
    6 Files
  • 5
    Apr 5th
    26 Files
  • 6
    Apr 6th
    0 Files
  • 7
    Apr 7th
    0 Files
  • 8
    Apr 8th
    22 Files
  • 9
    Apr 9th
    14 Files
  • 10
    Apr 10th
    10 Files
  • 11
    Apr 11th
    13 Files
  • 12
    Apr 12th
    14 Files
  • 13
    Apr 13th
    0 Files
  • 14
    Apr 14th
    0 Files
  • 15
    Apr 15th
    30 Files
  • 16
    Apr 16th
    0 Files
  • 17
    Apr 17th
    0 Files
  • 18
    Apr 18th
    0 Files
  • 19
    Apr 19th
    0 Files
  • 20
    Apr 20th
    0 Files
  • 21
    Apr 21st
    0 Files
  • 22
    Apr 22nd
    0 Files
  • 23
    Apr 23rd
    0 Files
  • 24
    Apr 24th
    0 Files
  • 25
    Apr 25th
    0 Files
  • 26
    Apr 26th
    0 Files
  • 27
    Apr 27th
    0 Files
  • 28
    Apr 28th
    0 Files
  • 29
    Apr 29th
    0 Files
  • 30
    Apr 30th
    0 Files

Top Authors In Last 30 Days

File Tags


packet storm

© 2022 Packet Storm. All rights reserved.

Security Services
Hosting By