Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/riimu/kit-csrf
Secure and simple CSRF library protected against timing and BREACH attacks
https://github.com/riimu/kit-csrf
Last synced: about 2 months ago
JSON representation
Secure and simple CSRF library protected against timing and BREACH attacks
- Host: GitHub
- URL: https://github.com/riimu/kit-csrf
- Owner: Riimu
- License: mit
- Created: 2014-05-03T10:34:04.000Z (over 10 years ago)
- Default Branch: master
- Last Pushed: 2018-12-07T20:38:54.000Z (about 6 years ago)
- Last Synced: 2024-11-30T08:04:19.886Z (about 2 months ago)
- Language: PHP
- Homepage: http://kit.riimu.net
- Size: 82 KB
- Stars: 64
- Watchers: 8
- Forks: 4
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGES.md
- License: LICENSE
Awesome Lists containing this project
README
# Secure CSRF validator #
*CSRF* is a PHP library for preventing [Cross-Site Request Forgery]
(https://www.owasp.org/index.php/Cross-Site_Request_Forgery_%28CSRF%29) attacks.
A CSRF attack takes advantage of authenticated users by sending them to a
malicious website that sends carefully crafted requests to the targeted website
in order to modify content on that website. The attack uses the authenticated
user's browser to send the request to bypass any authentication. This library
prevents these attacks by requiring a CSRF token in each POST, PUT and DELETE
request. These tokens are not known by the attacker, which prevents them from
sending malicious requests.This library supports storing the CSRF tokens using either cookies or sessions.
The token can also be submitted using either a hidden form field in POST
requests or using a HTTP header, which makes it easier to pass the token in
ajax requests.In order to provide additional security against different forms of attacks
against the CSRF tokens, this library uses constant time string comparisons to
prevent timing attacks and generates random encrypted tokens in each request to
prevent BREACH attacks. On top of that, all tokens are generated using a secure
random byte generator.The API documentation, which can be generated using Apigen, can be read online
at: http://kit.riimu.net/api/csrf/[![Build Status](https://img.shields.io/travis/Riimu/Kit-CSRF.svg?style=flat)](https://travis-ci.org/Riimu/Kit-CSRF)
[![Code Coverage](https://img.shields.io/scrutinizer/coverage/g/Riimu/Kit-CSRF.svg?style=flat)](https://scrutinizer-ci.com/g/Riimu/Kit-CSRF/)
[![Scrutinizer Code Quality](https://img.shields.io/scrutinizer/g/Riimu/Kit-CSRF.svg?style=flat)](https://scrutinizer-ci.com/g/Riimu/Kit-CSRF/)## Requirements ##
In order to use this library, the following requirements must be met:
* PHP version 5.4
* [Kit-SecureRandom](https://github.com/Riimu/Kit-SecureRandom) library is required## Installation ##
This library can be installed by using [Composer](http://getcomposer.org/). In
order to do this, you must download the latest Composer version and run the
`require` command to add this library as a dependency to your project. The
easiest way to complete these two tasks is to run the following two commands
in your terminal:```
php -r "readfile('https://getcomposer.org/installer');" | php
php composer.phar require "riimu/kit-csrf:2.*"
```If you already have Composer installed on your system and you know how to use
it, you can also install this library by adding it as a dependency to your
`composer.json` file and running the `composer install` command. Here is an
example of what your `composer.json` file could look like:```json
{
"require": {
"riimu/kit-csrf": "2.*"
}
}
```After installing this library via Composer, you can load the library by
including the `vendor/autoload.php` file that was generated by Composer during
the installation.### Manual installation ###
You can also install this library manually without using Composer. In order to
do this, you must download the [latest release](https://github.com/Riimu/Kit-CSRF/releases/latest)
and extract the `src` folder from the archive to your project folder. To load
the library, you can simply include the `src/autoload.php` file that was
provided in the archive.Note that if you install this library manually, you must also install the
dependencies by yourself. Installing the library via Composer also installs the
dependencies for you.## Usage ##
The idea of this library is to make security as convenient as possible. You only
really need two methods provided by the `CSRFHandler` class. The method
`validateRequest()` should be called at the very beginning of each request. This
method will only validate POST, PUT and DELETE requests so you can safely call
it on every request. The method `getToken()` can be used to retrieve the token
that should be included in each submitted form using a hidden field named
`csrf_token`.If the submitted token does not match against the secret token stored in the
cookie or session, the `validateRequest()` method will send a HTTP 400 (bad
request) header and kill the script execution. This should not affect the normal
usage of your website, but it will prevent any CSRF attack attempts against
your website.As an example, here is a simple web page that has one form that can be
submitted:```php
validateRequest();
$token = $csrf->getToken();?>
Simple Form
Hello %s!" . PHP_EOL, htmlspecialchars($_POST['my_name'], ENT_QUOTES | ENT_HTML5, 'UTF-8'));
}?>
What is your name?
```
### Using Sessions ###
By default, the library will save the secret token to a cookie. If you prefer
to save the token to a session instead, you can initialize the `CSRFHandler` by
setting the constructor parameter to `false`. For example:```php
validateRequest(true);
} catch (\Riimu\Kit\CSRF\InvalidCSRFTokenException $ex) {
header('HTTP/1.0 400 Bad Request');
exit('Bad CSRF Token!');
}
```### Using Token Headers ###
Note that if you are building a REST api to your website or you are using ajax
requests to send POST, PUT or DELETE requests, you may also provide the csrf
token using a header.To provide the token using a header, simply include a header named `X-CSRF-Token`
which contains the same value you would include in the `csrf_token` form field.### Using nonces ###
A *nonce* is a token that can be used only once. Turning CSRF tokens into nonces
provides protection against [Replay Attacks](https://en.wikipedia.org/wiki/Replay_attack).
It is important to note, however, that the best defense against such attacks is
using a secure HTTPS connection. However, if you do not have the luxury of an
encrypted connection at your disposal, it may be possible to [use nonces]
(http://blog.ircmaxell.com/2013/02/preventing-csrf-attacks.html) to prevent
these attacks.This library provides a way to implement nonces by using the `NonceValidator`
class. This class works exactly the same as `CSRFHandler` except that it accepts
each token generated by `getToken()` only once. Even if the attacker can spy
on the connection, they cannot resend the http request because the token only
works once.You can use the `NonceValidator` the same way as you would use the `CSRFHandler`,
for example:```php
validateRequest();
$token = $csrf->getToken();
```Note that `NonceValidator` always uses sessions to store the CSRF token. In
addition to that, it will also store which tokens have been used up and cannot
be used again. If you have a website that relies on a large number of form
submissions, this array of invalidated tokens can grow quite large. To clear this
array, simply regenerate the token using `regenerateToken()`. For example:
```php
validateRequest();if ($csrf->getNonceCount() > 100) {
$csrf->regenerateToken();
}$token = $csrf->getToken();
```### Manual Usage ###
If you wish to have more control over the token validation, this library
provides several methods that allows you to manually manage several aspects of
the library. For your convenience, the `CSRFHandler` provides the following
methods:* `isValidatedRequest()` tells if the current request is a POST, PUT or
DELETE request which should be validated.
* `validateRequest($throw = false)` validates the request and kills the script
or throws an exception if the token is invalid. The token is only validated
on POST, PUT and DELETE requests.
* `validateRequestToken()` validates the token sent in the request. True is
returned if the token exists and it matches against the secret token.
* `validateToken($token)` can be used to validate tokens manually. The token
passed to the method should be the one that has been returned by `getToken()`
* `getToken()` returns a valid base64 encoded token.
* `regenerateToken()` regenerates the secret CSRF token and invalidates all
the tokens returned previously by `getToken()`
* `getTrueToken()` returns the stored secret CSRF token that is used to
validate the tokens submitted by the user.
* `getRequestToken()` returns the token sent in the request.## Securing Your Website ##
Even this library does not prevent CSRF attacks if you fail to utilize the
tokens correctly. It is very important that each request is properly validated
and that the token is sent with each submitted form. However, there are still
couple of pitfalls that you should be aware of.If you're not using nonces, in some rare cases it may also be possible to use
[Session Fixation] (https://www.owasp.org/index.php/Session_fixation) attack to
determine the CSRF token used by the authenticated user. Even if the session ID
is regenerated upon login, the attacker may still take advantage of the known
CSRF token. To prevent this, it is simply advisable to regenerate the token
upon authentication by calling `regenerateToken()`.In order to create a website that is impervious to CSRF attacks, you must also
remember that only POST, PUT and DELETE requests should change the state of the
website. A CSRF token should be never be supplied in a GET parameter, because
this can be leaked using various different attacks. Thus, GET requests should
never affect the state. For example, allowing users to be deleted using a simple
GET request would make your website vulnerable to CSRF attacks.If you truly want to create a secure site, however, you must also only use
encrypted connections, i.e. you must use HTTPS. This is the only effective
measure against [Man-in-the-middle](https://www.owasp.org/index.php/Man-in-the-middle_attack)
attacks, but it also helps in preventing replay attacks.Finally, remember that CSRF tokens only protect you from external requests. They
offer no protection against [Cross-site Scripting](https://www.owasp.org/index.php/Cross-site_Scripting_%28XSS%29)
attacks. If the attacker is capable of running javascript on your website, the
CSRF tokens offer no additional protection. Using a XSS attack, the attacker is
always capable of finding out the CSRF token. The security of your website only
as strong as the weakest link.## Anatomy of the CSRF tokens ##
All the tokens generated by this library are random 32 byte strings. These
strings have been generated by using the SecureRandom library in order to ensure
that they have been generated using a secure random source. However, the tokens
returned by `getToken()` are more than double that in length. This is because
they are base64 encoded strings that also contain a hashed version of the token
using the secret token as a salt.In order to prevent BREACH attacks, each token returned by `getToken()` is
different, because a static token can be used to break the encryption used by a
HTTPS connection. In order to achieve this, the returned token actually consists
of a random generated token and an encrypted version of that token that has been
encrypted using HMAC-SHA256 using the secret token as the key. (which also makes
it infeasible to reverse the operation to find out the secret token). This
allows each token to be different, but still valid until `regenerateToken()` is
called. Thus, the actual length of the returned decoded string is 64 bytes.Note that a new random token is generated every time `getToken()` is called.
Thus, each string returned by that method is different. If you have a large
number of forms on your web page, it may be more efficient to use `SingleToken`
class, which loads the token only once and it can be casted to a string.## Credits ##
This library is copyright 2014 - 2015 to Riikka Kalliomäki.
See LICENSE for license and copying information.
Implementation of this library is based on ideas from Go library
[nosurf](https://github.com/justinas/nosurf) by Justinas Stankevicius