Permalänk
Medlem

[PHP] Säkerhet och include

Hej, jag funderar på att köra följande kod på en sida:

$page = $_GET['p']; $res = @include($page . '.htm'); if($res != 1) echo '<h1>Sidan kunde ej hittas</h1>Hittade inte ' . $page;

Undrar lite över säkerheten... servern körs i Safe Mode så det skulle inte gå att peka till en extern fil vad jag förstår. Alternativet är att göra en strängmatchning för alla potentiella sidor på sidan och därmed säkerställa att det inte missbrukas.

Jag kommer nog oavsett att göra så, men det är ändå roligt att få veta om det hade varit helt otänkbart ur säkerhetssynpunkt.

Permalänk
Medlem

Kör så här istället:

$allowed_pages = array('index', 'about', 'lol'); if (in_array($_GET['p'], $allowed_pages)) { include $_GET['p'].'.htm'; } else { echo 'Sidan kunde inte hittas.'; } // Eller så här switch($_GET['p']) { case 'about': include 'about.php'; break; case 'lol': include 'lol.php'; break; default: include 'default.php'; break; }

Finns många fler sätt...

Permalänk
Medlem

Jag får då förtydliga att jag inte alls är intresserad av säkerhetslösningar. Tråden ska inte innehålla inlägg som Akiras här ovan, alltså. Strängmatchning klarar jag själv, tack.

Permalänk
Medlem

Man kan inte tro att du klarar av strängmatchning om du seriöst funderar på att köra den där koden på din sida. Safe mode eller ej.

http://se2.php.net/Safe%20Mode

Edit: Oavsett om Safe Mode förhindrar åtkomst till skyddade filer eller inte så är det inte så snyggt att få o-stylade PHP-felmeddelanden i ansiktet vid en malformulerad GET-request.

Permalänk

det är ju "fel" sätt att göra det på... men jag tror det är rätt safe.

Permalänk
Citat:

Ursprungligen inskrivet av björn.....
det är ju "fel" sätt att göra det på... men jag tror det är rätt safe.

Det fungerar säkert ur ren säkerhetssynpunkt, men det fungerar inte alls om man ser till användarvänligheten.

Visa signatur

Om man tänker en tanke, så är den tanken inte den tanke man tror att man tänker. Utan det är den tanke som får en att tro att man tror den tanke man tror att man tänker.

Permalänk
Medlem
Citat:

Ursprungligen inskrivet av Prizephitah
Det fungerar säkert ur ren säkerhetssynpunkt, men det fungerar inte alls om man ser till användarvänligheten.

"Om man ser till användarvänligheten"? Var kommer den in i bilden?

Om jag har förstått det rätt kommer det här systemet att användas i samband med någon form av meny där länkarna ser ut ungefär såhär:

<a href="index.php?about">About</a>

Användarna ska med andra ord använda menyn för att navigera på siten, inte själv skriva in url:er i adressfältet. Användarna behöver ju aldrig bry sig om hur det fungerar bakom kulisserna, så länge det fungerar.

Enda gången användaren i det här fallet lägger märke till systemet är när h*n följer en trasig länk i menyn, och då får denne veta att sidan inte är tillgänglig. Visst, det hade kanske varit snyggare att skicka en 404 här, men användarvänligare? Knappast.

Permalänk

*raderat*

Visa signatur

Hör ropen skalla: Mer CO-OP åt oss alla!
Fanboys är kapitalismens svar på religiösa fundamentalister.
Upplysning für alle: www.thesciencenetwork.org www.transhumanism.org

Permalänk
Medlem

Wishie har helt rätt, användarvänligheten har inget med det här att göra. Tanken är att URLerna blir ganska snygga, t.ex. kan jag köra index.php?p=Ge_ett_barn_en_familj

Jag tycker personligen att det blir lika snyggt som en 404 också. Eller om vi säger såhär; det går att göra det här felmeddelandet lika snyggt som en 404 och tvärtom... jag tänker ju skriva ut denna H1 med felmeddelande som content istället för det riktiga innehållet som hade inkluderats om sidan hade hittats.

Citat:

Ursprungligen inskrivet av Akira
Man kan inte tro att du klarar av strängmatchning om du seriöst funderar på att köra den där koden på din sida. Safe mode eller ej.

Edit: Oavsett om Safe Mode förhindrar åtkomst till skyddade filer eller inte så är det inte så snyggt att få o-stylade PHP-felmeddelanden i ansiktet vid en malformulerad GET-request.

Jasså? Om man inte kör Safe Mode kan en include göras på externa URLer men när man kör Safe Mode (och specificerar en safe_mode_include_dir, kör PHP version < 6.0) nekas detta, som jag förstått det.

Sen får man inte alls mågot felmeddelande eftersom jag använder ett @ innan include. Eftersom jag använder include ist för require är det dessutom bara varningar, som inte ens visas på min webbserver per default.

Det verkar alltså som att detta inte har någon uppenbar säkerhetsbrist ändå?

Permalänk
Hedersmedlem

Safe mode eller inte, det är dålig praxis att gömma NOTICE med @ och att lita på data från användaren.
Även om safe mode kan tänkas vara bra kan källkoden för den funktionen innehålla säkerhetsbrister (har hänt förr om jag inte minns fel).

Just ja, att överhuvudtaget dölja någon typ av meddelande (NOTICE, WARNING, ERROR) under utveckling är riktigt dåligt, se till att E_ALL är i effekt under utvecklingen. Du kan slå av dem i produktion dock.

Slutligen är URL:er som använder query-strings ($_GET) inte bra val heller eftersom att sökmotorer kan ha problem med dessa. Detta är en snygg URL: http://mydomain.com/info, detta är inte en snygg URL: http://mydomain.com/?info.

Query-strings fungerar dock bra för vissa saker, exempelvis ange vilken sida i ett paging-system man är på (?page=2).

En annan sak att tänka på är att när du levererar en 404 ska även HTTP-headern överensstämma med detta:

header('404 Not found');

Summering: dålig kodpraxis avråds, lita inte på användaren, finns det ett möjligt säkerhetshåll, täpp till det, lita inte på magi (safe mode och magic_quotes_gpc).

EDIT: Alternativet jag rekommenderar är att faktiskt dela upp sidan i filer som inkluderar header och footer.

Ännu hellre, använd ett template-system (typ Smarty) för att separera logik från visning. Ytterligare ett steg därifrån är att följa MVC-modellen.

Visa signatur

Vim
Kinesis Classic Contoured (svart), Svorak (A5)
Medlem i signaturgruppen Vimzealoter.

Permalänk
Medlem
Citat:

Ursprungligen inskrivet av m0REc
Safe mode eller inte, det är dålig praxis att gömma NOTICE med @ och att lita på data från användaren.
Även om safe mode kan tänkas vara bra kan källkoden för den funktionen innehålla säkerhetsbrister (har hänt förr om jag inte minns fel).

Just ja, att överhuvudtaget dölja någon typ av meddelande (NOTICE, WARNING, ERROR) under utveckling är riktigt dåligt, se till att E_ALL är i effekt under utvecklingen. Du kan slå av dem i produktion dock.

Slutligen är URL:er som använder query-strings ($_GET) inte bra val heller eftersom att sökmotorer kan ha problem med dessa. Detta är en snygg URL: http://mydomain.com/info, detta är inte en snygg URL: http://mydomain.com/?info.

Query-strings fungerar dock bra för vissa saker, exempelvis ange vilken sida i ett paging-system man är på (?page=2).

En annan sak att tänka på är att när du levererar en 404 ska även HTTP-headern överensstämma med detta:

header('404 Not found');

Summering: dålig kodpraxis avråds, lita inte på användaren, finns det ett möjligt säkerhetshåll, täpp till det, lita inte på magi (safe mode och magic_quotes_gpc).

EDIT: Alternativet jag rekommenderar är att faktiskt dela upp sidan i filer som inkluderar header och footer.

Ännu hellre, använd ett template-system (typ Smarty) för att separera logik från visning. Ytterligare ett steg därifrån är att följa MVC-modellen.

Alltså, för att göra din långa historia kort, kan det innebära ett säkerhetsproblem att lita på källkoden för include. Det var det relevanta.

Angående felmeddelande (404) är det lite off-topic. Att köra @include är ju bara en variant, det går att först kolla om filen existerar t.ex. för att undvika notices, varningar och felmeddelanden. Jag gjorde ett så enkelt exempel som möjligt för att visa vad jag menade ur säkerhetssynpunkt, bara. Går att redirecta till en 404 också.

Den enda sökmotor jag bryr mig om för denna sida är Google, och Google länkar gärna till sidor med GET-data. För en användare är det lika tydligt med http://www.htl.se/?p=Ge_ett_barn_en_familj som det är med http://htl.se/Ge_ett_barn_en_familj, det sistnämnda innehåller bara några fler obegripliga tecken än det första för en internetanvändare att följa.

Magic Quotes vet jag inte varför du nämner, och jag har redan delat upp sidan i header, content och footer men som sagt var det bara den relevanta koden som jag postade.

Permalänk
Hedersmedlem
Citat:

Ursprungligen inskrivet av azoapes
Alltså, för att göra din långa historia kort, kan det innebära ett säkerhetsproblem att lita på källkoden för include. Det var det relevanta.

Angående felmeddelande (404) är det lite off-topic. Att köra @include är ju bara en variant, det går att först kolla om filen existerar t.ex. för att undvika notices, varningar och felmeddelanden. Jag gjorde ett så enkelt exempel som möjligt för att visa vad jag menade ur säkerhetssynpunkt, bara. Går att redirecta till en 404 också.

Den enda sökmotor jag bryr mig om för denna sida är Google, och Google länkar gärna till sidor med GET-data. För en användare är det lika tydligt med http://www.htl.se/?p=Ge_ett_barn_en_familj som det är med http://htl.se/Ge_ett_barn_en_familj, det sistnämnda innehåller bara några fler obegripliga tecken än det första för en internetanvändare att följa.

Magic Quotes vet jag inte varför du nämner, och jag har redan delat upp sidan i header, content och footer men som sagt var det bara den relevanta koden som jag postade.

Nja, det "skydd" safe mode ger för include, vilket inte alltid täpper till. Magic quotes nämnde jag eftersom att det är i effekt för din URL, det vill säga ser till att man inte kan göra saker som "?p=%000/etc/passwd".

Visst är det offtopic, men det kan likväl nämnas. Du nämnde att varningar var avstängda på servern och jag avrådde ifrån detta.

Du menar det första, hur som, det är värt att nämna återigen och det senare är betydligt snyggare än det förra.

Visa signatur

Vim
Kinesis Classic Contoured (svart), Svorak (A5)
Medlem i signaturgruppen Vimzealoter.

Permalänk
Medlem

Safe mode finns väl inte längre i php6. Så om du planerar att uppgradera någon gång är det inte alls någon säker lösning.

Om du har alla tillåtna sidor någonstans på disk skulle du ju kunna dir-lista dem till en array och sedan använda den enl. Akiras lösning. Men det visste du säkert redan...

Visa signatur

War is Peace.
Freedom is Slavery.

Permalänk
Medlem
Citat:

Ursprungligen inskrivet av m0REc
Nja, det "skydd" safe mode ger för include, vilket inte alltid täpper till. Magic quotes nämnde jag eftersom att det är i effekt för din URL, det vill säga ser till att man inte kan göra saker som "?p=%000/etc/passwd".

Visst är det offtopic, men det kan likväl nämnas. Du nämnde att varningar var avstängda på servern och jag avrådde ifrån detta.

Du menar det första, hur som, det är värt att nämna återigen och det senare är betydligt snyggare än det förra.

Har du någon källa på det där med "inte alltid täpper till"?

Jag har tyvärr ingen kontroll över servern, det är One som har makten i sin hand!

Ja jag håller med om att det är snyggare, men jag ska skapa en dynamisk lista över artiklar och sorterar helst inte in det i separata mappar då det kan bli upp emot 100 mappar då... väldigt oöverskådligt. Vet inte hur mycket pill med .htaccess som One stödjer heller, men det är säkert inte mycket och jag orkar ändå inte pilla. Användarna får stå ut med att titta på /?p= istället för / helt enkelt, jag sparar tillräckligt mycket tid för att det ska vara värt det.

"Du menar det första, hur som, det är värt att nämna återigen"
den där meningen förstod jag inte mycket av...

EDIT

Citat:

Safe mode finns väl inte längre i php6. Så om du planerar att uppgradera någon gång är det inte alls någon säker lösning.

Stämmer bra! (jag skrev därför ovan att mitt webbhotell kör PHP version < 6.0)

Permalänk

Varför sitta och tugga på med strängjämförelser för varje tillgänglig sida?

$request = isset($_GET['p']) ? $_GET['p'] : 'index'; if (!preg_match("~^[a-zA-Z0-9_-]$~", $request) header('404 Not found'); else include("content/{$request}.htm");

Permalänk
Medlem
Citat:

Ursprungligen inskrivet av vigge89
Varför sitta och tugga på med strängjämförelser för varje tillgänglig sida?

$request = isset($_GET['p']) ? $_GET['p'] : ''; if (!preg_match("~^[a-zA-Z0-9_-]$~", $request) header('404 Not found'); else include("content/{$request}.htm");

Hähä, i jämförelse med din kod så är min experimentkod ganska overkill...

$req = new RequestParser($_GET['p']); $req->setDefaultResponse('default'); $req->setAllowedResponses('test', 'admin'); try { $page = $req->parseRequest(); } catch (FileNotFound $e) { header($e->statusCode()); echo "<h1>404 File Not Found</h1>\n"; echo "Sidan {$e->getMessage()} finns inte eller har blivit flyttad."; exit; } include "pages/$page.php";