Skip to content
Snippets Groups Projects
Commit 50258951 authored by Peter Rotich's avatar Peter Rotich
Browse files

Add real class to handle CSRF protection

parent 00c9085a
No related branches found
No related tags found
No related merge requests found
......@@ -4,15 +4,19 @@
Provides mechanisms to protect against cross-site request forgery
attacks. This is accomplished by using a token that is not stored in a
cookie, but required to make changes to the system.
session, but required to make changes to the system.
This can be accomplished by emitting a hidden field in a form, or
sending a separate header (X-CSRFToken) when forms are submitted.
sending a separate header (X-CSRFToken) when forms are submitted (e.g Ajax).
This technique is based on the protection mechanism in the Django
project, detailed at and thanks to
https://docs.djangoproject.com/en/dev/ref/contrib/csrf/.
* TIMEOUT
Token can be expired after X seconds of inactivity (timeout) independent of the session.
Jared Hancock
Copyright (c) 2006-2012 osTicket
http://www.osticket.com
......@@ -23,69 +27,66 @@
vim: expandtab sw=4 ts=4 sts=4:
**********************************************************************/
function csrf_token() {
?>
<input type="hidden" name="__CSRFToken__" value="<?php
echo csrf_get_token(); ?>" />
<?php
}
Class CSRF {
var $name;
var $timeout;
var $csrf;
function csrf_get_token($length=32) {
if (!isset($_SESSION['CSRFToken'])) {
for ($i = 0; $i <= $length; $i++)
$r .= chr(mt_rand(0, 255));
$_SESSION['CSRFToken'] = base64_encode($r);
function CSRF($name='__CSRFToken__', $timeout=0) {
$this->name = $name;
$this->timeout = $timeout;
$this->csrf = &$_SESSION['csrf'];
}
return $_SESSION['CSRFToken'];
}
function csrf_ensure_cookie() {
global $csrf_unprotected;
if ($csrf_unprotected)
return true;
function reset() {
$this->csrf = array();
}
$token = csrf_get_token();
if (isset($_POST['__CSRFToken__'])) {
if ($token == $_POST['__CSRFToken__'])
return true;
function isExpired() {
return ($this->timeout && (time()-$this->csrf['time'])>$this->timeout);
}
elseif (isset($_SERVER['HTTP_X_CSRFTOKEN'])) {
if ($token == $_SERVER['HTTP_X_CSRFTOKEN'])
return true;
function getTokenName() {
return $this->name;
}
Http::response(400, 'CSRF Token Required');
}
function csrf_unprotect() {
global $csrf_unprotected;
$csrf_unprotected = true;
}
function getToken($len=32) {
if(!$this->csrf['token'] || $this->isExpired()) {
$len = $len>8?$len:32;
for ($i = 0; $i <= $len; $i++)
$r .= chr(mt_rand(0, 255));
$this->csrf['token'] = base64_encode(sha1(session_id().$r.SECRET_SALT));
$this->csrf['time'] = time();
} else {
//Reset the timer
$this->csrf['time'] = time();
}
# Many thanks to https://docs.djangoproject.com/en/dev/ref/contrib/csrf/
function csrf_enable_ajax() { ?>
<script type="text/javascript">
jQuery(document).ajaxSend(function(event, xhr, settings) {
function sameOrigin(url) {
// url could be relative or scheme relative or absolute
var host = document.location.host; // host + port
var protocol = document.location.protocol;
var sr_origin = '//' + host;
var origin = protocol + sr_origin;
// Allow absolute or scheme relative URLs to same origin
return (url == origin || url.slice(0, origin.length + 1) == origin + '/') ||
(url == sr_origin || url.slice(0, sr_origin.length + 1) == sr_origin + '/') ||
// or any other URL that isn't scheme relative or absolute i.e
// relative.
!(/^(\/\/|http:|https:).*/.test(url));
return $this->csrf['token'];
}
function safeMethod(method) {
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
function validateToken($token) {
return ($token && trim($token)==$this->getToken() && !$this->isExpired());
}
if (!safeMethod(settings.type) && sameOrigin(settings.url)) {
xhr.setRequestHeader("X-CSRFToken", "<?php echo csrf_get_token(); ?>");
function getFormInput($name='') {
if(!$name) $name = $this->name;
return sprintf('<input type="hidden" name="%s" value="%s" />', $name, $this->getToken());
}
});
</script>
<?php }
}
/* global function to add hidden token input with to forms */
function csrf_token() {
global $ost;
if($ost && $ost->getCSRF())
echo $ost->getCSRFFormInput();
}
?>
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment