Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
73.53% covered (warning)
73.53%
25 / 34
66.67% covered (warning)
66.67%
2 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
CsrfGuard
73.53% covered (warning)
73.53%
25 / 34
66.67% covered (warning)
66.67%
2 / 3
17.64
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
4
 call
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 check
68.97% covered (warning)
68.97%
20 / 29
0.00% covered (danger)
0.00%
0 / 1
11.42
1<?php
2/**
3 * CSRF Guard, modified from https://github.com/codeguy/Slim-Extras
4 *
5 * Use this middleware with your Slim Framework application
6 * to protect you from CSRF attacks.
7 *
8 * USAGE
9 *
10 * $app = new \Slim\Slim();
11 * $app->add(new \Slim\Extras\Middleware\CsrfGuard());
12 *
13 */
14namespace Slim\Extras\Middleware;
15
16class CsrfGuard extends \Slim\Middleware
17{
18    /**
19     * CSRF token key name.
20     *
21     * @var string
22     */
23    protected $key;
24
25    /**
26     * Constructor.
27     *
28     * @param string    $key        The CSRF token key name.
29     * @return void
30     */
31    public function __construct($key = 'csrf_token')
32    {
33        if (! is_string($key) || empty($key) || preg_match('/[^a-zA-Z0-9\-\_]/', $key)) {
34            throw new \OutOfBoundsException('Invalid CSRF token key "' . $key . '"');
35        }
36
37        $this->key = $key;
38    }
39
40    /**
41     * Call middleware.
42     *
43     * @return void
44     */
45    public function call() 
46    {
47        // Attach as hook.
48        $this->app->hook('slim.before', array($this, 'check'));
49
50        // Call next middleware.
51        $this->next->call();
52    }
53
54    /**
55     * Check CSRF token is valid.
56     * Note: Also checks POST data to see if a Moneris RVAR CSRF token exists.
57     *
58     * @return void
59     */
60    public function check() {
61        // Check sessions are enabled.
62        if (session_id() === '') {
63            throw new \Exception('Sessions are required to use the CSRF Guard middleware.');
64        }
65
66        if (! isset($_SESSION[$this->key])) {
67            if (function_exists('openssl_random_pseudo_bytes')) {
68                $rand_num = openssl_random_pseudo_bytes(16);//pull 16 bytes from /dev/random
69            }else{
70                /*
71                    RYO(Roll Your Own) random number gen.
72                    only used in the event openssl isn't available
73                */
74                $rand = array();
75                for($i = 0; $i < 64; $i++) {
76                    $random = mt_rand(rand(0,65012), mt_getrandmax());//get a random number between rand(0,65012) and mt rand max
77                    $rand[$i] = mt_rand($i, $random); //add an array key of $i and a value of a number between $i and the first random number
78                }
79                $rand = array_sum($rand); //shuffle the random number, then sum the values
80                $rand_num = str_shuffle($rand * 64); //multiply the rand number by 64 and shuffle the string.
81            }
82            if(isset($rand_num)) {
83                $build_string = $rand_num . serialize($_SERVER) . time();
84                if(isset($build_string)) {
85                    $token = hash('whirlpool', str_shuffle($build_string));
86                } else {
87                    throw new \Exception('Could not generate a random number for the CSRF token!');
88                }
89            } else {
90                throw new \Exception('Could not generate a random number for the CSRF token!');
91            }
92            $_SESSION[$this->key] = $token; //sha1(serialize($_SERVER) . rand(0, 0xffffffff));
93        }
94
95        $token = $_SESSION[$this->key];
96
97        // Validate the CSRF token.
98        if (in_array($this->app->request()->getMethod(), array('POST', 'PUT', 'DELETE'))) {
99            $userToken = $this->app->request()->post($this->key);
100            if ($token !== $userToken) {
101                $this->app->alerts->addMessage('danger', 'Your session has expired. Please refresh the page and try again.');
102                $this->app->halt(400);
103            }
104        }
105
106        // Assign CSRF token key and value to view.
107        $this->app->view()->appendData(array(
108            'csrf_key'      => $this->key,
109            'csrf_token'    => $token,
110            'syncfusion_license' => $_ENV['SYNCFUSION_LICENSE'] ?? '',
111        ));
112    }
113}