Navigering:
- forum.jorgis.com
- Linker
- Admin CP
Sikker bruk av include-script
Skrevet av Jørgen, 2004-07-07
Bruk av dynamiske include-script har tatt seg opp voldsomt i det siste, siden flere og flere får snusen på hva noen korte PHP-snutter kan gjøre for å forenkle drift av deres hjemmeside. Det mange ikke tar med i beregningen er hvor lett et slikt script kan lures til å hente ondsinnete filer, eller i verste fall kompromittere hele systemet. Det skal jeg prøve å ta et lite oppgjør med her.
Hva er det?
Et include-script er en liten kodesnutt i PHP som gir en webside de fordeler frames gav uten de samme ulempene, siden man kan ha designet sitt i HTML og CSS, og bruke include-scriptet til kun å få tak i innholdet. Nesten total atskillelse av design og innhold, altså. Slik unngår man problemer hvis man skal redesigne en side med mange undersider, og man kan også laste opp nytt innhold uten å måtte ta ned forsiden.
Include-script finnes i to varianter; nemlig dynamiske og statiske. Førstnevnte er mest aktuelt for de fleste, siden det ikke krever endring av forsiden, og include-scriptets kode for å laste opp en ny side. Førstnevnte er også farligst, siden det kan lett lures til å hente feile filer, og dermed risikere å få uønsket besøk på serveren.
Statiske include-script er mer eller mindre skuddsikre, men mangler mye av den funksjonaliteten dynamiske include-script gir. Derfor føler jeg det ikke er noen vits i å ta det opp her.
Hvordan
Et include-script benytter seg av - og har blitt navngitt etter - en PHP-funksjon som benyttes til å inkludere filer i andre filer. Den funksjonen benyttes ofte (men ikke alltid) i sammenheng med den superglobale variabelen $_GET[]. En superglobal variabel er en variabel som er tilgjengelig overalt i koden, og også overalt på webtjeneren. Når man holder på med superglobale variabler, bør man være meget forsiktig, men det er ikke alle som tenker helt over det.
$_GET[] brukes til å hente data fra adresselinjen. Du har sikkert sett sider som har brukt dette før, med adresser som www.domene.com/index.php?s=about. Jorgis.com benytter seg også av dette, noe du kan se i adresselinjen over. Et slikt script kan se slik ut:
include "$_GET['s'].php">;
Include-uttrykket henter altså det som kommer etter "s" i URL'en, og legger til en filendelse. Deretter inkluderes filen til scriptet.
Include-scriptet inkluderer da hvilken som helst fil brukeren spesifiserer i URL-en. Hvis URL-en er index.php?s=articles, inkluderes filen articles.php. Dette kan misbrukes, ved å bl.a. benytte ../ og ./, noe som gjør det mulig å hente filer som ligger en mappe over i hierarkiet. Hvis jeg skriver index.php?s=../slemfil.php, inkluderes filen slemfil.php, selv om den ligger en mappe lenger opp. Dette kan i verste fall brukes til å inkludere en fil fra andre brukere på serveren, noe som kan gjøre at en ondsinnet inntrenger kan få uautorisert tilgang til serveren.
Løsninger
Siden et dynamisk include-script tar imot variabler direkte fra bruker, må man være veldig forsiktig med hva man tar imot, og dermed må man validere hva bruker sender. Det kan gjøres med bl.a. regulære uttrykk (regular expressions), kun akseptere filnavn som begynner på en viss bokstav/rekke bokstaver eller ved å sjekke om det som inkluderes ligger i en forhåndsdefinert liste over godkjente filer. Sistnevnte er ikke så veldig aktuell for de som vil ha en selvgående løsning, siden man likevel må laste opp en ny kopi av index-siden.
Eksempel 1 - Regular Expressions
<?php
$filnavn = $_GET['s'];
$filendelse = '.php';
if (eregi("^[a-z0-9]+$", $filnavn)) {
@include $filnavn . $filendelse;
}
else {
@include "404.php";
}
?>
Denne benytter seg av regulære uttrykk for å teste om filnavnet kun inneholder bokstavene a til z og tallene 0 til 9. Dermed er det umulig å bruke scriptet til å få tak i filer utenfor den mappen.
Eksempel 2 - Bokstavleken (:p)
<?php
$filnavn = $_GET['s'];
$filendelse = '.php';
@include 'abc' . $filnavn . $filendelse;
?>
Dette scriptet inkluderer bare filer med filnavn som begynner på "abc", og dermed er det umulig for andre å inkludere filer fra andre steder. Hvis du i tillegg spesifiserer en mappe filene skal hentes fra, er det nesten skuddsikkert. Legg merke til alfakrøllen foran include-utrykket. Den gjør at include-funksjonen ikke returnerer en feilmelding hvis filen ikke finnes.
Eksempel 3 - Kun tillatte filer
<?php
$filnavn = $_GET['s'];
$tillatt = array("index", "articles", "links");
$filendelse = '.php';
if (in_array($filnavn)) {
@include $filnavn . $filendelse;
}
else {
@include '404.php';
}
?>
Denne varianten av scriptet inneholder først et array som inneholder alle de tillatte filnavnene. Deretter sjekkes det med funksjonen in_array() om den filen som skal inkluderes er med i arrayet. Hvis den er det, inkluderes filen. Hvis ikke, inkluderes en 404-fil, som inneholder en beskjed om at brukeren er kommet feil. PS: in_array() er følsom for forskjeller mellom stor og liten bokstav.
Konklusjon
De tre overnevnte scriptene demonstrerer bare noen de alternativene man har når man skal lage et sikkert include-script. Det finnes sikkert flere hundre forskjellige variasjoner, alt fra enkle script på et par linjer til svære kolosser på over 50 linjer. Alt etter behov, altså. Av de tre overnevnte, er det eksempel 2 som er mest aktuelt for de aller fleste.
Tilbake til forrige side.