├── .gitignore ├── .scrutinizer.yml ├── .travis.yml ├── LICENSE ├── README.md ├── composer.json ├── composer.lock ├── phpunit.php ├── phpunit.xml ├── src └── CSRF.php └── tests └── CSRF.php /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_* 2 | ._* 3 | vendor 4 | .idea -------------------------------------------------------------------------------- /.scrutinizer.yml: -------------------------------------------------------------------------------- 1 | filter: 2 | paths: [src/*] 3 | excluded_paths: [test/*] 4 | tools: 5 | external_code_coverage: 6 | timeout: 600 7 | runs: 3 8 | php_code_coverage: false -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | php: 4 | - 5.6 5 | - 5.5 6 | - 5.4 7 | - 5.3 8 | - hhvm 9 | 10 | before_script: 11 | - composer self-update 12 | - composer install 13 | 14 | script: 15 | - phpunit --coverage-text --coverage-clover=coverage.clover 16 | 17 | after_script: 18 | - wget https://scrutinizer-ci.com/ocular.phar 19 | - php ocular.phar code-coverage:upload --format=php-clover coverage.clover 20 | 21 | matrix: 22 | allow_failures: 23 | - php: hhvm -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Nick Volgas 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Volnix\CSRF 2 | 3 | [](https://travis-ci.org/volnix/csrf) [](https://packagist.org/packages/volnix/csrf) [](https://packagist.org/packages/volnix/csrf) [](https://scrutinizer-ci.com/g/volnix/csrf/?branch=master) 4 | 5 | 6 | CSRF protection library that compares provided token to session token to ensure request validity. Token values are stored in session and validated against that session store to verify the request. Tokens are changed on every request so ensure frequently changes and increase the difficulty in guessing the token value. 7 | 8 | ## Installation 9 | 10 | This package is installed via composer and is pulled in as the `volnix/csrf` package. 11 | 12 | ```json 13 | 14 | "require": { 15 | "volnix/csrf": "~1.0" 16 | } 17 | 18 | ``` 19 | 20 | ## Unit Tests 21 | 22 | The unit tests for this application live in the `./tests` directory. There is a test for each library in the security package. The PHPUnit xml file is in the root of the project (`./phpunit.xml`). 23 | 24 | ## Usage 25 | 26 | This library is used for preventing cross-site request forgery. Currently you can retrieve the token, a pre-built query string, or a pre-built hidden input tag. 27 | 28 | There are two main pieces to this library: 29 | 30 | 1. Injection of a CSRF token 31 | 2. Validation of the CSRF token 32 | 33 | #### 1. Injection of token 34 | 35 | There are a variety of ways to get your CSRF token into your form markup: 36 | 37 | Value only: 38 | 39 | ```php 40 | 41 | 44 | 45 | 46 | 47 | 48 | 49 | ``` 50 | 51 | Hidden input string: 52 | 53 | ```php 54 | 55 |
60 | 61 | ``` 62 | 63 | Query string: 64 | 65 | ```php 66 | 67 | 71 | 72 | ``` 73 | 74 | If a different token name is desired, you may pass it in on any call that retrieves the token (`getToken()`, `getHiddenInputString()`, `getQueryString()`): 75 | 76 | ```php 77 | 78 | 83 | 84 | ``` 85 | 86 | #### 2. Validation of token 87 | 88 | To validate your token, just pass in your array of POST/GET/REQUEST data. If you have a custom token name, then there is an optional second argument for it. 89 | 90 | > **Note:** token validation is done using a constant-time comparison method to protect against timing attacks. 91 | 92 | Basic POST data validation: 93 | 94 | ```php 95 | 96 | // generic POST data 97 | if ( CSRF::validate($_POST) ) { 98 | // good token 99 | } else { 100 | // bad token 101 | } 102 | 103 | ``` 104 | 105 | Using Symfony's HTTP Foundation: 106 | 107 | ```php 108 | 109 | // symfony object 110 | $request = \Symfony\Component\HttpFoundation\Request::createFromGlobals(); 111 | 112 | if ( CSRF::validate($request->request->all()) ) { 113 | // good token 114 | } else { 115 | // bad token 116 | } 117 | 118 | ``` 119 | 120 | Validating a custom-named token: 121 | 122 | ```php 123 | 124 | // validating with a custom token name 125 | if ( CSRF::validate($_POST, 'my_custom_name') ) { 126 | // good token 127 | } else { 128 | // bad token 129 | } 130 | 131 | ``` 132 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "volnix/csrf", 3 | "description": "CSRF protection library that compares provided token to session token to ensure request validity.", 4 | "license": "MIT", 5 | "homepage": "https://github.com/volnix/csrf", 6 | "authors": [ 7 | { 8 | "name": "Nick Volgas", 9 | "email": "nvolgas@ark.org" 10 | } 11 | ], 12 | "autoload": { 13 | "psr-4": { 14 | "Volnix\\CSRF\\": "src/" 15 | } 16 | }, 17 | "require": { 18 | "php": ">= 5.3" 19 | }, 20 | 21 | "require-dev":{ 22 | "phpunit/phpunit": "~3.7" 23 | }, 24 | "minimum-stability": "dev" 25 | } 26 | -------------------------------------------------------------------------------- /composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", 5 | "This file is @generated automatically" 6 | ], 7 | "hash": "39cd19be040f552ea699734260d386ed", 8 | "content-hash": "d609693b320b15f2322430e0aa01a0a6", 9 | "packages": [], 10 | "packages-dev": [ 11 | { 12 | "name": "phpunit/php-code-coverage", 13 | "version": "1.2.x-dev", 14 | "source": { 15 | "type": "git", 16 | "url": "https://github.com/sebastianbergmann/php-code-coverage.git", 17 | "reference": "fe2466802556d3fe4e4d1d58ffd3ccfd0a19be0b" 18 | }, 19 | "dist": { 20 | "type": "zip", 21 | "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/fe2466802556d3fe4e4d1d58ffd3ccfd0a19be0b", 22 | "reference": "fe2466802556d3fe4e4d1d58ffd3ccfd0a19be0b", 23 | "shasum": "" 24 | }, 25 | "require": { 26 | "php": ">=5.3.3", 27 | "phpunit/php-file-iterator": ">=1.3.0@stable", 28 | "phpunit/php-text-template": ">=1.2.0@stable", 29 | "phpunit/php-token-stream": ">=1.1.3,<1.3.0" 30 | }, 31 | "require-dev": { 32 | "phpunit/phpunit": "3.7.*@dev" 33 | }, 34 | "suggest": { 35 | "ext-dom": "*", 36 | "ext-xdebug": ">=2.0.5" 37 | }, 38 | "type": "library", 39 | "extra": { 40 | "branch-alias": { 41 | "dev-master": "1.2.x-dev" 42 | } 43 | }, 44 | "autoload": { 45 | "classmap": [ 46 | "PHP/" 47 | ] 48 | }, 49 | "notification-url": "https://packagist.org/downloads/", 50 | "include-path": [ 51 | "" 52 | ], 53 | "license": [ 54 | "BSD-3-Clause" 55 | ], 56 | "authors": [ 57 | { 58 | "name": "Sebastian Bergmann", 59 | "email": "sb@sebastian-bergmann.de", 60 | "role": "lead" 61 | } 62 | ], 63 | "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", 64 | "homepage": "https://github.com/sebastianbergmann/php-code-coverage", 65 | "keywords": [ 66 | "coverage", 67 | "testing", 68 | "xunit" 69 | ], 70 | "time": "2014-09-02 10:13:14" 71 | }, 72 | { 73 | "name": "phpunit/php-file-iterator", 74 | "version": "dev-master", 75 | "source": { 76 | "type": "git", 77 | "url": "https://github.com/sebastianbergmann/php-file-iterator.git", 78 | "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0" 79 | }, 80 | "dist": { 81 | "type": "zip", 82 | "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/6150bf2c35d3fc379e50c7602b75caceaa39dbf0", 83 | "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0", 84 | "shasum": "" 85 | }, 86 | "require": { 87 | "php": ">=5.3.3" 88 | }, 89 | "type": "library", 90 | "extra": { 91 | "branch-alias": { 92 | "dev-master": "1.4.x-dev" 93 | } 94 | }, 95 | "autoload": { 96 | "classmap": [ 97 | "src/" 98 | ] 99 | }, 100 | "notification-url": "https://packagist.org/downloads/", 101 | "license": [ 102 | "BSD-3-Clause" 103 | ], 104 | "authors": [ 105 | { 106 | "name": "Sebastian Bergmann", 107 | "email": "sb@sebastian-bergmann.de", 108 | "role": "lead" 109 | } 110 | ], 111 | "description": "FilterIterator implementation that filters files based on a list of suffixes.", 112 | "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", 113 | "keywords": [ 114 | "filesystem", 115 | "iterator" 116 | ], 117 | "time": "2015-06-21 13:08:43" 118 | }, 119 | { 120 | "name": "phpunit/php-text-template", 121 | "version": "1.2.1", 122 | "source": { 123 | "type": "git", 124 | "url": "https://github.com/sebastianbergmann/php-text-template.git", 125 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" 126 | }, 127 | "dist": { 128 | "type": "zip", 129 | "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", 130 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", 131 | "shasum": "" 132 | }, 133 | "require": { 134 | "php": ">=5.3.3" 135 | }, 136 | "type": "library", 137 | "autoload": { 138 | "classmap": [ 139 | "src/" 140 | ] 141 | }, 142 | "notification-url": "https://packagist.org/downloads/", 143 | "license": [ 144 | "BSD-3-Clause" 145 | ], 146 | "authors": [ 147 | { 148 | "name": "Sebastian Bergmann", 149 | "email": "sebastian@phpunit.de", 150 | "role": "lead" 151 | } 152 | ], 153 | "description": "Simple template engine.", 154 | "homepage": "https://github.com/sebastianbergmann/php-text-template/", 155 | "keywords": [ 156 | "template" 157 | ], 158 | "time": "2015-06-21 13:50:34" 159 | }, 160 | { 161 | "name": "phpunit/php-timer", 162 | "version": "1.0.7", 163 | "source": { 164 | "type": "git", 165 | "url": "https://github.com/sebastianbergmann/php-timer.git", 166 | "reference": "3e82f4e9fc92665fafd9157568e4dcb01d014e5b" 167 | }, 168 | "dist": { 169 | "type": "zip", 170 | "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3e82f4e9fc92665fafd9157568e4dcb01d014e5b", 171 | "reference": "3e82f4e9fc92665fafd9157568e4dcb01d014e5b", 172 | "shasum": "" 173 | }, 174 | "require": { 175 | "php": ">=5.3.3" 176 | }, 177 | "type": "library", 178 | "autoload": { 179 | "classmap": [ 180 | "src/" 181 | ] 182 | }, 183 | "notification-url": "https://packagist.org/downloads/", 184 | "license": [ 185 | "BSD-3-Clause" 186 | ], 187 | "authors": [ 188 | { 189 | "name": "Sebastian Bergmann", 190 | "email": "sb@sebastian-bergmann.de", 191 | "role": "lead" 192 | } 193 | ], 194 | "description": "Utility class for timing", 195 | "homepage": "https://github.com/sebastianbergmann/php-timer/", 196 | "keywords": [ 197 | "timer" 198 | ], 199 | "time": "2015-06-21 08:01:12" 200 | }, 201 | { 202 | "name": "phpunit/php-token-stream", 203 | "version": "1.2.2", 204 | "source": { 205 | "type": "git", 206 | "url": "https://github.com/sebastianbergmann/php-token-stream.git", 207 | "reference": "ad4e1e23ae01b483c16f600ff1bebec184588e32" 208 | }, 209 | "dist": { 210 | "type": "zip", 211 | "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/ad4e1e23ae01b483c16f600ff1bebec184588e32", 212 | "reference": "ad4e1e23ae01b483c16f600ff1bebec184588e32", 213 | "shasum": "" 214 | }, 215 | "require": { 216 | "ext-tokenizer": "*", 217 | "php": ">=5.3.3" 218 | }, 219 | "type": "library", 220 | "extra": { 221 | "branch-alias": { 222 | "dev-master": "1.2-dev" 223 | } 224 | }, 225 | "autoload": { 226 | "classmap": [ 227 | "PHP/" 228 | ] 229 | }, 230 | "notification-url": "https://packagist.org/downloads/", 231 | "include-path": [ 232 | "" 233 | ], 234 | "license": [ 235 | "BSD-3-Clause" 236 | ], 237 | "authors": [ 238 | { 239 | "name": "Sebastian Bergmann", 240 | "email": "sb@sebastian-bergmann.de", 241 | "role": "lead" 242 | } 243 | ], 244 | "description": "Wrapper around PHP's tokenizer extension.", 245 | "homepage": "https://github.com/sebastianbergmann/php-token-stream/", 246 | "keywords": [ 247 | "tokenizer" 248 | ], 249 | "time": "2014-03-03 05:10:30" 250 | }, 251 | { 252 | "name": "phpunit/phpunit", 253 | "version": "3.7.x-dev", 254 | "source": { 255 | "type": "git", 256 | "url": "https://github.com/sebastianbergmann/phpunit.git", 257 | "reference": "38709dc22d519a3d1be46849868aa2ddf822bcf6" 258 | }, 259 | "dist": { 260 | "type": "zip", 261 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/38709dc22d519a3d1be46849868aa2ddf822bcf6", 262 | "reference": "38709dc22d519a3d1be46849868aa2ddf822bcf6", 263 | "shasum": "" 264 | }, 265 | "require": { 266 | "ext-ctype": "*", 267 | "ext-dom": "*", 268 | "ext-json": "*", 269 | "ext-pcre": "*", 270 | "ext-reflection": "*", 271 | "ext-spl": "*", 272 | "php": ">=5.3.3", 273 | "phpunit/php-code-coverage": "~1.2", 274 | "phpunit/php-file-iterator": "~1.3", 275 | "phpunit/php-text-template": "~1.1", 276 | "phpunit/php-timer": "~1.0", 277 | "phpunit/phpunit-mock-objects": "~1.2", 278 | "symfony/yaml": "~2.0" 279 | }, 280 | "require-dev": { 281 | "pear-pear.php.net/pear": "1.9.4" 282 | }, 283 | "suggest": { 284 | "phpunit/php-invoker": "~1.1" 285 | }, 286 | "bin": [ 287 | "composer/bin/phpunit" 288 | ], 289 | "type": "library", 290 | "extra": { 291 | "branch-alias": { 292 | "dev-master": "3.7.x-dev" 293 | } 294 | }, 295 | "autoload": { 296 | "classmap": [ 297 | "PHPUnit/" 298 | ] 299 | }, 300 | "notification-url": "https://packagist.org/downloads/", 301 | "include-path": [ 302 | "", 303 | "../../symfony/yaml/" 304 | ], 305 | "license": [ 306 | "BSD-3-Clause" 307 | ], 308 | "authors": [ 309 | { 310 | "name": "Sebastian Bergmann", 311 | "email": "sebastian@phpunit.de", 312 | "role": "lead" 313 | } 314 | ], 315 | "description": "The PHP Unit Testing framework.", 316 | "homepage": "http://www.phpunit.de/", 317 | "keywords": [ 318 | "phpunit", 319 | "testing", 320 | "xunit" 321 | ], 322 | "time": "2014-10-17 09:04:17" 323 | }, 324 | { 325 | "name": "phpunit/phpunit-mock-objects", 326 | "version": "1.2.x-dev", 327 | "source": { 328 | "type": "git", 329 | "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", 330 | "reference": "c39c4511c3b007539eb170c32cbc2af49a07351a" 331 | }, 332 | "dist": { 333 | "type": "zip", 334 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/c39c4511c3b007539eb170c32cbc2af49a07351a", 335 | "reference": "c39c4511c3b007539eb170c32cbc2af49a07351a", 336 | "shasum": "" 337 | }, 338 | "require": { 339 | "php": ">=5.3.3", 340 | "phpunit/php-text-template": ">=1.1.1@stable" 341 | }, 342 | "require-dev": { 343 | "phpunit/phpunit": "3.7.*@dev" 344 | }, 345 | "suggest": { 346 | "ext-soap": "*" 347 | }, 348 | "type": "library", 349 | "extra": { 350 | "branch-alias": { 351 | "dev-master": "1.2.x-dev" 352 | } 353 | }, 354 | "autoload": { 355 | "classmap": [ 356 | "PHPUnit/" 357 | ] 358 | }, 359 | "notification-url": "https://packagist.org/downloads/", 360 | "include-path": [ 361 | "" 362 | ], 363 | "license": [ 364 | "BSD-3-Clause" 365 | ], 366 | "authors": [ 367 | { 368 | "name": "Sebastian Bergmann", 369 | "email": "sb@sebastian-bergmann.de", 370 | "role": "lead" 371 | } 372 | ], 373 | "description": "Mock Object library for PHPUnit", 374 | "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", 375 | "keywords": [ 376 | "mock", 377 | "xunit" 378 | ], 379 | "time": "2014-02-16 12:43:56" 380 | }, 381 | { 382 | "name": "symfony/yaml", 383 | "version": "2.8.x-dev", 384 | "source": { 385 | "type": "git", 386 | "url": "https://github.com/symfony/yaml.git", 387 | "reference": "f65177d7093bc29aefebfbdbe496b9e3a6292653" 388 | }, 389 | "dist": { 390 | "type": "zip", 391 | "url": "https://api.github.com/repos/symfony/yaml/zipball/f65177d7093bc29aefebfbdbe496b9e3a6292653", 392 | "reference": "f65177d7093bc29aefebfbdbe496b9e3a6292653", 393 | "shasum": "" 394 | }, 395 | "require": { 396 | "php": ">=5.3.9" 397 | }, 398 | "type": "library", 399 | "extra": { 400 | "branch-alias": { 401 | "dev-master": "2.8-dev" 402 | } 403 | }, 404 | "autoload": { 405 | "psr-4": { 406 | "Symfony\\Component\\Yaml\\": "" 407 | }, 408 | "exclude-from-classmap": [ 409 | "/Tests/" 410 | ] 411 | }, 412 | "notification-url": "https://packagist.org/downloads/", 413 | "license": [ 414 | "MIT" 415 | ], 416 | "authors": [ 417 | { 418 | "name": "Fabien Potencier", 419 | "email": "fabien@symfony.com" 420 | }, 421 | { 422 | "name": "Symfony Community", 423 | "homepage": "https://symfony.com/contributors" 424 | } 425 | ], 426 | "description": "Symfony Yaml Component", 427 | "homepage": "https://symfony.com", 428 | "time": "2015-11-18 13:45:00" 429 | } 430 | ], 431 | "aliases": [], 432 | "minimum-stability": "dev", 433 | "stability-flags": [], 434 | "prefer-stable": false, 435 | "prefer-lowest": false, 436 | "platform": { 437 | "php": ">= 5.3" 438 | }, 439 | "platform-dev": [] 440 | } 441 | -------------------------------------------------------------------------------- /phpunit.php: -------------------------------------------------------------------------------- 1 | 2 |