[PHP] SESSION over meerdere SUBdomeinen

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Beste tweakers,

Ik had een goed werken website sinds ik gebruik maak van subdomeinen. Werken mijn SESSION niet meer.

Een lid die zich inlogt en vervolgens naar andere subdomein gaat is hij uitgelogt en als hij terug komt is hij wel weer ingelogt. Hoe kan ik een session maken die over meerdere subdomeinen geldig zijn?

Ik heb veel gezocht maar kom er niet uit?
Dit onderstaande stukje is wat in ieder pagina boven aan geincludeert wordt.
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
if(isset($_GET['cikis']) == 1){
    session_unset();
    session_destroy();
    $_SESSION = array();
    setcookie("user_id", "", time() - 3600);
    setcookie("user_password", "", time() - 3600);
    unset($_COOKIE['user_id']);
    unset($_COOKIE['user_password']);
    header("Location: ".$SITE['url']."");
}elseif(isset($_SESSION['user_id'])){
    mysql_query("UPDATE uye SET lastactive = NOW() WHERE id = '".$_SESSION['user_id']."'");
}elseif(isset($_COOKIE['user_id'])){
    $query = mysql_query("SELECT naam,wachtwoord,status FROM uye WHERE id='".$_COOKIE['user_id']."'");
    $object = mysql_fetch_assoc($query);
    $dbnaam = htmlspecialchars($object['naam']);
    $dbpass = htmlspecialchars($object['wachtwoord']);
    $dbstatus = htmlspecialchars($object['status']);
    if($dbpass == $_COOKIE['user_password']){
        $_SESSION['user_id'] = $COOKIE['user_id'];
        $_SESSION['user_status'] = $dbstatus;
        $_SESSION['user_name'] = $dbnaam;
    }else{
        setcookie("user_id", "", time() - 3600);
        setcookie("user_password", "", time() - 3600);
        unset($_COOKIE['user_id']);
        unset($_COOKIE['user_password']);
    }
}



Deze stukje is als voor inloggen.

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
if(isset($_POST['giris'])){
    $query = mysql_query("SELECT id,naam,wachtwoord,status,actief FROM uye WHERE naam='".$_POST['user']."'");
    $object = mysql_fetch_assoc($query);
    $dbpass = htmlspecialchars($object['wachtwoord']);
    $count = mysql_num_rows($query);
    $userpass = md5($_POST['pass']);
    $userid = htmlspecialchars($object['id']);
    $dbnaam = htmlspecialchars($object['naam']);
    $userstatus = htmlspecialchars($object['status']);
    $useractief = htmlspecialchars($object['actief']);
    if($count == 1){
        if($dbpass == $userpass){
            if($useractief == 1){
                $_SESSION['user_id'] = $userid;
                $_SESSION['user_status'] = $userstatus;
                $_SESSION['user_name'] = $dbnaam;
                if($_POST['cookie'] == "do"){
                    setcookie("user_id", $userid, time() + 365 * 86400);
                    setcookie("user_password", $dbpass, time() + 365 * 86400);
                }
            }else{
                echo "Je account is niet geactiveerd. Activeer deze, door op de link in de verzonden e-mail te klikken.<br />\n";
            }
        }else{
            echo "<font color=\"red\">Þifre yanlis</font>";
        }
    }else{
        echo "<font color=\"red\">Lütfen geçerli bir kullanýcý adý giriniz</font>";
    }
}


Met de volgende controleer ik of iemand ingelogt is of niet
PHP:
1
2
3
4
5
if(isset($_SESSION['user_id'])){
/// ingelogt
}else{
// niet ingelogt
}

Acties:
  • 0 Henk 'm!

Verwijderd

Als je "veel" gezocht hebt, waarom heb je niet gekeken op de #1 referentie voor php? http://nl2.php.net/manual/en/function.setcookie.php kijk bij de parameter domain.

Voor sessions check http://nl2.php.net/manual/en/ref.session.php bij session.cookie_domain

Nog een beetje meer effort volgende keer.

[ Voor 29% gewijzigd door Verwijderd op 09-04-2008 15:21 ]


Acties:
  • 0 Henk 'm!

  • gertvdijk
  • Registratie: November 2003
  • Laatst online: 18-09 11:40
Interessant, want dit probleem kom ik ook tegen bij een webprojectje binnenkort. (bookmarked)

Maar ga jij allereerst even heel snel je SQL injection security probleem aanpassen! 8)7
PHP:
1
$query = mysql_query("SELECT id,naam,wachtwoord,status,actief FROM uye WHERE naam='".$_POST['user']."'");

Hier kan een hacker heel gemakkelijk SQL code inserten. Denk aan
code:
1
2; UPDATE uye SET actief = 1 WHERE id=2
voor $_POST['user'] om zijn account te laten activeren.
edit (sql injection)
Verwijderd schreef op woensdag 09 april 2008 @ 15:26:
Hoe kan ik de SQL injection dan voorkomen?
Dus maak ervan:
PHP:
1
$user = mysql_real_escape_string($_POST['user']);

of een nog nettere oplossing hier.

[ Voor 28% gewijzigd door gertvdijk op 09-04-2008 15:33 ]

Kia e-Niro 2021 64 kWh DynamicPlusLine. See my GitHub and my blog for articles on security and other stuff.


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Bedankt voor de links cookie was ik neit opzoek naar maar dit keer zag ik de voglende bij staan: session.cookie_domain. Ik zal kijken hoe ik dit gebruik moet maken.

@Gertvdijk

Hoe kan ik de SQL injection dan voorkomen?

Acties:
  • 0 Henk 'm!

Verwijderd

de waardes in $_POST worden direct achter je query geplakt zonder dat je de input checked.

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Is dit voldoende volgende functie?
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function security($gegevens){
    // kijken of de magic_quotes aan staan    
    if (get_magic_quotes_gpc()){
        // alle slashes strippen
        $gegevens = stripslashes($gegevens);
    }
    // kijken welke php-versie er draait
    if(version_compare(phpversion(),"4.3.0") == "-1"){
        // gegevens van alle mysql-acties ontdoen
        $gegevens = mysql_escape_string($gegevens);
    }else{
        // gegevens van alle mysql-acties ontdoen
        $gegevens = mysql_real_escape_string($gegevens);
    }
    // rare tekens vervangen door html-tekst
    $gegevens = htmlspecialchars($gegevens);
    // alle tags strippen
    $gegevens = strip_tags($gegevens);
    // geef de gegevens terug
    return $gegevens;
}

Acties:
  • 0 Henk 'm!

  • frickY
  • Registratie: Juli 2001
  • Laatst online: 18-09 14:42
Ik denk dat je beter bij het begin kunt beginnen een een tutorial over de basics van security kunt lezen :?

Maar kijk voor een algemene indruk eens naar http://www.php.net/mysql_real_escape_string en zoek eens op "SQL injection" om te lezen wat het precies inhoud.

[ Voor 14% gewijzigd door frickY op 09-04-2008 15:45 ]


Acties:
  • 0 Henk 'm!

  • gertvdijk
  • Registratie: November 2003
  • Laatst online: 18-09 11:40
Je sql injection probleem is wel uitgelegd dacht ik zo.

Nou heb ik e.e.a. uitgezocht over sessions/cookies en subdomeinen. Je moet ervoor zorgen dat je cookie wordt verzonden aan alle subdomeinen door hem op je juiste manier op te laten slaan. (setcookie session_set_cookie_params)
Voorbeeld:
code:
1
2
.domein.tld     TRUE    /  FALSE   1270105626      __utma  173272373.530861431.1198802193.xxx
.mijnsub.domein.tld     TRUE    /  FALSE   1270105626      __utmb  173272373.530861431.1198802193.xxx

De eerste cookie wordt naar alle subdomeinen van domein.tld gestuurd, de tweede alleen naar mijnsub.domein.tld.
Ik vermoed dus dat jij je cookies met het 'www' subdomein laat opslaan.
code:
1
.www.domein.tld     TRUE    /  FALSE   1270105626      __utma  173272373.530861431.1198802193.xxx

Waardoor de cookie niet wordt verzonden bij subdomein.domein.tld

Het lijkt erop de browser gewoon de cookie domain pakt van het huidige adres. Als dat met het www 'subdomein' gebeurt kan ik me voorstellen dat hij dat ook zo opslaat.
Dus of je hele website ombouwen tot het niet bezoeken met www.domein.tld of:
PHP:
1
setcookie("user_id", $userid, time() + 365 * 86400, '/', '.domein.tld');

Eventueel kan je met regexen en $_SERVER['HTTP_HOST'] nog mooiere generiekere code maken.

[ Voor 24% gewijzigd door gertvdijk op 09-04-2008 16:31 ]

Kia e-Niro 2021 64 kWh DynamicPlusLine. See my GitHub and my blog for articles on security and other stuff.


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Bijvoorbeeld.

Ik log in op http://domein.nl maar als ik http://www.domein.nl komt dan ben ik uitgelogdt. Ook anders om.

Hij pakt per subdomein. Maar het is mij even niet gelukt met deze session.cookie_domain. Even verder kijken

Acties:
  • 0 Henk 'm!

  • gertvdijk
  • Registratie: November 2003
  • Laatst online: 18-09 11:40
Da's gek. :/ Hier werkt het prima. (Apache/2.2.3 (Debian) PHP/5.2.0-8+etch10, Firefox 2.0.0.13 Ubuntu Gutsy) Welke server en client software gebruik je?
Kan je ook even kijken wat er precies aan cookie data in je browser staat? In Firefox: Preferences -> Sercurity -> Show cookies
of gewoon een cookies.txt file (onder unix /home/user/.mozilla/firefox/profile-id.default/cookies.txt)
Dat is ook de bedoeling met je huidige code. ;)

[ Voor 16% gewijzigd door gertvdijk op 09-04-2008 16:31 ]

Kia e-Niro 2021 64 kWh DynamicPlusLine. See my GitHub and my blog for articles on security and other stuff.


Acties:
  • 0 Henk 'm!

  • Thomasje
  • Registratie: Augustus 2002
  • Laatst online: 29-05-2024

Thomasje

Semacode

Verwijderd schreef op woensdag 09 april 2008 @ 16:16:
Bijvoorbeeld.

Ik log in op http://domein.nl maar als ik http://www.domein.nl komt dan ben ik uitgelogdt. Ook anders om.

Hij pakt per subdomein. Maar het is mij even niet gelukt met deze session.cookie_domain. Even verder kijken
PHP:
1
ini_set("session.cookie_domain", "domein.nl");


Met bovenstaande code worden alle sessies goed afgehandeld.

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Als ik mijn cookies bekijkt.

Bij iedere bezoek aan andere subdomein maakt de browser een Cookie met PHPSESSID en zijn eigen HOST.

[code=php]
ini_set("session.cookie_domain", "domein.nl");
[code]

Waar moet ik de bovenstaande code plaatsen vlak voor dat ik SESSIONS maakt of gewoon boven aan elke pagina?

Acties:
  • 0 Henk 'm!

  • Thomasje
  • Registratie: Augustus 2002
  • Laatst online: 29-05-2024

Thomasje

Semacode

Verwijderd schreef op woensdag 09 april 2008 @ 16:45:
Als ik mijn cookies bekijkt.

Bij iedere bezoek aan andere subdomein maakt de browser een Cookie met PHPSESSID en zijn eigen HOST.

[code=php]
ini_set("session.cookie_domain", "domein.nl");
[code]

Waar moet ik de bovenstaande code plaatsen vlak voor dat ik SESSIONS maakt of gewoon boven aan elke pagina?
Zo heb ik hem staan.

PHP:
1
2
ini_set("session.cookie_domain", "domein.nl"); 
session_start();

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Bedank Thomasje het is me gelukt.

Ik heb nog een klein probleempje ingelogd blijven als de sessie verlopen is ivm cookie.

Ik heb tijdens het inloggen een checkbox voor mij onthouden.

PHP:
1
2
3
4
if($_POST['cookie'] == "do"){
setcookie("user_id", $userid, time() + 365 * 86400);
setcookie("user_password", $dbpass, time() + 365 * 86400);
}


De cookie wordt inderdaad geplaats als ik de sessie verwijderd n Firefox: Preferences -> Sercurity -> Show cookies

Maar als nog blijf ik niet ingelogd.

Door onderstaande code controleer ik de cookie en maak ik nieuwe sessie aan.
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
if(isset($_COOKIE['user_id'])){
    $query = mysql_query("SELECT naam,wachtwoord,status FROM uye WHERE id='".$_COOKIE['user_id']."'");
    $object = mysql_fetch_assoc($query);
    $dbnaam = htmlspecialchars($object['naam']);
    $dbpass = htmlspecialchars($object['wachtwoord']);
    $dbstatus = htmlspecialchars($object['status']);
    if($dbpass == $_COOKIE['user_password']){
        $_SESSION['user_id'] = $COOKIE['user_id'];
        $_SESSION['user_status'] = $dbstatus;
        $_SESSION['user_name'] = $dbnaam;
    }else{
        setcookie("user_id", "", time() - 3600);
        setcookie("user_password", "", time() - 3600);
        unset($_COOKIE['user_id']);
        unset($_COOKIE['user_password']);
    }
}

Acties:
  • 0 Henk 'm!

  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

setcookie - 5e argument

Intentionally left blank


Acties:
  • 0 Henk 'm!

Verwijderd

$path = "/var/www/Game/sessions";
session_save_path($path);

als je dit in je config zet dan wordt hj altijd op dezelfde plek opgeslagen, en van de zelfde plek geladen. Ik denk dat dit ook zal werken :)

Acties:
  • 0 Henk 'm!

  • Thomasje
  • Registratie: Augustus 2002
  • Laatst online: 29-05-2024

Thomasje

Semacode

Verwijderd schreef op woensdag 09 april 2008 @ 17:08:
$path = "/var/www/Game/sessions";
session_save_path($path);

als je dit in je config zet dan wordt hj altijd op dezelfde plek opgeslagen, en van de zelfde plek geladen. Ik denk dat dit ook zal werken :)
Volgens mij heeft hij een ander probleem nu

Acties:
  • 0 Henk 'm!

  • rhodium
  • Registratie: Augustus 2003
  • Laatst online: 19:11
Een .htaccess met daarin php_value session.cookie_domain .domein.nl werkt prima. Ik gebruik dit zelf altijd.

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Thomasje

$path = "/var/www/Game/sessions";
session_save_path($path);

Deze werkt toch hetzelfde wat jij gaf?

<?php
ini_set("session.cookie_domain", "domein.nl");
session_start();
?>

Acties:
  • 0 Henk 'm!

  • ChessSpider
  • Registratie: Mei 2006
  • Laatst online: 01-08 19:01
gertvdijk schreef op woensdag 09 april 2008 @ 15:24:
Interessant, want dit probleem kom ik ook tegen bij een webprojectje binnenkort. (bookmarked)

Maar ga jij allereerst even heel snel je SQL injection security probleem aanpassen! 8)7
PHP:
1
$query = mysql_query("SELECT id,naam,wachtwoord,status,actief FROM uye WHERE naam='".$_POST['user']."'");

Hier kan een hacker heel gemakkelijk SQL code inserten. Denk aan
code:
1
2; UPDATE uye SET actief = 1 WHERE id=2
voor $_POST['user'] om zijn account te laten activeren.
edit (sql injection)

[...]

Dus maak ervan:
PHP:
1
$user = mysql_real_escape_string($_POST['user']);

of een nog nettere oplossing hier.
Dat is niet waar, je kan geen meerdere queries gescheiden door ; uitvoeren met mysql_query().

SELECT * FROM tabel WHERE uid = '[u]1'; UPDATE tabel SET userrights = 1 WHERE uid = '5[/u]'


Zal niet werken in een mysql_query().


Rest van je bericht klopt natuurlijk 100%.

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Ik heb de SQL injection als volgt gedaan.

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php
function security($gegevens){
    // kijken of de magic_quotes aan staan    
    if (get_magic_quotes_gpc()){
        // alle slashes strippen
        $gegevens = stripslashes($gegevens);
    }
    // kijken welke php-versie er draait
    if(version_compare(phpversion(),"4.3.0") == "-1"){
        // gegevens van alle mysql-acties ontdoen
        $gegevens = mysql_escape_string($gegevens);
    }else{
        // gegevens van alle mysql-acties ontdoen
        $gegevens = mysql_real_escape_string($gegevens);
    }
    // rare tekens vervangen door html-tekst
    $gegevens = htmlspecialchars($gegevens);
    // alle tags strippen
    $gegevens = strip_tags($gegevens);
    // geef de gegevens terug
    return $gegevens;
}
?>


De query als volgt
PHP:
1
2
3
<?php
$query = mysql_query("SELECT id,naam,wachtwoord,status,actief FROM uye WHERE naam='".security($_POST['user'])."'");
?>


Zo zal het veilig genoeg zijn geloof ik.

Acties:
  • 0 Henk 'm!

  • gertvdijk
  • Registratie: November 2003
  • Laatst online: 18-09 11:40
ChessSpider schreef op woensdag 09 april 2008 @ 17:23:
Dat is niet waar, je kan geen meerdere queries gescheiden door ; uitvoeren met mysql_query().
Oh, inderdaad. Ik ging er niet vanuit dat zelfs die beperkingen al in PHP zijn gemaakt ten behoeve van security.

@ TS:
Ja, het is nu wel veilig(er).
Kan je eens wat meer debuggen in je code? Bijvoorbeeld even var_dump'en van je $_COOKIE ofzo. Het probleem lijkt mij namelijk te zitten in je code voor het 'resumen' van je sessie a.d.h.v. een cookie.

@ Thomasje:
Veel eleganter inderdaad via een ini_set. Wist niet dat dat ook werkte in safe mode van PHP (ik ging daar niet vanuit). Omdat veel hosters safe_mode aan hebben staan, zocht ik niet in een php.ini setting.

Kia e-Niro 2021 64 kWh DynamicPlusLine. See my GitHub and my blog for articles on security and other stuff.


Acties:
  • 0 Henk 'm!

  • Thomasje
  • Registratie: Augustus 2002
  • Laatst online: 29-05-2024

Thomasje

Semacode

gertvdijk schreef op woensdag 09 april 2008 @ 18:08:
[...]
@ Thomasje:
Veel eleganter inderdaad via een ini_set. Wist niet dat dat ook werkte in safe mode van PHP (ik ging daar niet vanuit). Omdat veel hosters safe_mode aan hebben staan, zocht ik niet in een php.ini setting.
Ja zo zijn er een hoop ini_set instellingen die je kan doen als safe_mode aan staat.

Acties:
  • 0 Henk 'm!

Verwijderd

Verwijderd schreef op woensdag 09 april 2008 @ 17:33:
Ik heb de SQL injection als volgt gedaan.

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php
function security($gegevens){
    // kijken of de magic_quotes aan staan    
    if (get_magic_quotes_gpc()){
        // alle slashes strippen
        $gegevens = stripslashes($gegevens);
    }
    // kijken welke php-versie er draait
    if(version_compare(phpversion(),"4.3.0") == "-1"){
        // gegevens van alle mysql-acties ontdoen
        $gegevens = mysql_escape_string($gegevens);
    }else{
        // gegevens van alle mysql-acties ontdoen
        $gegevens = mysql_real_escape_string($gegevens);
    }
    // rare tekens vervangen door html-tekst
    $gegevens = htmlspecialchars($gegevens);
    // alle tags strippen
    $gegevens = strip_tags($gegevens);
    // geef de gegevens terug
    return $gegevens;
}
?>


De query als volgt
PHP:
1
2
3
<?php
$query = mysql_query("SELECT id,naam,wachtwoord,status,actief FROM uye WHERE naam='".security($_POST['user'])."'");
?>


Zo zal het veilig genoeg zijn geloof ik.
Duidelijk het werk van iemand die totaal niet snapt wanneer hij wat moet escapen... De functies htmlspecialchars en strip_tags aanroepen voor iets wat de database in moet?

Als je geen HTML in een veld wilt, moet je dat ook niet toelaten. Foute input -> laat gebruiker de input verbeteren.

Als je een variabele wilt laten zien, die geen "goedgekeurde" HTML mag bevatten, haal je er altijd een escape functie over in je templatesysteem, als je die gebruikt voor je output.

De functie version_compare returnt geen string, vergelijk het resultaat dan ook niet met een string. Sowieso moet je die functie niet gebruiken als je wilt zien of een bepaalde functie bestaat. Daarvoor is function_exists.

Sowieso moeten alle servers met magic_quotes_gpc aan worden afgeschoten. Mensen configureren de server maar gewoon goed. Net zoiets als register_globals. Als je nou een library schrijft die door duizenden mensen gebruikt moet worden is het een ander verhaal. Maar als je iets voor een bepaalde klant maakt, kun je best eisen dat ze de boel op een goed geconfigureerde server hosten.

Een functienaam als "security" is overigens gewoon kut. Noem het dan "mega_escape" of "make_safe_for_mysql_query" of whatever.
Pagina: 1