PHP Säkerhet

Den 20 april 2009, i Säkerhet, Webben, av TXC

SQL Injection Sårbarheter

SQL injection sårbarheter är en i helt annan klass av data validering brist. Specifikt, det tillåter någon att manipulera en databas fråga. Till exempel, i ditt PHP script, så kanske du frågar användaren för ett användarnamn och lösenord, och frågar sedan databasen om detta och får tillbaka resultatet.

SELECT * FROM users WHERE name='$username' AND pass='$password';

Hur som helst, om användaren vill slingra sig förbi, så kan han skriva in detta som sitt lösenord:

' OR '1'='1

Detta resulterar i att frågan som blir sänt är:

SELECT * FROM users WHERE name='known_user' AND pass='' OR '1'='1';

Denna kommer att returnera användarnamnet utan att validera lösenordet, the elaka användaren har fått tillgång till applikationen med en användare som han väljer. För att förebygga detta så måste du escapa alla farliga tecken från den data som användaren har skrivit in, speciellt alla enkla citationstecken (‘). Den enklaste och bästa vägen för detta är att använda PHP’s mysql_real_escape_string.

$username = mysql_real_escape_string($_POST['username']);
$password = mysql_real_escape_string($_POST['password']);

Men beroende på din PHP konfiguration så kanske man måste göra mer. PHP konfiguration kan ställa det, magic quotes, är oftast aktiverad från början i nuvarande versioner av PHP. Denna möjlighet kan stängas av i php.ini med värdet magic_quotes_gpc = Off, eftersom den escapar alla citationtecken (enkla och dubbla) som skickas (GET, POST och Cookies). Denna möjlighet är till för oerfarna utvecklare som inte tänker på detta. Denna möjlighet är bra men den sänker prestandan rejält när den är påslagen, speciellt när man skickar data som inte behöver escapas. Som flesta erfarna utvecklare väljer att sätta detta värde till Off.

Om du utvecklar applikationer som är installerad på en delad server där du inte har tillgång till php.ini, använd koden nedan för att kontrollera status på magic_quotes_gpc och ifall den är påslagen så skickar man alla värden igenom PHPs stripslashes(). Du kan sedan skicka valda värden igenom mysql_real_escape_string .

if (get_magic_quotes_gpc()){
    $_GET = array_map('stripslashes', $_GET);
    $_POST = array_map('stripslashes', $_POST);
    $_COOKIE = array_map('stripslashes', $_COOKIE);
}

SQL injection brister leder inte alltid till att man kan få tillgång till någon annans konto. Exempelvis kan de låta en angripare att visa valda databasposter om resultatet av sökningen visas på sidan.

Du bör alltid kontrollera datat användaren lämnat om det kommer att användas i en sökfråga för tecken ‘”,;() och, möjligen, för sökorden ”FROM”, ”LIKE” och ”WHERE” i en skiftlägeskänsliga sätt. Det är dessa tecken och sökord som är användbara i en SQL insertion attack, så om du tar bort dem från användarens input där de är onödiga, så kommer du att ha mycket mindre att oroa sig för denna typ av fel.

Felmeddelanden

Du skall försäkra dig om att display_errors i php.ini är satt till ”Off”. Annars när fel uppstår, tex databas anslutnings fel, kommer att synas i användarnas webbläsare. En angripare kan använda detta för se hur din applikation fungerar och leta efter möjliga sätt för att göra intrång, detta genom att skicka in olika data och granska felmeddelanden.

display_errors värdet kan ändras i scriptet genom ini_set funktionen, men detta är inte lika som att sätta det i php.ini, eftersom ett ”fatal” felmeddelande kommer fortfarande att synas, eftersom om ett script har ett ”fatal” fel och inte kan köras som kan inte ini_set köras.

Istället för att visa felmeddelanden så sätt error_log till ”1″ och kontrollera PHP loggen med jämna mellanrum för felmeddelanden. Alternativt så kan du utveckla din egna felhantering som körs automatiskt när fel uppstår, och som kan eposta dig felmeddelanden, eller köra annan form kod. Det är en smart lösning att göra, eftersom du kommer att notifierad om detta och kan fixa det snarast möjligast innan en angripare kan köra sin attack. Läs PHP manualen om felhantering och lär dig mer om set_error_handler() funktionen.

Konfigurera PHP för Säkerhet

Generellt, dom flesta nya PHP installationer som använder nyare versioner av PHP är konfiguerade med mycket säkrare standard inställningar än vad tidigare versioner var. Hursomhelst, din applikation kan bli installerad på en gammal server som har en version som är äldre än den du använder och som inte har samma inställningar. I detta fall, standard inställningar är inte alltid så säkra som an tror dom är.

Du bör sätta upp en sida som kallas på phpinfo() för en lista av dina php.ini variablar och kan kolla över dom efter osäkra inställningar. Håll denna sida på ett säkert ställe och låt inte allmänheten få tillgång till den. Sidan kan innehålla information som en potentiell hackare kan finns denna information användbar.

Några inställningar bör man se över noga.

  1. register_globals: Denna inställning är sedan PHP 4.3 som standard satt till ”off”. Den exporterar all data som skickas via POST, GET & cookies till vanliga variablar. Den kan ställa till det rejält. Så här är ett råd. Sätt den till OFF, inga men, inga undantag, gör det bara! Denna inställning är säkert ansvarig för fler PHP brister än vad någon annan funktion är. Om du är på en delad server som har denna inställning till On och dom inte vill byta, Byt webbhotell!
  2. safe_mode: PHPs Safe Mode är väldigt användbar för att förhindra otillåten tillgång till andras filer. Det fungerar genom att du bara kan läsa filer som ägs av samma användare som filen själv. Men det ställer till det när det kommer till andra saker som tex. filuppladdning. PHPs safe_mode är helt fel väg att gå, det finns flera andra sätt att lösa detta på. safe_mode satt till Off skall det vara.
  3. disable_funtions: Denna inställning kan bara ändras i php.ini, och inte i filer själv. Det är en komma separerad lista med namn på funktioner som du vill stänga av. Det kan hjälpa till genom att stänga av exec, passthru & system. Inställningen är upp till dig.
  4. open_basedir: Med denna inställning kan man "låsa in" användaren till sin katalog. Användaren kan inte läsa en fil utanför sin katalog. Denna inställning tillsammans med tex. PHP & fast_cgi är rätt väg att gå istället för PHPs safe_mode.

Läs igenom säkerhets manualen i PHP och lär dig den väl. Behandla det som prov där du lär dig den fram och backlänges. Du kommer att bli satt på prov av hackers som verkligen kommer att sätta dig på prov. Du får en guldstjärna i kanten om hackaren ger upp och tar ett enklare mål.

Slutsats

Som jag visat i denna artikel, så är det många saker som man måste vara uppmärksam på när det gäller att säkra upp sina PHP kunskaper, men detta gäller inte bara PHP utan det gäller vilket språk som helst. PHP är inte mindre säkert än något annat språk. Den viktigaste saken när det gäller att utveckla mot säkerhet är att lära känna dina verktyg. Jag hoppas att du gillade denna artikel och jag hoppas att du lärde dig något. Kom ihåg: bara för att du inte är paranoid så betyder det inte att det är någon efter dig.

Sidor: 1 2

Taggad med:  

3 Responses till “PHP Säkerhet”

  1. Daniel skriver:

    Me like big time!
    Du får definitivt en permanent länkning till denna artikeln när jag fått pli på RRnet’s frontsida. :)

    Fler borde lära sig om dessa saker i PHP, ist för att ordna till så vi andra får bita i det sura äpplet och böka med PHP’s safe_mode…

    • TXC skriver:

      Man tackar man tackar. Det är hela vitsen att folk skall äntligen fatta.

      safe_mode, gör sitt jobb, men det är fel väg att gå. Tex. Apache, med fast_cgi så gör den ett bra jobb, och kör scripten som användaren, sedan med php.ini där man kan sätta open_basedir mm. Så blir det säkert.

      Skall lägga till det jag nämnde precis i texten. En länk hade uppskattats. :D

      • Daniel skriver:

        Ej att förglömma är att PHP inställningar även kan sättas individuellt på olika VirtualHost’s i Apache. Och därigenom anpassa konfigurationen efter specifika miljöer.
        Sen kan man ifrågasätta applikationer som t.ex. kräver Register Globals.
        Safe_Mode är bra, men det är ingen lösning i slutändan. Folk måste förstå det.
        Och det finns fler fall där det krånglar till saker, än hjälper.
        Kan man bara skriva säkert nog, och misstänka allting (t.ex. med variabler man stoppar in i MySQL (genom att köra en extra kontrollfunktion, även om man har tvättat variablerna före) så kommer man långt.
        Folk borde lära sig att skriva bra, säker kod.
        Länken kommer, har bara en HEL del kvar att skriva på den sidan eftersom det har kommit ett tjog saker emellan.