Doriți să reacționați la acest mesaj? Creați un cont în câteva clickuri sau conectați-vă pentru a continua.

    Tutorial Pentru Anti-SQL-Inject!

    KidRock4u
    KidRock4u
    Incepator
    Incepator


    Numarul mesajelor : 70
    Varsta : 33
    Location : http://sinopticmu.tk
    Data de inscriere : 29/12/2008

    Tutorial Pentru Anti-SQL-Inject! Empty Tutorial Pentru Anti-SQL-Inject!

    Mesaj  KidRock4u Lun Dec 29, 2008 8:57 pm

    *Am facut acest tutorial fiindca am vazut foarte multe servere in ultima vreme "picand" ...acesta este mai mult ca un sfat!
    Nu dau credite nimanui credite-le nu isi au locul aici!

    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 av recomand:
    -MuWeb 0.3 http://files.filefront.com/DmgTeam+MuSite+V+10rar/;10671010;/fileinfo.html
    -MuWeb 0.9 http://products.muweb.org/download.php
    -DMG Team WebSite v0.1 http://files.filefront.com/DmgTeam+MuSite+V+10rar/;10671010;/fileinfo.html
    *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:
    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" Very Happy Very Happy Very Happy king king king king

      Data/ora curentă este: Sam Mai 11, 2024 6:47 pm