This repository was archived by the owner on Apr 29, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcsrfguard.class.php
115 lines (97 loc) · 3.57 KB
/
csrfguard.class.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
<?php
/*
PHP CSRF Guard is a secure anti-CSRF token generator and checker class.
Multiple CSRF tokens are allowed.
Licensed under the MIT license <http://www.opensource.org/licenses/mit-license.php>
@author Quentin LEGRAND
@version 1.0
*/
Class CsrfGuard {
protected static $cookieName = "CSRF_tokens";
private static $key = null;
public static function setKey($key) {
self::$key = $key;
}
public static function check($token, $form = null, $timespan = null) {
// First, get the cookie corresponding to the token if it exists
$cookie = self::getCookie($token);
if($cookie === null)
throw new Exception("Invalid token");
// Then check if seal is correct
if(!self::checkSeal($cookie))
throw new Exception("Cookie seal is broken")
// Then, check if form key is valid
if($form !== null && $cookie["form"] != $form)
throw new Exception("Token is invalid for this form");
// Then, check if token is not expired
if($timespan !== null && $cookie["time"] + $timespan < time())
throw new Exception("Token is expired");
// Else, it's ok, don't forget to delete token
self::removeCookie($cookie);
return true;
}
public static function generate($form = null) {
// Generate a new key if not already defined
if(self::$key === null) self::$key = self::random();
// Generate random token
$token = self::random()
$cookie = array(
"form" => $form,
"token" => $token,
"time" => time()
);
// Sign cookie
self::seal($cookie);
// Save it in browser cookie
self::saveCookie($cookie);
// Return the token
return $token;
}
protected static function saveCookies($cookies) {
setcookie(self:$cookieName, json_encode($cookies), 0, "/", false, true, true);
}
protected static function saveCookie($cookie) {
$cookies = json_decode(self::getCookies());
$cookies[] = $cookie;
self::saveCookies($cookies);
}
protected static function getCookies() {
if(isset($_COOKIE[self::$cookieName]))
return $_COOKIE[self::$cookieName];
else
return array();
}
protected static function getCookie($token) {
$cookies = self::getCookies();
foreach($cookies as $cookie) {
if($cookie["token"] == $token)
return $cookie;
}
return null;
}
protected static function remove($token) {
$cookies = self::getCookies();
foreach($cookies as $idx => $cookie) {
if($cookies["token"] == $token) {
unset($cookies[$idx]);
self::saveCookies($cookies);
return true;
}
}
return false;
}
protected static function seal(&$cookie) {
$cookie["seal"] = self::sign($cookie["form"].$cookie["token"].$cookie["time"]);
return $cookie;
}
protected static function checkSeal($cookie) {
$seal = self::sign($cookie["form"].$cookie["rand"].$cookie["time"]);
return $seal == $cookie["seal"];
}
protected static function sign($str) {
return hash_hmac("sha256", $str, self::$key);
}
protected static function random() {
return bin2hex(random_bytes(32));
}
}