EvoGfx
Doriti să reactionati la acest mesaj? Creati un cont în câteva clickuri sau conectati-vă pentru a continua.

Mic tutorial pentru Anti-SQL-Inject

In jos

Mic tutorial pentru Anti-SQL-Inject Empty Mic tutorial pentru Anti-SQL-Inject

Mesaj Scris de EST-Zone Dum Dec 28, 2008 12:17 am

*Am vazut foarte multe servere in ultima vreme "picand" ...acesta este mai mult ca un sfat!

Folositi unul din web-urile de mai jos:
*Aceste
web-uri nu pot fi injectate sau pana la momentrul de fata nu sau gasit
hole-uri (gauri) pentru a le injecta...deci va recomand:
-MuWeb 0.3
-MuWeb 0.6
-MuWeb 0.9
-DMG Team WebSite v0.1
*DMG Team WebSite v0.2 coming soon

Pentru inceput sa vorbim putin despre Injection:

Pentru o vizualizare mai "atractiva" vizitati: http://weblogs.studentclub.ro/ovidiupl/archive/2005/10/20/12168.aspx

Ovidiu Platon a scris:


Cod:
Un mit despre SQL Injection

În prezent, cea mai mare parte a
aplicațiilor dezvoltate la noi și în lumea largă folosesc pe undeva și
o bază de date, iar limbajul preferat pentru interacțiunea cu
diferitele implementări de motoare relaționale este SQL (Structured
Query Language). În condițiile în care securitatea are prioritate
maximă în orice aplicație, nu e de mirare că noțiunea de SQL Injection,
un atac foarte comun asupra bazelor de date, a fost tratată pe larg în
diferite materiale.

În primul rând, să clarificăm puțin ce
înseamnă injectarea de cod în general și SQL Injection în particular.
Injectarea de cod este procesul prin care cod executabil străin este
introdus în memoria unui proces, de obicei deghizat în date, prin
intermediul unei vulnerabilități oarecare. Un exemplu clasic de
injectare de cod este exploatarea vulnerabilităților de tip buffer
overrun, cu injectarea de cod executabil prin intermediul unui șir de
caractere invalid și neverificat de aplicație.

SQL Injection
reprezintă introducerea de comenzi SQL într-un script utilizat de o
aplicație de baze de date. Vectorul de atac îl reprezintă
instrucțiunile SQL generate dinamic de aplicație, după cum vom vedea în
detaliu puțin mai jos. Un atac SQL Injection poate avea consecințe
variate, de la divulgarea de informații confidențiale și până la
preluarea controlului complet asupra serverului de baze de date, în
funcție de prezența altor vulnerabilități.

Problema își are
originile în modalitatea tradițională de a scrie interogările SQL:
Direct în codul aplicației, sub formă de șiruri de caractere
concatenate pentru obținerea interogării care va fi trimisă serverului.
De exemplu, pentru a vedea dacă o combinație utilizator + parolă se
află în baza de date, am putea scrie:

SELECT COUNT(*) FROM [dbo].[Users]
WHERE [Username] = 'user' AND [Password] = 'pass'

(Să
trecem peste faptul că stocarea parolelor direct în baza de date e o
idee foarte proastă). Într-o aplicație scrisă în C# cu ADO.NET, o
astfel de comandă ar putea fi formulată în felul următor:

// Codul de mai jos nu tine cont de necesitati
// ale aplicatiilor reale: eliberarea resurselor, prinderea
// exceptiilor samd. Nu il folositi ca atare in aplicatii
// de productie
string connectionString;
string userName, password;
// ...
// Initializarile de rigoare
// ...
SqlConnection sqlConn = new SqlConnection(connectionString);
SqlCommand cmd = new SqlCommand();
cmd.Connection = sqlConn;
cmd.CommandType = CommandType.Text;
cmd.CommandText = "SELECT COUNT(*) FROM [dbo].[Users] " +
"WHERE [Username] = '" + userName + "' AND [Password] = '" +
password + "'";
sqlConn.Open();
cmd.ExecuteNonQuery();
// ... Alte comenzi

Un
exercițiu mic pentru cititori: Să spunem că după apelarea procedurii
stocate, într-o variabilă întreagă numită userCount avem numărul de
utilizatori pentru care combinația utilizator + parolă există în baza
de date. Cum e mai bine să scriem testul: if (userCount != 0) sau if
(userCount == 1)? De ce?

Ce se întâmplă dacă, dintr-un motiv sau altul, în loc de numele de utilizator, cineva introduce ' OR 1 = 1 --?

Comanda SQL devine:

SELECT COUNT(*) FROM [dbo].[Users]
WHERE [Username] = '' OR 1 = 1 -- AND [Password] = '...'

Problema
e că primul apostrof devine perechea celui care deschidea șirul
reprezentând numele utilizatorului, 1 = 1 este întotdeauna adevărat, OR
este adevărat dacă unul din operanzi este adevărat, și atunci expresia
din clauza WHERE e adevărată tot timpul. (Șirul -- reprezintă un
comentariu în Transact SQL - varietatea de SQL din Microsoft SQL Server
- și textul de după acest șir este ignorat.)

Exemplul de mai sus
e un fel de "Hello, World!" al SQL Injection și îl găsiți în nenumărate
materiale. O aplicație ce își construiește interogările în mod dinamic
în acest fel e o gaură de securitate așteptând să fie exploatată, iar
exemplul dat este inocent în comparație cu ce se poate obține prin SQL
Injection.

În general vulnerabilități de acest gen apar în
aplicații web, deoarece modelul aplicație web + bază de date este
foarte popular. Nu vă lăsați păcăliți, asta nu înseamnă că doar
aplicațiile web sunt vulnerabile. Orice aplicație care își construiește
cererile în mod dinamic ca în exemplul dat expune acest gen de
vulnerabilități. Dar nu aici doream să ajung.

Mitul pe care
vreau să îl scutur puțin este "Prin utilizarea procedurilor stocate
riscul atacurilor de tip SQL Injection dispare". Această afirmație
ascunde de fapt o altă afirmație cu care nu sunt de acord: Cererile
formulate dinamic sunt în mod inerent "diabolice". Mai mult, unii
adoptă afirmația de mai sus ca atare și o susțin cu fervoare
religioasă, fără să știe toate aspectele problemei.

Nu mă
înțelegeți greșit: Sunt un fan uriaș al procedurilor stocate. Motivele
pentru care folosesc aproape exclusiv proceduri stocate țin de
modularizarea codului (care duce la localizarea modificărilor și la
ușurința în întreținere), de posibilitatea de a testa procedurile
stocate individual, de securizarea lor prin liste de control al
accesului, de eleganța aplicației pe ansamblu.

Cu toate acestea,
există unele lucruri pe care procedurile stocate nu le pot face în mod
elegant. Să vă dau un exemplu simplu: Să presupunem că avem o tabelă cu
utilizatori care conține printre altele două coloane (varchar de o
lungime oarecare, pentru simplitate), numite FirstName și LastName. Să
presupunem că pe undeva prin aplicația construită pe această bază de
date am un câmp text în care utilizatorii pot introduce nume care să
fie căutate în baza de date. Pentru că avem o aplicație extrem de
simplă nu folosim Full Text Search sau alte artificii spectaculoase, ci
recurgem la o interogare banală.

Dacă un utilizator introduce
"Ioan Popescu" în câmpul text, presupunem că dorește să vadă acele
persoane din baza de date care au în componența numelui complet ambele
cuvinte. Atunci, o interogare ar putea arăta în felul următor:

SELECT * FROM [dbo].[Users]
WHERE (([FirstName] LIKE '%Ioan%') OR ([LastName] LIKE '%Ioan%')) AND
(([FirstName] LIKE '%Popescu%') OR ([LastName] LIKE '%Popescu%'))

Dacă, însă, utilizatorul introduce "Ioan Gigel Popescu", interogarea devine:

SELECT * FROM [dbo].[Users]
WHERE (([FirstName] LIKE '%Ioan%') OR ([LastName] LIKE '%Ioan%')) AND
(([FirstName] LIKE '%Gigel%') OR ([LastName] LIKE '%Gigel%')) AND
(([FirstName] LIKE '%Popescu%') OR ([LastName] LIKE '%Popescu%'))

Așa
ceva nu e tocmai banal de implementat într-o procedură stocată, ținând
cont că nu se poate ști în avans cum va arăta clauza WHERE. Cum nu
dorim să formulăm cererea în mod dinamic, am cam rămas fără opțiuni,
nu? Ei bine, nu. Soluția o reprezintă cererile parametrizate.
Presupunând că folosim C#, ADO.NET și SQL Server, iată cum ar arăta o
cerere parametrizată pentru prima interogare:

// Sa presupunem ca tabloul e deja initializat
// si ca am verificat validitatea datelor
// (tabloul are cel putin un element,
// nu exista nici un null, nici un sir
// vid, am testat fiecare cuvant cu
// expresii regulate pentru a ne asigura
// ca avem doar litere samd).
string[] keywords;
string connectionString = "...";

SqlConnection sqlConn = new SqlConnection(connectionString);
SqlCommand cmd = new SqlCommand();
cmd.Connection = sqlConn;
cmd.CommandType = CommandType.Text;
cmd.CommandText = "SELECT * FROM [dbo].[Users] WHERE ";
// ATENTIE: Codul de mai jos este doar un exemplu
// In cod real va recomand sa folositi StringBuilder
// pentru a concatena siruri multiple si sa scrieti
// cod mai putin criptic.
for (int i = 0; i  0)
{
cmd.CommandText += " AND ";
}
cmd.CommandText += string.Format(
"(([FirstName] LIKE @Argument{0}) OR ([LastName] LIKE @Argument{0}))", i);
cmd.Parameters.Add(
string.Format("@Argument{0}", i),
SqlDbType.VarChar, 80).Value = keywords[i];
}
sqlConn.Open();
SqlDataReader reader = cmd.ExecuteReader();
// ... samd

Cu o abordare de genul acesta, prima interogare devine

SELECT * FROM [dbo].[Users]
WHERE (([FirstName] LIKE @Argument0) OR ([LastName] LIKE @Argument0)) AND
(([FirstName] LIKE @Argument1) OR ([LastName] LIKE @Argument1))

iar a doua devine

SELECT * FROM [dbo].[Users]
WHERE (([FirstName] LIKE @Argument0) OR ([LastName] LIKE @Argument0)) AND
(([FirstName] LIKE @Argument1) OR ([LastName] LIKE @Argument1)) AND
(([FirstName] LIKE @Argument2) OR ([LastName] LIKE @Argument2))

În
exemplele date, Argument0 .. Argument2 conțin "%Ioan%", "%Gigel%",
respectiv "%Popescu%" (fără ghilimele, evident). Avantajul este că
indiferent ce ar conține, șirurile de caractere nu vor modifica în nici
un fel căutarea așa cum o face un atac SQL Injection.

Repetați
după mine: "Prin utilizarea cererilor parametrizate riscul atacurilor
de tip SQL Injection dispare". În general, vă recomand să folosiți
proceduri stocate cu cea mai mare încredere, pentru că au o listă
întreagă de avantaje. Țineți cont, însă, că invocarea procedurilor
stocate este un caz particular de invocare al unei cereri
parametrizate. Dacă ajungeți într-o situație când trebuie neapărat să
compuneți dinamic o interogare, aceasta este modalitatea corectă de a o
face.

Atrag atenția asupra acestui aspect dintr-un motiv simplu:
Unii oameni asociază procedurile stocate cu eliminarea SQL Injection
fără a înțelege că parametrizarea este cea care duce la securizarea
aplicației. În aceste condiții, respectivele persoane adoptă politici
de genul "folosim doar proceduri stocate în aplicație", ajung în
situații în care cererile formulate dinamic reprezintă singura soluție,
așa că scriu o procedură stocată care acceptă un argument de tip șir de
caractere, pe care îl execută în interior cu EXECUTE sau cu
sp_executesql, fără să realizeze că au ajuns de unde au plecat.

Pentru a nu mai lungi vorba, să recapitulăm:

* NU concatenați șiruri de caractere pentru a forma comenzi SQL și NU executați aceste comenzi prin nici un mijloc.
*
Folosiți numai cereri parametrizate. Încercați să folosiți proceduri
stocate în cât mai multe situații, iar când acest lucru nu este posibil
creați interogările dinamic, dar cu argumentele transmise ca parametri.

Sper să vă fie de folos sfatul meu. Dacă mai aveți alte sugestii legate de acest subiect, aștept comentarii.


De ce va recomand MuWeb-urile de mai sus?
Deoarece sunt unele dintre singurele web-uri care nu au ft multe "gauri"
EST-Zone
EST-Zone
Fondator
Fondator

Numarul mesajelor : 596
Varsta : 29
Ce photoshop folosesti? : cs3
WarN :
Mic tutorial pentru Anti-SQL-Inject Left_bar_bleue0 / 1000 / 100Mic tutorial pentru Anti-SQL-Inject Right_bar_bleue

Puncte Castigate :
Mic tutorial pentru Anti-SQL-Inject Left_bar_bleue35 / 10035 / 100Mic tutorial pentru Anti-SQL-Inject Right_bar_bleue

Verifica-ti Cunostintele (PUNCTE) :
Mic tutorial pentru Anti-SQL-Inject Left_bar_bleue0 / 1000 / 100Mic tutorial pentru Anti-SQL-Inject Right_bar_bleue

Data de inscriere : 26/08/2008

https://evogfx.4umer.com

Sus In jos

Sus

- Subiecte similare

 
Permisiunile acestui forum:
Nu puteti raspunde la subiectele acestui forum