veiligheid van $_SESSION variables

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Gerard Nijboer

Gerard Nijboer

13/10/2009 19:37:00
Quote Anchor link
Hey,

Voor het inloggen op mijn site maak ik gebruik van een PHP session.
Als de variabele $_SESSION['usr_userid'] is ingesteld, ben je ingelogd en heb je dus toegang tot extra pagina's.
Hoe veilig is zo'n systeem? Is het makkelijk te kraken en hoe zou ik het veiliger kunnen maken?
Graag wat tips.

Bedankt!
 
PHP hulp

PHP hulp

25/04/2024 14:03:56
 
Martijn Wieringa

Martijn Wieringa

13/10/2009 19:46:00
Quote Anchor link
Als je gebruik maakt van 'sessies' wordt op de pc van de bezoeker een cookie opgeslagen met hierin zijn SESSION_ID. Elke keer als de bezoeker een nieuwe pagina aanvraagt op jou domein, dan wordt deze cookie meegestuurd zodat jij de bezoeker opnieuw kunt identificeren.

Het gevaar ligt er in dat iemand de SESSION_ID mogelijk kan kopieren, en in aan zijn eigen browser kan toevoegen als cookie. Wanneer deze persoon nu naar jou website gaat, denkt PHP dat het dezelfde bezoeker betreft, omdat deze alleen de SESSION_ID als referentie heeft.

Deze 'feature' noemen we 'session hijacking'.

Wat te doen:
Wat ik standaard doe is o.a. het IP adres & user agent van de gebruiker koppelen aan de betreffende sessie. Wanneer óf het IP, óf de user agent veranderd, reset ik de sessie. Nadeel van deze aanpak is dat iemand met een wisselend IP adres mogelijk opnieuw moet inloggen.



Hier wat PHP code die je inspiratie kan bieden:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
<?php

    // Define urls & paths
    define('ROOT_URL', 'http://www.domainname.tld/';
    define('ROOT_PATH', dirname(__FILE__) . '/');
    define('SESSION_PATH', ROOT_PATH . 'sessions/');

    // Update session path
    session_save_path(SESSION_PATH);


    // Validate & start session
    function __session_start()
    {

        $sSessionId = __session_start_id();

        session_id($sSessionId);
        session_start();

        // Validate session
        if(isset($_SESSION['session']))
        {

            if($_SESSION['session']['REMOTE_ADDR'] && (strcmp($_SESSION['session']['REMOTE_ADDR'], $_SERVER['REMOTE_ADDR']) !== 0)) // IP has changed during session
            {
                session_write_close();
                $sSessionId = __session_start_id(false); // Force a new ID

                session_id($sSessionId);
                session_start();

                $_SESSION['session'] = array();
                $_SESSION['session']['ROOT_URL'] = ROOT_URL;
                $_SESSION['session']['REMOTE_ADDR'] = false; // No IP/SESSION lock
                $_SESSION['session']['HTTP_USER_AGENT'] = (isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '');
                $_SESSION['session']['HTTP_X_FORWARDED_FOR'] = (isset($_SERVER['HTTP_X_FORWARDED_FOR']) ? $_SERVER['HTTP_X_FORWARDED_FOR'] : '');

                die('<p>Your IP has changed during your session! As a protection against <a href="http://en.wikipedia.org/wiki/Session_hijacking" target="_blank">session hijacking</a> your session data is erased!</p><p>Your session is no longer chained to your IP, so it can support multiple IP addresses from now on.</p><p><a href="' . escapeHtml(ROOT_URL) . '">Please continue</a></p>');
            }

            elseif((isset($_GET['core']['session']) && (strcasecmp($_GET['core']['session'], 'reset') === 0)) || (strcmp($_SESSION['session']['ROOT_URL'], ROOT_URL) !== 0) || (strcmp($_SESSION['session']['HTTP_USER_AGENT'], (isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '')) !== 0) || (strcmp($_SESSION['session']['HTTP_X_FORWARDED_FOR'], (isset($_SERVER['HTTP_X_FORWARDED_FOR']) ? $_SERVER['HTTP_X_FORWARDED_FOR'] : '')) !== 0))
            {

                session_write_close();
                $sSessionId = __session_start_id(false); // Force a new ID

                session_id($sSessionId);
                session_start();

                $_SESSION['session'] = array();
                $_SESSION['session']['ROOT_URL'] = ROOT_URL;
                $_SESSION['session']['REMOTE_ADDR'] = $_SERVER['REMOTE_ADDR'];
                $_SESSION['session']['HTTP_USER_AGENT'] = (isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '');
                $_SESSION['session']['HTTP_X_FORWARDED_FOR'] = (isset($_SERVER['HTTP_X_FORWARDED_FOR']) ? $_SERVER['HTTP_X_FORWARDED_FOR'] : '');
            }
        }

        else
        {
            $_SESSION['session'] = array();
            $_SESSION['session']['ROOT_URL'] = ROOT_URL;
            $_SESSION['session']['REMOTE_ADDR'] = $_SERVER['REMOTE_ADDR'];
            $_SESSION['session']['HTTP_USER_AGENT'] = (isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '');
            $_SESSION['session']['HTTP_X_FORWARDED_FOR'] = (isset($_SERVER['HTTP_X_FORWARDED_FOR']) ? $_SERVER['HTTP_X_FORWARDED_FOR'] : '');
        }
    }


    // Lookup session id (or generate a new one)
    function __session_start_id($bRestoreSession = true)
    {

        $sSessionName = session_name();

        do
        {
            $sSessionId = randomCode(64, false, true); // Generate unique ID, hexadecimal
        }
        while(file_exists(session_save_path() . '/sess_' . $sSessionId));

        if($bRestoreSession) // Try to restore session
        {
            if(isset($_GET[$sSessionName]))
            {

                if(preg_match('/^[0-9a-fA-F]{64,64}$/', $_GET[$sSessionName]))
                {

                    $sSessionId = $_GET[$sSessionName];
                }

                else
                {
                    unset($_GET[$sSessionName]);
                }
            }


            if(isset($_COOKIE[$sSessionName]))
            {

                if(preg_match('/^[0-9a-fA-F]{64,64}$/', $_COOKIE[$sSessionName]))
                {

                    $sSessionId = $_COOKIE[$sSessionName];
                }

                else
                {
                    unset($_COOKIE[$sSessionName]);
                }
            }
        }

        else
        {
            unset($_GET[$sSessionName]);
            unset($_COOKIE[$sSessionName]);
        }


        return $sSessionId;
    }


    // Create a random code with N digits.
    function randomCode($iLength = 64, $bUserFriendly = false, $bHex = false)
    {

        if($bUserFriendly)
        {

            /*
                Some fonts use (almost) the same symbols for 'i', 'l' and 'one', same goes for 'o' and 'zero'.
                That's why we removed these characters from the characterlist (UPPERCASE + lowercase).
            */

            if($bHex)
            {

                $aCharacters = array('a', 'b', 'c', 'd', 'c', 'd', 'e', 'f', 'A', 'B', 'C', 'D', 'E', 'F', '2', '3', '4', '5', '6', '7', '8', '9');
            }

            else
            {
                $aCharacters = array('a', 'b', 'c', 'd', 'c', 'd', 'e', 'f', 'g', 'h', 'j', 'k', 'm', 'n', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '2', '3', '4', '5', '6', '7', '8', '9');
            }
        }

        else
        {
            if($bHex)
            {

                $aCharacters = array('a', 'b', 'c', 'd', 'c', 'd', 'e', 'f', 'A', 'B', 'C', 'D', 'E', 'F', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9');
            }

            else
            {
                $aCharacters = array('a', 'b', 'c', 'd', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9');
            }
        }


        $sResult = '';

        for($i = 0; $i < $iLength; $i++) // (62 ^ [$digits] mogelijke codes)
        {
            $sResult .= $aCharacters[rand(0, sizeof($aCharacters) - 1)];
        }


        return $sResult;
    }


?>
Gewijzigd op 01/01/1970 01:00:00 door Martijn Wieringa
 
Michael -

Michael -

13/10/2009 19:57:00
Quote Anchor link
Lees dit eens: Session Hijacking
 
Gerard Nijboer

Gerard Nijboer

13/10/2009 19:59:00
Quote Anchor link
Ziet er goed uit, en compleet duidelijk!
Zijn er verder nog problemen waar ik rekening mee moet houden?
 
Roel -

Roel -

13/10/2009 22:22:00
Quote Anchor link
@Pholeron; bedankt, die methode gebruik ik zelf ook maar die user agent is nog een goede toevoeging :)
 
Martijn Wieringa

Martijn Wieringa

14/10/2009 12:57:00
Quote Anchor link
@Hoithebest
Graag gedaan :)
 



Overzicht Reageren

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.