[php/sql] eigen session handler

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

  • Saven
  • Registratie: December 2006
  • Laatst online: 19-09 14:15

Saven

Administrator

Topicstarter
Hi daar,

Eigenlijk het volgende; ik heb gekozen om een eigen session handler te gebruiken i.c.m. een database. Heb hier t internet enige tijd op nagezocht en een beetje de puzzelstukjes aan elkaar verbonden. Heb daarmee de volgende class gemaakt.

init() functie is de constructor die door mijn framework wordt aangeroepen
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
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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
class session
{
    public $core;
    
    private $sess_print;
    
    public function init()
    {
        session_set_save_handler
        (
            array(&$this, 'open'),
            array(&$this, 'close'),
            array(&$this, 'read'),
            array(&$this, 'write'),
            array(&$this, 'destroy'),
            array(&$this, 'gc')
        );
        
        session_start();
        
        /*
            Werkt niet, omdat er bij het eerste bezoek nog geen sessie in de database staat
            Dus hij destroyt hem altijd > gevolg is dat er nooit een sessie komt
        */
        if( $this->fingerprint() != $this->sess_print)
        {
            //session_destroy();
            //even uitgecomment, omdat t toch niet werkt
        }
    }
    
    private function fingerprint()
    {
        $print  = @$_SERVER['HTTP_USER_AGENT'].'ennogwatzooi';
        
        return sha1($print);
    }
    
    public function get($key)
    {
        if( isset($_SESSION[$key]) )
        {
            return $_SESSION[$key];
        }
        else
        {
            return false;
        }
    }
    
    public function delete_cookie()
    {
        setcookie(session_name(), '', -99999);
    }
    
    public function open($path, $name)
    {
        return true;
    }
    
    public function close()
    {
        return true;
    }
    
    public function read($sid)
    {
        $query = $this->core->db->prepare(
        "
            SELECT
                id, data, fingerprint, last_access
            FROM
                sessions
            WHERE
                id = :sess_id
            AND
                fingerprint = :print
            LIMIT 1
        ");
        
        $query->bindParam(':sess_id', $sid, PDO::PARAM_INT);
        $query->bindParam(':print', $this->fingerprint(), PDO::PARAM_STR);
        
        $query->execute();
        
        if( $query->rowCount() == 1 )
        {
            $f = $query->fetch(PDO::FETCH_ASSOC);
            
            /*
                fingerprint in een variable zetten zodat we in de
                init() kunnen controleren of die overeenkomt
            */
            $this->sess_print = $f['fingerprint'];
            
            return $f['data'];
        }
        else
        {
            return false;
        }
    }
    
    public function write($sid, $data)
    {
        $query = $this->core->db->prepare(
        "
            INSERT INTO
                sessions
            SET
                id = :sess_id,
                data = :sess_data,
                last_access = UNIX_TIMESTAMP(),
                fingerprint = :print,
                ip = :ip
            ON DUPLICATE KEY
            UPDATE
                last_access = UNIX_TIMESTAMP()
        ");
        
        $query->bindParam(':sess_id', $sid, PDO::PARAM_STR);
        $query->bindParam(':sess_data', $data, PDO::PARAM_STR);
        $query->bindParam(':print', $this->fingerprint(), PDO::PARAM_STR);
        $query->bindParam(':ip', $_SERVER['REMOTE_ADDR'], PDO::PARAM_STR);
        
        return $query->execute();
    }
    
    public function destroy($sid)
    {
        $query = $this->core->db->prepare(
        "
            DELETE FROM
                sessions
            WHERE
                id = :sess_id
            LIMIT
                1
        ");
        
        $query->bindParam(':sess_id', $sid, PDO::PARAM_STR);
        
        return $query->execute();
    }
    
    public function gc($lifetime)
    {
        $time = time() - $lifetime;
        
        $query = $this->core->db->prepare(
        "
            DELETE FROM
                sessions
            WHERE
                last_access < :time
            LIMIT
             1
        ");
        
        $query->bindParam(':time', $time, PDO::PARAM_INT);
        
        return $query->execute();
    }
}


Dit spreekt denk ik wel voor zich, maar als er iets onduidelijk is hoor ik het graag.
Het komt er in feite op neer dat ik de sessie aan een 'fingerprint' wil koppelen. Zodat als er -hoe dan ook- een sessie gestolen wordt (dmv cookie stelen oid) diegene daar niks mee kan.

Dit werkt nu een beetje, de query in mijn read() functie heeft dat al als voorwaarde. Alleen als ik de sessie cookie van de ene browser kopieër naar de andere browser, denkt de site wél dat dat mijn session_id is.
Korter gezegd: hij pakt niet de sessie data uit mijn database, maar php denkt wel dat session_id() de gestolen cookie is.

Ook worden wel updates doorgevoerd aan de sessie, in mijn geval de "last_access" veld, wordt wel elke keer geupdate.


Als 'oplossing' wilde ik in mijn read() functie de fingerprint uit de database halen, en in mijn init() vergelijken met de echte fingerprint(). Als deze niet overeenkomen, de sessie vernietigen. Hier zitten alleen een paar haken en ogen aan.

De eerste is dat het eigenlijk helemaal niet werkt:
Werkt niet, omdat er bij het eerste bezoek nog geen sessie in de database staat
Dus hij destroyt hem altijd > gevolg is dat er nooit een sessie komt
De tweede is dat als dit zou werken, de sessie voor de 'echte' gebruiker ook verloren gaat, waardoor hij/zij een nieuwe sessie krijgt (cq opnieuw moet inloggen).

Iemand een wél idee hoe ik dit fatsoenlijk werkend kan oplossen? :)

Acties:
  • 0 Henk 'm!

  • dusty
  • Registratie: Mei 2000
  • Laatst online: 15-09 18:24

dusty

Celebrate Life!

Je maakt je eigen sessie handler, maar gebruikt toch session_start(); van php?

Beetje onlogisch niet? Wat dus betekent dus dat jouw sessie handler afhangt van de sessie handler van php; juist iets wat je wilt ontwijken als je je eigen sessie handler aan het maken bent.

Los je dat probleem op, zal je ontdekken dat het "zichzelf vernietigen" ook is opgelost.

Voor je tweede probleem; ik zou zeggen niet de echte gebruiker uitloggen, maar de "hacker" loggen, gaat het "te vaak" fout voor de "hacker" dan zet je een tijdelijke ban waardoor je zelfs de sessie niet meer checkt voor de "hacker" maar gewoon aanneemt dat de sessie niet geldig is voor de "hacker". (en de hacker ondertussen maar proberen in te loggen :+) de echte gebruiker hoeft er uiteraard niets van te merken.

Back In Black!
"Je moet haar alleen aan de ketting leggen" - MueR


Acties:
  • 0 Henk 'm!

  • Saven
  • Registratie: December 2006
  • Laatst online: 19-09 14:15

Saven

Administrator

Topicstarter
met een eigen session handler heb je meer controle over de php sessie functionaliteit. Hij override de default php session handler, dus kan alsnog session_start() en $_SESSION gebruiken :)

Zichzelf vernietigen oplossen gaat dus niet 1 2 3 zoals jij wil :P

Het gaat niet per se over een echte 'member' , ook gasten krijgen een sessie, aangezien session_start() op elke pagina wordt uitgevoerd. De cookie van de 'hacker' moet dus verwijderd worden. Op die manier heeft de echte gebruiker geen last van dat zijn hele sessie uit de database gaat. Waar zou ik dat dan het beste af kunnen vangen?

In de destructor controleren op fingerprint? Of in de close() ? Of is de sessie voor die tijd al geupdate? (last_access wordt nu namelijk nog geupdate ook als de fingerprint niet matcht)

Acties:
  • 0 Henk 'm!

  • CyBeR
  • Registratie: September 2001
  • Niet online

CyBeR

💩

dusty schreef op maandag 25 maart 2013 @ 00:29:
Je maakt je eigen sessie handler, maar gebruikt toch session_start(); van php?

Beetje onlogisch niet? Wat dus betekent dus dat jouw sessie handler afhangt van de sessie handler van php; juist iets wat je wilt ontwijken als je je eigen sessie handler aan het maken bent.
Nee, je plakt in essentie je eigen storage backend achter de session mechanieken van php zelf. Werkt prima en is precies wat je wilt.


TS: wat je wilt kan eigenlijk gewoon niet. Er is geen enkele manier om dat te beveiligen zonder dat je er met een minimale moeite omheen kunt, omdat je gewoon niet genoeg controle hebt over de client. Het enige wat je hebt is wat de client jou stuurt, en met uitzondering van het IP-adres kan de client dat compleet naar eigen believen aanpassen.

M.a.w: het enige wat je kunt doen is de sessie koppelen aan een IP-adres en geloof me dat is irritant voor de gebruiker die wel 's van plek verandert.

Websites beveiligen doe je met TLS.

All my posts are provided as-is. They come with NO WARRANTY at all.


Acties:
  • 0 Henk 'm!

  • dusty
  • Registratie: Mei 2000
  • Laatst online: 15-09 18:24

dusty

Celebrate Life!

CyBeR schreef op maandag 25 maart 2013 @ 01:18:
[...]
Nee, je plakt in essentie je eigen storage backend achter de session mechanieken van php zelf. Werkt prima en is precies wat je wilt.
[...]
Dat is dan geen "Eigen Session Handler."

Back In Black!
"Je moet haar alleen aan de ketting leggen" - MueR


Acties:
  • 0 Henk 'm!

  • CyBeR
  • Registratie: September 2001
  • Niet online

CyBeR

💩

dusty schreef op maandag 25 maart 2013 @ 01:45:
[...]

Dat is dan geen "Eigen Session Handler."
Helemaal zelfs sessions handlen is gewoon dom als dat al voor je gedaan wordt. De storage echter is een ander punt; php's default handler is gebaseerd op het in /tmp opslaan van files met informatie, wat al meteen stuk gaat als je load balanced werkt. Dus dat kun je implementatiespecifiek maken.

En dat heet bij PHP een "eigen session handler".

All my posts are provided as-is. They come with NO WARRANTY at all.


Acties:
  • 0 Henk 'm!

  • Saven
  • Registratie: December 2006
  • Laatst online: 19-09 14:15

Saven

Administrator

Topicstarter
CyBeR schreef op maandag 25 maart 2013 @ 01:18:
[...]


Nee, je plakt in essentie je eigen storage backend achter de session mechanieken van php zelf. Werkt prima en is precies wat je wilt.


TS: wat je wilt kan eigenlijk gewoon niet. Er is geen enkele manier om dat te beveiligen zonder dat je er met een minimale moeite omheen kunt, omdat je gewoon niet genoeg controle hebt over de client. Het enige wat je hebt is wat de client jou stuurt, en met uitzondering van het IP-adres kan de client dat compleet naar eigen believen aanpassen.

M.a.w: het enige wat je kunt doen is de sessie koppelen aan een IP-adres en geloof me dat is irritant voor de gebruiker die wel 's van plek verandert.

Websites beveiligen doe je met TLS.
Ja dat klopt, maar het is meer bedoeld als extra laag. De gebruiker weet niet waaruit de fingerprint bestaat, en als iemand de fingerprint wil spoofen zou hij eerst een kijkje in de code moeten nemen. Daar hoort het ip-adres in ieder geval niet bij trouwens :)

Maar de essentie is gewoon, dat hij de sessie blijft updaten (last_access) terwijl hij eigenlijk de sessie-cookie zou moeten verwijderen (of de sessie_destroyen, gaat even om het idee) Daar kom ik even niet over uit hoe te doen

Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Saven schreef op maandag 25 maart 2013 @ 12:27:
De gebruiker weet niet waaruit de fingerprint bestaat
Ah, de fameuze "security through obscurity" :X
Saven schreef op maandag 25 maart 2013 @ 12:27:
en als iemand de fingerprint wil spoofen zou hij eerst een kijkje in de code moeten nemen
Helemaal niet; dan hoeft die iemand alleen maar met een tool als Wireshark of Fiddler2 of zelfs gewoon de browser-eigen tools (Firebug/IE F12 Dev.tools/Chrome Dev.tools/Safari Dev.tools/Opera Dragonfly) te kijken wat er verstuurd wordt en exact diezelfde zaken te versturen. Hooguit 10 seconden werk en met een sniffer ook nog eens über makkelijk te hijacken op, bijvoorbeeld, draadloze netwerken.
Saven schreef op maandag 25 maart 2013 @ 12:27:
Daar hoort het ip-adres in ieder geval niet bij trouwens :)
Het enige dat (ietwat) lastiger te spoofen is. Gefeliciteerd; het wiel dat je zojuist hebt uitgevonden is met deze kers op de taart nu helemaal vierkant 8)7
Saven schreef op maandag 25 maart 2013 @ 12:27:
Maar de essentie is gewoon, dat hij de sessie blijft updaten (last_access) terwijl hij eigenlijk de sessie-cookie zou moeten verwijderen (of de sessie_destroyen, gaat even om het idee) Daar kom ik even niet over uit hoe te doen
De essentie is dat je beter je tijd kunt steken in een nieuw ontwerp; het verwijderen van cookies, destroyen van sessies etc. is wel 't minste van je problemen ;)

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • Saven
  • Registratie: December 2006
  • Laatst online: 19-09 14:15

Saven

Administrator

Topicstarter
RobIII schreef op maandag 25 maart 2013 @ 13:05:
[...]

Ah, de fameuze "security through obscurity" :X


[...]

Helemaal niet; dan hoeft die iemand alleen maar met een tool als Wireshark of Fiddler2 of zelfs gewoon de browser-eigen tools (Firebug/IE F12 Dev.tools/Chrome Dev.tools/Safari Dev.tools/Opera Dragonfly) te kijken wat er verstuurd wordt en exact diezelfde zaken te versturen. Hooguit 10 seconden werk en met een sniffer ook nog eens über makkelijk te hijacken op, bijvoorbeeld, draadloze netwerken.


[...]

Het enige dat (ietwat) lastiger te spoofen is. Gefeliciteerd; het wiel dat je zojuist hebt uitgevonden is met deze kers op de taart nu helemaal vierkant 8)7


[...]

De essentie is dat je beter je tijd kunt steken in een nieuw ontwerp; het verwijderen van cookies, destroyen van sessies etc. is wel 't minste van je problemen ;)
Ok ondanks je onprofessionele kortzichtige reactie zal ik toch even reageren.
In de eerste plaats wordt de fingerprint gehasht, waardoor iemand dus niet weet hoe die is opgebouwd. Je tweede opmerking gaat dan ook niet op.

Het is ook helemaal geen security through obsecurity, het doel van het koppelen van de sessie aan een fingerprint is dan ook niet om het onmogelijk te maken om de sessie te kopieëren, hooguit wat lastiger. Ik kies expres niet voor een IP lock omdat dat weer ongewenste effecten kan hebben (dynamisch ip bijv.)

Dus dat gezegd te hebben, heb ik het volgende geprobeerd. Aangezien php eerst read() voor hij write() heb ik mijn read() functie omgegooid, om daar te controleren op fingerprint.
Helaas werkt dit niet zoals ik wilde:
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
    public function write($sid, $data)
    {
        $get = $this->core->db->prepare(
        "
            SELECT
                id, fingerprint
            FROM
                sessions
            WHERE
                id = :sess_id
            LIMIT
                1
        ");
        
        $get->bindParam(':sess_id', $sid, PDO::PARAM_STR);
        
        $get->execute();
        
        if( $get->rowCount() == 1 )
        {
            $f = $get->fetch(PDO::FETCH_ASSOC);
            
            if( $f['fingerprint'] != $this->fingerprint() )
            {
                session_destroy();
            }
            else
            {
                $upd = $this->core->db->prepare(
                "
                    UPDATE
                        sessions
                    SET
                        data = :sess_data,
                        last_access = UNIX_TIMESTAMP()
                    WHERE
                        id = :sess_id
                    LIMIT
                        1
                ");
                
                $upd->bindParam(':sess_id', $sid, PDO::PARAM_STR);
                $upd->bindParam(':sess_data', $data, PDO::PARAM_STR);
                
                $upd->execute();
            }
        }
        else
        {
            $ins = $this->core->db->prepare(
            "
                INSERT INTO
                    sessions
                SET
                    id = :sess_id,
                    data = :sess_data,
                    last_access = UNIX_TIMESTAMP(),
                    fingerprint = :print,
                    ip = :ip
            ");
            
            $ins->bindParam(':sess_id', $sid, PDO::PARAM_STR);
            $ins->bindParam(':sess_data', $data, PDO::PARAM_STR);
            $ins->bindParam(':print', $this->fingerprint(), PDO::PARAM_STR);
            $ins->bindParam(':ip', $_SERVER['REMOTE_ADDR'], PDO::PARAM_STR);
            
            $ins->execute();
        }
    }


Ik krijg namelijk de volgende foutmelding als ik een sessie wil hijacken:
Warning: session_destroy() [function.session-destroy]: Trying to destroy uninitialized session in


als ik de cookie wil verwijderen (m.b.v. this->delete_cookie()) krijg ik de beroemde melding
Warning: Cannot modify header information - headers already sent by 


Hoe kan ik dan in hemelsnaam de sessie verwijderen voordat er iets geupdate wordt (in mijn geval de 'last_access' veld in de tabel sessions)?

Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Saven schreef op maandag 25 maart 2013 @ 13:23:
[...]

Ok ondanks je onprofessionele kortzichtige reactie zal ik toch even reageren.
Helaas was dat een mijn professionele mening ;)
Saven schreef op maandag 25 maart 2013 @ 13:23:
In de eerste plaats wordt de fingerprint gehasht
Nog makkelijker; dan hoef ik alleen maar de hash te sniffen en die (ook) te sturen als hacker zijnde. Hoef ik me niet eens te bekommeren over waar die hash uit wordt opgebouwd ;) Dit is juist pracht voorbeeld van security through obscurity.
Saven schreef op maandag 25 maart 2013 @ 13:23:
waardoor iemand dus niet weet hoe die is opgebouwd.
Want een stukje JS ontleden (of, heck, je doet 't in Flash of <insert_andere_techniek_hier>) is rocket science? Je bepaalt de fingerprint (en diens hash) client-side. Het enige deel waar je géén controle over hebt in de keten.
Saven schreef op maandag 25 maart 2013 @ 13:23:
Je tweede opmerking gaat dan ook niet op.
I beg to differ ;)
Saven schreef op maandag 25 maart 2013 @ 13:23:
Het is ook helemaal geen security through obsecurity, het doel van het koppelen van de sessie aan een fingerprint is dan ook niet om het onmogelijk te maken om de sessie te kopieëren, hooguit wat lastiger.
Met "wat lastiger" omschrijf je 't denk ik nog 't best. Maar vraag je dan eens af: waarom al die R&D steken hierin als je hooguit 5 minuten van een kwaadwillende zijn/haar tijd af schaaft? Is het die investering waard?
Saven schreef op maandag 25 maart 2013 @ 13:23:
Ik kies expres niet voor een IP lock omdat dat weer ongewenste effecten kan hebben (dynamisch ip bijv.)
Ik zou me eerder zorgen maken over complete organisaties/netwerken die achter NAT of een proxy zitten waardoor een IP veel eerder nutteloos is. Dynamische IP's wijzigen hooguit eens in de zoveel dagen; een beetje sessie verloopt voor die tijd toch al.

Gewoon een sessie-id + een HTTPS verbinding en je bent al op een veel beter op pad dan je nu bent. De rest is allemaal alleen maar overboddige ballast code die onderhouden moet worden, bugs oplevert/bevat, onnodig werk dat verzet is.

[ Voor 6% gewijzigd door RobIII op 25-03-2013 13:35 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • Saven
  • Registratie: December 2006
  • Laatst online: 19-09 14:15

Saven

Administrator

Topicstarter
RobIII schreef op maandag 25 maart 2013 @ 13:32:
[...]

Helaas was dat een mijn professionele mening ;)


[...]

Nog makkelijker; dan hoef ik alleen maar de hash te sniffen en die (ook) te sturen als hacker zijnde. Hoef ik me niet eens te bekommeren over waar die hash uit wordt opgebouwd ;) Dit is juist pracht voorbeeld van security through obscurity.


[...]

Want een stukje JS ontleden (of, heck, je doet 't in Flash of <insert_andere_techniek_hier>) is rocket science? Je bepaalt de fingerprint (en diens hash) client-side. Het enige deel waar je géén controle over hebt in de keten.


[...]

I beg to differ ;)


[...]

Met "wat lastiger" omschrijf je 't denk ik nog 't best. Maar vraag je dan eens af: waarom al die R&D steken hierin als je hooguit 5 minuten van een kwaadwillende zijn/haar tijd af schaaft? Is het die investering waard?


[...]

Ik zou me eerder zorgen maken over complete organisaties/netwerken die achter NAT of een proxy zitten waardoor een IP veel eerder nutteloos is. Dynamische IP's wijzigen hooguit eens in de zoveel dagen; een beetje sessie verloopt voor die tijd toch al.

Gewoon een sessie-id + een HTTPS verbinding en je bent al op een veel beter op pad dan je nu bent. De rest is allemaal alleen maar overboddige ballast code die onderhouden moet worden, bugs oplevert/bevat, onnodig werk dat verzet is.
Zoals je misschien kunt voorstellen, kan de toon die je in je vorige bericht aansloeg, bij iemand voor de nodige verontwaardiging zorgen ;)

De hash wordt niet gestuurd over de verbinding, maar wordt serverside gegenereerd door en aantal client specifieke waardes door elkaar te husselen.

Dit security through obsecurity vind ik ook een beetje onzin omdat het juist extra waarde biedt ten opzichte van de standaard php methode. HTTPS komt later ook aan de orde, maar dat staat nu even los van mijn sessie laag.

Maar hierdoor wijken we heel erg af van mijn probleem, wat ik in de post boven jou beschreef. Ik zie geen mogelijkheid om de sessie te stoppen / verwijderen / opnieuw te starten vóórdat ik een tabel update

Acties:
  • 0 Henk 'm!

  • TheDevilOnLine
  • Registratie: December 2012
  • Laatst online: 06-06 22:54
Maar als iemand echt wil spoofen kan hij ook gewoon een eigen (lees: gekopieerd van de oorspronkelijke gebruiker) HTTP_USER_AGENT meesturen om het juist niet te laten opvallen dat hij spooft. Op deze manier zou het dan nog werken, de spoofer weet alleen niet waarom het werkt!

Acties:
  • 0 Henk 'm!

  • Saven
  • Registratie: December 2006
  • Laatst online: 19-09 14:15

Saven

Administrator

Topicstarter
TheDevilOnLine schreef op maandag 25 maart 2013 @ 15:25:
Maar als iemand echt wil spoofen kan hij ook gewoon een eigen (lees: gekopieerd van de oorspronkelijke gebruiker) HTTP_USER_AGENT meesturen om het juist niet te laten opvallen dat hij spooft. Op deze manier zou het dan nog werken, de spoofer weet alleen niet waarom het werkt!
alleen is de user agent niet het enige wat verstuurd wordt :) maar ik wil het graag hebben over de kern van mijn probleem :P hoe verwijder ik een sessie / verwijder ik de cookie / maak ik een nieuwe sessie aan, vóórdat hij de tabel update

Acties:
  • 0 Henk 'm!

  • Cartman!
  • Registratie: April 2000
  • Niet online
Je kunt toch simpelweg de sessie ophalen en daarna de fingerprint berekenen en vergelijken met je huidige fingerprint, als ermee geknoeid is mik je hem weg (en log je dit evt).

Acties:
  • 0 Henk 'm!

  • Saven
  • Registratie: December 2006
  • Laatst online: 19-09 14:15

Saven

Administrator

Topicstarter
Cartman! schreef op maandag 25 maart 2013 @ 16:28:
Je kunt toch simpelweg de sessie ophalen en daarna de fingerprint berekenen en vergelijken met je huidige fingerprint, als ermee geknoeid is mik je hem weg (en log je dit evt).
dat doe ik ook (althans dat poog ik) :)

Alleen voordat ik de sessie kan verwijderen, roept php de write() functie nog aan. Bij het eerste bezoek van iemand die een sessie id gestolen heeft, denkt php nog dat de session_id() de gestolen sessie id is. maar ik wil dus dat hij die gestolen sessie verwijdert en een nieuwe sessie aanmaakt

Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Nu online

Janoz

Moderator Devschuur®

!litemod

Ik vermoed toch echt dat je het concept "security by obscurity" niet helemaal begrijpt. De veiligheid die je denkt te kunnen bieden is enkel en alleen gebaseerd op het geheim houden van je source code. Iedereen die ziet wat je doet kan het gelijk omzeilen.

In dit geval gaat dat ontoegelijk makkelijk. Alles wat de client opstuurt is te onderscheppen en na te spelen. Alle velden waarvan jij denkt dat ze iets zeggen over de client is data die de client zelf opstuurt in het request. Het simpel afvangen van een request is genoeg om de sessie over te nemen.

De toevoeging van de hashfunctie is, op het verkorten van de geconcateneerde string na, verder compleet zinloos.


Je initiele probleem is trouwens simpel op te lossen door onderscheid te kunnen maken tussen nieuwe en bestaande sessies. Je hebt al een keurige if constructie in de read staan die dat onderscheid lijkt te maken.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • 0 Henk 'm!

  • dusty
  • Registratie: Mei 2000
  • Laatst online: 15-09 18:24

dusty

Celebrate Life!

Saven schreef op maandag 25 maart 2013 @ 13:23:
[...]
als ik de cookie wil verwijderen (m.b.v. this->delete_cookie()) krijg ik de beroemde melding
Warning: Cannot modify header information - headers already sent by 


Hoe kan ik dan in hemelsnaam de sessie verwijderen voordat er iets geupdate wordt (in mijn geval de 'last_access' veld in de tabel sessions)?
Geen HTML output naar de client sturen totdat je klaar bent met al je headers.

Back In Black!
"Je moet haar alleen aan de ketting leggen" - MueR


Acties:
  • 0 Henk 'm!

  • Saven
  • Registratie: December 2006
  • Laatst online: 19-09 14:15

Saven

Administrator

Topicstarter
dusty schreef op maandag 25 maart 2013 @ 17:27:
[...]

Geen HTML output naar de client sturen totdat je klaar bent met al je headers.
Dat weet ik, maar dat doe ik ook niet. Pas op het einde laad ik mijn template (laatste regel)
$core->tpl->display('index.php');

Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Saven schreef op maandag 25 maart 2013 @ 19:12:
[...]

Dat weet ik, maar dat doe ik ook niet.
Niet bewust misschien, maar er is wél al iets ge-output. Het is dan ook pas een keer of anderhalf miljard keer voorbij gekomen hier en mijn water zegt me dat 't geheid ergens een spatie/tab/BOM is voor een <?php of achter een ?>.

[ Voor 52% gewijzigd door RobIII op 25-03-2013 19:34 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • Saven
  • Registratie: December 2006
  • Laatst online: 19-09 14:15

Saven

Administrator

Topicstarter
RobIII schreef op maandag 25 maart 2013 @ 19:34:
[...]

Niet bewust misschien, maar er is wél al iets ge-output. Het is dan ook pas een keer of anderhalf miljard keer voorbij gekomen hier en mijn water zegt me dat 't geheid ergens een spatie/tab/BOM is voor een <?php of achter een ?>.
Nee dat is niet het geval, je water heeft het fout. Lls ik ergens anders cookies of headers() zet, bijvoorbeeld in de init() functie, werkt het wel. Maarrr ik heb ontdekt dat php de sessie pas write aan het einde van het de executie. Na de display() dus pas.

Das niet zo mooi, want hoe delete ik nu een cookie in die functie?

Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Nu online

Janoz

Moderator Devschuur®

!litemod

Saven schreef op maandag 25 maart 2013 @ 19:50:
[...]

Nee dat is niet het geval, je water heeft het fout. Lls ik ergens anders cookies of headers() zet, bijvoorbeeld in de init() functie, werkt het wel. Maarrr ik heb ontdekt dat php de sessie pas write aan het einde van het de executie.
Wanneer had je dan verwacht dat de write plaats zou vinden? Wanneer denk je dat php weet wat de uiteindelijke waarde van de sessiegegevens zouden moeten zijn?
Na de display() dus pas.
Dus is er al wel output geweest ;)
Das niet zo mooi, want hoe delete ik nu een cookie in die functie?
Euhm... niet in die functie. Maar waarom zou je pas aan het einde van de verwerking je cookie gaan deleten? Dat is toch compleet onzinnig? Ja, het request is illegaal, maar laten we eerst de hele pagina en al zijn handelingen doorvoeren en dan als alles gedaan en doorgevoerd is gaan we de sessie nog eens even invalideren.

Het lijkt me handiger wanneer je op de rem trapt voor je al je acties uithaalt.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Saven schreef op maandag 25 maart 2013 @ 19:50:
Maarrr ik heb ontdekt dat php de sessie pas write aan het einde van het de executie. Na de display() dus pas.
Wat dus effectief betekent dat er wél iets is ge-output voordat de write() plaatsvindt. Dat ik niet weet hoe PHP z'n zaakjes precies regelt achter de schermen kun je mij als dotNetter niet kwalijk nemen, daar bestaat documentatie voor.
Session data is usually stored after your script terminated
Called by normal PHP shutdown, by session_write_close(), or when session_register_shutdown() fails

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • Gomez12
  • Registratie: Maart 2001
  • Laatst online: 17-10-2023
Saven schreef op maandag 25 maart 2013 @ 19:50:
[...]
Das niet zo mooi, want hoe delete ik nu een cookie in die functie?
Basisprincipe van cookies, ze zijn niet simpel te deleten.

Je moet ze ook helemaal niet willen deleten, want het is client-side code en die is per definitie onbetrouwbaar.

Wil je ze echt weghebben dan moet je tig x een redirect doen naar nieuwe pagina's die ze weghalen en dan heel hard gaan bidden dat de client ze ook echt weghaalt.

Je moet ze gewoon server-side invalidaten en gewoon de client-side negeren (nadat je een delete-request hebt gestuurd). Of als je het netjes wilt doen dan stuur je gewoon consequent met elke invalid cookie een delete-request terug.

Er zijn 1001 valide redenen te verzinnen waarom een cookie niet verwijderd wordt (back-knop ingedrukt voordat de data binnen is, browser afgesloten voordat data binnen is, eigenlijk simpelweg alles wat ervoor kan zorgen dat niet alle data geinterpreteerd wordt in de browser van de client, kan ook een ad-blocker oid zijn)

Op het moment dat jouw server-side afhankelijk is van of er geen client-side cookie aanwezig is dan...

Acties:
  • 0 Henk 'm!

  • EvilWhiteDragon
  • Registratie: Februari 2003
  • Laatst online: 22:02
flush(); een optie? Niet erg mooi misschien, maar dan dwing je PHP om alvast wat te sturen naar de client

LinkedIn
BlackIntel


Acties:
  • 0 Henk 'm!

  • DataGhost
  • Registratie: Augustus 2003
  • Laatst online: 21:26

DataGhost

iPL dev

Saven schreef op maandag 25 maart 2013 @ 13:23:
[...]

In de eerste plaats wordt de fingerprint gehasht, waardoor iemand dus niet weet hoe die is opgebouwd. Je tweede opmerking gaat dan ook niet op.
Jawel. Zoals RobIII al aangaf, als je met iets als Wireshark ofzo gewoon de hele request langs ziet komen en die vervolgens exact zo weer stuurt, hoef ik van heel de fingerprint niks te weten. Je server zal uiteindelijk toch dezelfde fingerprint berekenen. Daar gaat het om, je kan niet iets wat een client over een onbeveiligde verbinding stuurt als veilig of zelfs maar bruikbaar als beveiliging beschouwen. Jouw server kan op geen enkele manier onderscheid maken tussen een origineel en een afgeluisterd request. Zie ook Wikipedia: Replay attack.

Nogmaals, de enige praktische en bruikbare oplossing is het zetten van een sessie-cookie over HTTPS en de rest van het verkeer daar ook overheen laten lopen (specifiek: geen van het verkeer over niet-HTTPS). Daar heb je heel je fingerprint niet voor nodig, de PHP-sessiehandler voldoet prima.
Saven schreef op maandag 25 maart 2013 @ 12:27:
[...]

De gebruiker weet niet waaruit de fingerprint bestaat, [...] Daar hoort het ip-adres in ieder geval niet bij trouwens :)
Nu weet iedereen dus waaruit jouw fingerprint wel *kan* bestaan en is er genoeg informatie voor een praktische attack. Aangezien je het IP (het enige 'moeilijke' stukje) niet eens meeneemt is het helemaal triviaal. Als ik het goed begrijp bouw je je fingerprint dus op uit enkel de HTTP-request(headers) van de client. Iedereen met telnet/netcat/whatever, een sniffer, ctrl+c en ctrl+v kan dus een sessie stelen.

[ Voor 21% gewijzigd door DataGhost op 25-03-2013 20:54 ]


Acties:
  • 0 Henk 'm!

  • Freeaqingme
  • Registratie: April 2006
  • Laatst online: 19-09 20:56
Waarom sla je je sessies op in een RDBMS? Over het algemeen schaalt dit vrij slecht omdat het aantal writes veelal nagenoeg gelijk is aan het aantal reads. Als scaling geen issue is, waarom dan afwijken van je filesystem? Als scaling wel een issue is; zou ik eerder kijken naar memcached, of als het persistent moet bijvoorbeeld Redis.

No trees were harmed in creating this message. However, a large number of electrons were terribly inconvenienced.


Acties:
  • 0 Henk 'm!

  • Gomez12
  • Registratie: Maart 2001
  • Laatst online: 17-10-2023
DataGhost schreef op maandag 25 maart 2013 @ 20:48:
[...]
Jouw server kan op geen enkele manier onderscheid maken tussen een origineel en een afgeluisterd request. Zie ook Wikipedia: Replay attack.
Hier zijn wel manieren voor te verzinnen om dit moeilijker te maken, maar mits het niet in een 100% controlled omgeving gebeurt is het omzeilen slechts een sample-grootte probleem.
[...]
Als ik het goed begrijp bouw je je fingerprint dus op uit enkel de HTTP-request(headers) van de client. Iedereen met telnet/netcat/whatever, een sniffer, ctrl+c en ctrl+v kan dus een sessie stelen.
Leuker nog, met die fingerprint dwingt hij mensen opnieuw in te loggen op de voor hun meest random momenten.
Iemand installeert een ad-blocker : Opnieuw inloggen
Iemand installeert een google-bar : Opnieuw inloggen
Iemand installeert een geupdate browser : Opnieuw inloggen
Iemand installeert een extensie die iets met de header doet : Opnieuw inloggen
etc. etc.

Ik denk dat ik na 2 weken al zoiets zou hebben van : Die k*t-site kan nog niet eens onthouden dat ik ingelogd ben. Next...

Finger printing is een kunst en als je de kunst niet beheerst dan wordt het al heel erg snel een drama

Acties:
  • 0 Henk 'm!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
Even voor de grap gekeken. :p In principe hoor je een lege string terug te geven als je sessie niet bestaat bij het lezen. Ik vraag me zelfs eigenlijk af waarom er nu geen oneindige loop ontstaat. Zie de goto in de source van php naar regel 452 in session.c. Succes is gedefinieerd als een string terug, regel 125 in mod_user.c. Edit: Beter gekeken: komt doordat de key niet geinvalideerd is. Anders zou je eens kunnen proberen de key te invalideren of op een andere manier de foutconditie+goto terug te triggeren bij een foute fingerprint. Bij geen resultaat hoor je een lege string terug te geven, of standaard sessie-info. read() is een goed moment om de fingerprint en bijbehorend cookie te zetten, helaas staat de mogelijkheid hiervoor alleen beschreven in de source code en niet in de documentatie.

Overigens is de useragent-string ook aan verandering onderhevig, dus die zou ik niet in de fingerprint willen hebben. Eigenlijk zou alleen een onmogelijke switch tussen OS of browser bijzonder zijn; maar ook dat is makkelijk te faken voor een aanvaller. Iets aan de hand van tijdstippen zou wellicht mogelijk zijn; dan zou je de fingerprint steeds moeten laten veranderen (in zowel db als cookie). Als vorige bezoektijdstippen uit elkaar zijn gelopen, is dat een indicatie voor een aanval. Alternatief kan zelfs dat komen doordat een oud image van je bezoeker is teruggezet, of de machine gecloond is.

NB: Zoals al eerder gezegd; voor verreweg de meeste sites zijn dit soort zaken overigens tamelijk overbodige complexiteit, en loont het totaal niet de moeite om hier werk in te gaan steken. :p

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


Acties:
  • 0 Henk 'm!

  • Gomez12
  • Registratie: Maart 2001
  • Laatst online: 17-10-2023
pedorus schreef op maandag 25 maart 2013 @ 22:40:
Als vorige bezoektijdstippen uit elkaar zijn gelopen, is dat een indicatie voor een aanval. Alternatief kan zelfs dat komen doordat een oud image van je bezoeker is teruggezet, of de machine gecloond is.
Of het is een indicatie dat iemand in een netwerk is gehangen met een foutieve ntp-server of het is een indicatie van zomer / wintertijd, of het is een indicatie dat iemand wat zit te spelen met een tijd-limited iets op zijn eigen pc of... of ....

Acties:
  • 0 Henk 'm!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
Dat was niet helemaal wat ik bedoel. Je gebruikt natuurlijk niet een tijd op de client. Je genereert unieke fingerprints op de server aan de hand van de tijd van een request. Als de fingerprint niet als een van de laatste x gegenereerd is voor die sessie, invalideer je de sessie.

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten

Pagina: 1