46735899 sql injection

25
1 Universitatea din București Facultatea de Matematică și Informatică Specializarea: Baze de Date și Tehnologii Web Anul: II master SQL Injection (Referat la SecuritateaBazelor de Date) Studenți: Chifu Adrian-Gabriel (grupa 505) Duma Melania (grupa 505) Ilie Roxana (grupa 505) București, 2011

Upload: bujorianu-simona

Post on 28-Dec-2015

43 views

Category:

Documents


0 download

DESCRIPTION

bnm

TRANSCRIPT

Page 1: 46735899 SQL Injection

1

Universitatea din București Facultatea de Matematică și Informatică Specializarea: Baze de Date și Tehnologii Web Anul: II master

SQL Injection

(Referat la SecuritateaBazelor de Date)

Studenți:

Chifu Adrian-Gabriel (grupa 505)

Duma Melania (grupa 505)

Ilie Roxana (grupa 505)

București, 2011

Page 2: 46735899 SQL Injection

2

Cuprins

Cuprins ............................................................................................................................ 2

Privire de ansamblu ........................................................................................................ 4

Introducere .............................................................................................................................4

Privire de ansamblu asupra SQL Injection ...............................................................................4

SQL Injection: Oracle versus alte sisteme ................................................................................5

Dezvoltarea aplicațiilor ...........................................................................................................5

SQL Injection ................................................................................................................... 5

Introducere .............................................................................................................................5

Categoriile de atacuri cu SQL Injection....................................................................................5

Ce este vulnerabil ....................................................................................................................6

Ce nu este vulnerabil ...............................................................................................................7

Tipuri de Sql Injection ..................................................................................................... 7

Manipularea codului SQL ........................................................................................................7

Code Injection .........................................................................................................................8

Injectare cu apel funcţie ..........................................................................................................9

Supraîncărcarea bufferului ...................................................................................................10

PL/SQL ........................................................................................................................... 11

Instrucţiunea execute immediate .........................................................................................11

Pachetul DBMS_SQL..............................................................................................................13

Cursoare dinamice ................................................................................................................14

JDBC .............................................................................................................................. 15

PreparedStatement ...............................................................................................................15

CallableStatement ................................................................................................................16

Prevenirea SQL Injection în Oracle ................................................................................ 17

Cereri parametrizate .............................................................................................................17

Validarea datelor de intrare .................................................................................................18

Page 3: 46735899 SQL Injection

3

Securitatea funcțiilor apelate ...............................................................................................19

Mesajele de eroare ...............................................................................................................19

Excepții.......................................................................................................................... 21

Nume de tabele dinamice .....................................................................................................21

Clauza LIKE ............................................................................................................................21

Funcții Oracle ................................................................................................................ 22

Determinarea privilegiilor funcțiilor .....................................................................................22

Restricționarea accesului la funcții .......................................................................................23

Funcții standard ....................................................................................................................23

Funcții oferite de ORACLE......................................................................................................23

Exemple reale - SQL Injection ....................................................................................... 24

Bibliografie .................................................................................................................... 25

Page 4: 46735899 SQL Injection

4

Privire de ansamblu

Introducere

Majoritatea dezvoltatorilor subestimează riscul atacurilor cu SQL Injection ce afectează

aplicațiile cu baze de date Oracle în spate. Se pare că mulți dezvoltatori de aplicații nu înțeleg în

întregime riscul atacurilor cu SQL Injection și nici tehnicile folosite pentru prevenirea unor astfel

de atacuri.

Lucrarea se adresează dezvoltatorilor de aplicații, administratorilor de baze de date și

auditorilor de aplicații și are ca scop sublinierea riscurilor atacurilor cu SQL Injection și

demonstrarea premiselor de vulnerabilitate ale aplicațiilor web. Nu se vrea a fi un tutorial

pentru realizarea de atacuri SQL și nici nu oferă nici instrucțiuni în această privință.

Privire de ansamblu asupra SQL Injection

SQL Injection este un atac de bază folosit fie pentru obținerea accesului neautorizat la o

bază de date, fie pentru extragerea informațiilor direct din baza de date. Principiile care stau la

baza SQL Injection sunt simple și aceste tipuri de atac sunt ușor de executat și stăpânit.

Orice program sau aplicație pot fi vulnerabile la SQL Injection, inclusiv procedurile stocate

executate în mod direct printr-o conexiune la o bază de date, aplicații în Oracle Forms, aplicații

web, etc. Numeroase vulnerabilități au fost descoperite în pachetele standard Oracle Database

cum ar fi DBMS_DATAPUMP, DBMS_REGISTRY și DBMS_METADATA (vezi update-ul de

importanță critică din ianuarie 2006). Aplicațiile web prezintă cel mai mare risc al acestor

atacuri de vreme ce un atacator poate exploata vulnerabilitățile la SQL Injection de la distanță

fără autentificare la nivel de bază de date sau la nivel de aplicație.

Aplicațiile web care au în spate o bază de date Oracle sunt mai vulnerabile la atacurile cu

SQL Injection decât ar crede majoritatea dezvoltatorilor. În urma unor auditări de aplicații au

fost descoperite multe aplicații web vulnerabile la SQL Injection, deși standardele de codare au

fost bine stabilite pe parcursul dezvoltării multora dintre acestea. Atacurile SQL Injection pe

baza funcțiilor reprezintă cea mai mare preocupare, de vreme ce aceste atacuri nu necesită

informații despre aplicație și pot fi ușor automatizate.

Din fericire, atacurile SQL Injection sunt ușor de combătut prin anumite procedee de

codare. Cu toate acestea, orice parametru transmis oricărui enunț SQL dinamic trebuie validat,

sau trebuie folosite variabile legate.

Page 5: 46735899 SQL Injection

5

SQL Injection: Oracle versus alte sisteme

Oracle se descurcă bine în general împotriva atacurilor SQL Injection de vreme ce nu

există suport pentru cereri SQL multiple (SQL Server și PostgreSQL), nu există cererea EXECUTE

(SQL Server), și nu există funcția INTO OUTFILE (MySQL) – toate acestea fiind metode de

exploatare a vulnerabilităților la SQL Injection. În plus, utilizarea variabilelor legate în mediile

Oracle din motive de performanță oferă cea mai eficientă protecție împotriva atacurilor SQL

Injection.

Cu toate că Oracle oferă mai puține posibilități de atac pentru SQL Injection comparativ cu

alte baze de date, aplicațiile pe baza Oracle fără o protecție corespunzătoare împotriva

atacurilor pot fi vulnerabile și exploatate cu ușurință prin intermediul vulnerabilităților SQL

Injection.

Dezvoltarea aplicațiilor

Aplicațiile pot fi dezvoltate utilizând mai multe moduri de conectare la o bază de date Oracle –

unele metode sunt mai vulnerabile la SQL Injection decât altele. Vom pune accent numai pe

câteva limbaje de programare și pe câteva arhitecturi pentru aplicații care sunt folosite uzual

pentru aplicații web-based, deși tehnicile descrise ar trebui să fie relevante pentru majoritatea

limbajelor și arhitecturilor. Accentul se pune pe aplicații care folosesc fie Java și JDBC pentru

conectarea la o bază de date Oracle, fie PL/SQL drept limbaj de programare. Considerăm că

acestea două sunt cele mai uzuale metode pentru aplicațiile web-based în tandem cu baze de

date Oracle.

SQL Injection

Introducere

Atacurile prin SQL Injection sunt în esență simple – un atacator strecoară un șir de

caractere în aplicație în speranța că va reuși să manipuleze cererea SQL în avantajul său.

Complexitatea atacului implică exploatarea unei cereri SQL care poate fi necunoscută

atacatorului. Aplicațiile open-source și cele comerciale livrate alături codul sursă sunt mai

vulnerabile de vreme ce atacatorul poate descoperi potențiale vulnerabilități înaintea atacului.

Categoriile de atacuri cu SQL Injection

Sunt patru categorii principale pentru atacurile SQL Injection împotriva bazelor de date

Oracle:

Page 6: 46735899 SQL Injection

6

1. Manipularea SQL

2. Injectarea codului

3. Injectarea apelurilor de funcții

4. Supraîncărcarea bufferelor.

Primele două categorii, ar trebui să fie cunoscute bine, de vreme ce sunt atacurile cel mai

frecvent descrise pentru toate tipurile de baze de date (inclusiv SQL Server, MySQL, PostgreSQL

și Oracle).

Manipularea SQL implică de obicei modificarea cererii SQL prin intermediul operațiilor

UNION sau prin alterarea clauzelor WHERE cu scopul returnării unui alt rezultat. Multe atacuri

SQL prezentate și cunoscute sunt de acest tip. Cel mai bine cunoscut atac este realizat prin

modificarea clauzei WHERE din cererea de autentificare a utilizatorilor astfel încât clauza

WHERE să fie mereu TRUE.

Injectarea codului se realizează atunci când atacatorul inserează noi cereri SQL sau

comenzi pentru baza de date într-o anumită cerere SQL. Atacul clasic prin această metodă

adaugă o comandă EXECUTE pentru SQL Server la cererea SQL vulnerabilă. Injectarea codului

funcționează numai când sunt suportate cereri SQL multiple pentru o solicitare către baza de

date. SQL Server și PostgreSQL au această capabilitate și este posibil uneori să injectezi cereri

SQL multiple și în Oracle. Vulnerabilitățile la injectarea codului SQL în Oracle implică executarea

dinamică SQL în PL/SQL.

Ultimele două categorii sunt relativ specifice atacurilor împotriva bazelor de date Oracle și

nu sunt atât de bine cunoscute și documentate. În majoritatea aplicațiilor auditate s-au

descoperit vulnerabilități la aceste două feluri de atac.

Injectarea apelurilor de funcții reprezintă inserarea de funcții pentru baze de date Oracle

sau de funcții modificate într-o cerere SQL vulnerabilă. Aceste apeluri de funcții pot fi utilizate

pentru a efectua apeluri către sistemul de operare sau pentru a manipula date din baza de

date.

Supraîncărcarea bufferelor reprezintă o subcategorie pentru injectarea apelurilor de

funcții. În unele baze de date comerciale și open-source există puține funcții vulnerabile la

supraîncărcarea buffer-ului. Sunt disponibile patch-uri pentru majoritatea vulnerabilităților, dar

multe baze de date care nu sunt open-source rămân fără patch-uri.

Ce este vulnerabil

O aplicație este vulnerabilă la SQL Injection dintr-un singur motiv – inputul de stringuri nu

este validat corespunzător și este trecut către o cerere SQL dinamică fără vreo astfel de

Page 7: 46735899 SQL Injection

7

validare. De obicei stringul este trecut direct la cererea SQL. Cu toate acestea, intrarea dată de

utilizator poate fi stocată în baza de date și mai târziu să fie transmisă unei cereri SQL. Acest

procedeu se cheamă SQL Injection de ordinul doi. Din cauza lipsei de „memorie” a multor

aplicații web, este frecventă scrierea datelor în baza de date sau stocarea acestora prin alte

mijloace între paginile web. Acest atac indirect este mult mai complex și adesea necesită

cunoștințe profunde despre aplicație.

Ce nu este vulnerabil

Cererile SQL care folosesc variabile legate sunt în general protejate împotriva SQL

Injection de vreme ce baza de date folosește valoarea variabilei legate exclusiv și nu

interpretează variabila în niciun fel. PL/SQL și JDBC permit variabile legate. Variabilele legate ar

trebui să fie utilizate pe scară largă din rațiuni de securitate și performanță.

Tipuri de Sql Injection

Pentru bazele de date Oracle funcţionează patru tipuri de atacuri Sql Injection. Primele

dintre aceste tipuri, manipulări SQL si injectarea codului, sunt cele care sunt bine cunoscute şi

documentate. În schimb, ultimele dintre aceste tipuri, injectarea cu apeluri de funcţii şi atacuri

de tip supraîncărcare a bufferului, sunt cele pentru care nu există o documentaţie, ceea ce duce

la o creştere a vulnerabilităţii aplicaţiilor la ele. Toate aceste tipuri de SQL Injection sunt valide

şi pentru alte tipuri de baze date cum sunt SQL Server, DB2, MySQL şi PostgreSQL.

Manipularea codului SQL

Manipularea codului SQL reprezintă cea mai raspândită metodă de atac de tip SQL

Injection. Cel mai adesea, această metodă presupune modificarea instrucţiunii SQL prin

adăugarea de elemente clauzei WHERE sau extinderea instrucţiunii cu ajutorul operatorilor

UNION, INTERSECT, sau MINUS.

Exemplul clasic în care apare manipularea instrucţiunii SQL este în timpul operaţiunii de

autentificare. De exemplu, o aplicaţie web ar putea să facă autentificarea unui utilizator prin

executarea query-ului de mai jos şi apoi verificarea daca acesta a întors vreun rezultat:

SELECT * FROM users

WHERE username = 'bob' and PASSWORD = 'mypassword'

Page 8: 46735899 SQL Injection

8

Manipulând instrucţiunea de mai sus, ca în exemplul de mai jos, bazându-se pe

precendenţa operatorilor, clauza WHERE poate deveni adevarată pentru orice linie, astfel

atacatorul primind acces la datele aplicaţiei.

SELECT * FROM users

WHERE username = 'bob' and PASSWORD = 'mypassword'

or ‘a’ = ‘a’

Operatorul pentru mulţimi, UNION, este folosit adesea în atacurile de tip SQL Injection,

scopul fiind acela de a manipula o instrucţiune SQL astfel încât să returneze rânduri dintr-un alt

tabel. Spre exemplu, un formular web poate folosi următorul query pentru a returna o listă de

produse disponibile.

SELECT product_name FROM all_products

WHERE product_name like '%Chairs%'

Atacatorul este cel care ar putea încerca să manipuleze intrucţiunea SQL de mai sus, astfel

încât să returneze atât produsele dorite, dar şi o listă a utilizatorilor bazei de date, cum se vede

în exemplul de mai jos:

SELECT product_name FROM all_products

WHERE product_name like '%Chairs'

UNION

SELECT username FROM dba_users

WHERE username like '%'

Code Injection

Atacurile de tip code injection încearcă adăugarea unor instrucţiuni sau comenzi SQL

adiţionale. Acest tip de atac este utilizat adesea împotriva aplicaţiilor de tip Microsoft SQL

Server, dar funcţionează rar în cazul aplicaţiilor ce folosesc o bază de date Oracle. Instrucţiunea

EXECUTE folosită de SQL Server reprezintă o ţintă frecventă a atacurilor de tip SQL Injection,

Oracle neavând însă o instrucţiune corespunzătoare acesteia.

În aplicaţiile de tip PL/SQL sau Java, Oracle nu permite ca o cerere către baza de date să

conţină mai multe instrucţiuni SQL. Datorită acestui lucru, atacul de mai jos nu va funcţiona

într-o aplicaţie PL/SQL sau Java ce are în spate o bază de date Oracle, şi va returna o eroare:

SELECT * FROM users

Page 9: 46735899 SQL Injection

9

WHERE username = 'bob' and PASSWORD = 'mypassword';

DELETE FROM users

WHERE username = 'admin';

Însă există limbaje de programare sau diferite API-uri care permit executarea

instrucţiunilor SQL multiple. Astfel, aplicaţiile PL/SQL sau Java pot executa dinamic blocuri

PL/SQL anonime, ce sunt vulnerabile la code injection. Mai jos este prezentat un exemplu de

bloc PL/SQL ce poate fi executat într-o aplicaţie web:

BEGIN ENCRYPT PASSWORD('bob', 'mypassword'); END;

Blocul PL/SQL de mai sus execută o procedură stocată ce are ca scop criptarea si salvarea

parolei unui utilizator. Un atacator ar putea să încerce manipularea blocului PL/SQL astfel:

BEGIN ENCRYPT PASSWORD('bob', 'mypassword');

DELETE FROM users

WHERE upper(username) = upper('admin'); END;

Injectare cu apel funcţie

Injectarea folosind apeluri de funcţii reprezintă o metodă de inserare a funcţiilor în cadrul

unor instrucţiuni SQL vulnerabile. Aceste apeluri de funcţii pot fi folosite pentru a face apeluri

către funcţii ale sistemului sau pot manipula informaţii din baza de date.

Oracle permite executarea funcţiilor în cadrul unei instrucţiuni SQL. Astfel, Oracle pune la

dispoziţie peste 1000 de funcţii organizate în aproximativ 175 de pachete, însă doar câteva

dintre aceste funcţii pot fi folositoare în cazul unui atac SQL Injection (cum ar fi funcţiile care

gestionează comunicarea în reţea). Pe langă aceste funcţii, orice funcţie custom poate de

asemenea fi executată într-o instrucţiune SQL.

Funcţiile executate ca parte a unei instrucţiuni SQL SELECT nu pot face nicio modificare

asupra bazei de date, decât dacă funcţia respectivă este marcată ca “PRAGMA TRANSACTION”.

În schimb funcţiile executate în cadrul instrucţiunilor INSERT, UPDATE, sau DELETE pot aduce

modificări asupra bazei de date.

Folosindu-se de funcţiile Oracle standard, un atacator poate trimite informaţii de la baza

de date către un alt calculator sau poate executa alte atacuri folosindu-se de serverul bazei de

date. Orice instrucţiune SQL dinamică este vulnerabilă, astfel încât chiar şi cele mai simple

instrucţiuni SQL pot fi exploatate, aşa cum arată exemplul de mai jos.

SELECT TRANSLATE('user input',

Page 10: 46735899 SQL Injection

10

'0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ',

'0123456789') FROM dual;

Instrucţiunea SQL de mai sus nu este susceptibilă altor tipuri de atacuri SQL Injection, dar

poate fi uşor manipulată cu ajutorul unui atac de injectare de apel funcţie. Atacatorul poate

manipula instrucţiunea SQL astfel încât să se execute ca mai jos, ceea ce va duce la executarea

cererii de afişare a unei pagini de pe un server web. De asemenea atacatorul ar putea manipula

URL-ul pentru a include şi alte funcţii ce ar putea returna informaţii din baza de date ce vor fi

apoi trimise serverului web din cadrul URL-ului.

SELECT TRANSLATE('' ||

UTL_HTTP.REQUEST('http://192.168.1.1/') || '',

'0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ', '0123456789')

FROM dual;

Întrucât este permisă executarea funcţiilor custom şi funcţiilor din pachete custom, acest

lucru face ca anumite instrucţiuni SQL să fie vulnerabile. Un exemplu este reprezentat de o

aplicaţie ce are definită o funcţie ADDUSER în pachetul custom MYAPPADMIN. Funcţia a fost

marcată “PRAGMA TRANSACTION”, pentru a putea fi executată în orice situaţie specială ce ar

putea apărea. Datorită acestui lucru, această funcţie poate face scrieri în baza de date chiar şi

din cadrul unei instrucţiuni SELECT, cum se observă în exemplul de mai jos în care atacatorul

poate crea noi utilizatori ai aplicaţiei.

SELECT TRANSLATE('

' || myappadmin.adduser('admin', 'newpass') || '',

'0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ', '0123456789')

FROM dual;

Supraîncărcarea bufferului

Atacurile de forma supraîncărcarea bufferului sunt folosite pentru a corupe execuţia unei

aplicaţii. Prin trimiterea unor date de intrare atent construite, un atacator poate face ca

aplicaţia să execute cod arbitrar, şi poate duce de asemenea la oprirea funcţionării aplicaţiei.

Anumite funcţii standard Oracle sunt vulnerabile la supraîncărcarea bufferului, lucru ce

poate fi exploatat de către un atac SQL Injection. Printre funcţiile standard Oracle vulnerabile se

numără: BFILENAME (Oracle8i, Oracle9i), FROM_TZ (Oracle9i), NUMTODSINTERVAL (Oracle8i,

Oracle9i), NUMTOYMINTERVAL (Oracle8i, Oracle9i), TO_TIMESTAMP_TZ (Oracle9i), TZ_OFFSET

(Oracle9i).

Page 11: 46735899 SQL Injection

11

Pentru a împiedica atacurile de acest gen, este recomandat ca pachetele neesenţiale

lucrului cu baze de ate (DBMS_*, UTL_*) să nu fie accesibile utilizatorilor aplicaţiei.

PL/SQL

Instrucţiunile SQL pot fi executate în PL/SQL cu ajutorul: embedded SQL, cursoarelor,

instrucţiunilor execute immediate, sau pachetului DBMS_SQL. Instrucţiunile SQL embedded şi

cursoarele statice lucrează doar prin intermediul cererilor parametrizate, ceea ce le protejează

de atacurile SQL Injection. Însă, cursoarele dinamice pot fi vulnerabile la atacuri de tip SQL

injection, la fel ca si instrucţiunile execute immediate şi DBMS_SQL, deoarece permit folosirea

instrucţiunilor SQL dinamice.

Instrucţiunea execute immediate

Instrucţiunea execute immediate este folosită pentru execuţia instrucţiunilor SQL

dinamice în cadrul codului PL/SQL.

Sintaxa instrucţiunii execute immediate este următoarea:

EXECUTE IMMEDIATE dynamic_string

[INTO {define_variable[, define_variable]... | record}]

[USING [IN | OUT | IN OUT] bind_argument

[, [IN | OUT | IN OUT] bind_argument]...]

[{RETURNING | RETURN} INTO bind_argument

[,bind_argument]...];

Un exemplu de instrucţiune execute immediate ce este vulnerabilă atacurilor SQL

injection poate arăta astfel:

CREATE OR REPLACE PROCEDURE demo(name IN VARCHAR2) AS

sqlstr VARCHAR2(1000);

code VARCHAR2(100);

BEGIN

...

sqlstr := 'SELECT postal-code FROM states WHERE state-name = ''' ||

name || '''';

Page 12: 46735899 SQL Injection

12

EXECUTE IMMEDIATE sqlstr INTO code;

IF code = 'IL' THEN ...

...

END;

La prima vedere, instrucţiunea SQL nu pare a fi vulnerabilă. Nu poate fi manipulată cu

ajutorul operatorilor pe mulţimi şi nu poate fi adaugată o altă instrucţiune SQL întrucât acest

lucru nu este permis în cadrul unei instrucţiuni execute immediate, decât dacă este folosit un

bloc PL/SQL (ex: BEGIN ... END). Manipularea clauzei WHERE de asemenea nu ar aduce multe

rezultate. Însă, această instrucţiune poate fi exploatată cu uşurinţă, prin inserarea unor funcţii

standard (ex: UTL_HTTP) care ar putea duce la supraîncărcarea bufferului.

Pentru a preveni atacurile SQL Injection şi pentru a îmbunătăţi performanţa aplicaţiei, ar

trebui folosite întotdeauna cereri parametrizate.

CREATE OR REPLACE PROCEDURE demo(name IN VARCHAR2) AS

sqlstr VARCHAR2(1000);

code VARCHAR2(100);

BEGIN

...

sqlstr := 'SELECT postal-code FROM states WHERE state-name = :name';

EXECUTE IMMEDIATE sqlstr USING name INTO code;

IF code = 'IL' THEN ...

...

END;

Instrucţiunea execute immediate poate utiliza şi blocuri PL/SQL anonime, ceea ce o face

vulnerabilă la atacuri SQL Injection întrucât un atacator ar putea încerca inserarea mai multe

instrucţiuni SQL.

CREATE OR REPLACE PROCEDURE demo(value IN VARCHAR2) AS

BEGIN

...

-- vulnerable

Page 13: 46735899 SQL Injection

13

EXECUTE IMMEDIATE 'BEGIN updatepass(''' || value || '''); END;'; --

not vulnerable

cmd := 'BEGIN updatepass(:1); END;';

EXECUTE IMMEDIATE cmd USING value;

...

END;

Pachetul DBMS_SQL

Pachetul DBMS_SQL permite execuţia instrucţiunilor de SQL dinamic, având aceleaşi

funcţionalităţi ca şi instrucţiunea execute immediate. La fel ca şi în cazul instrucţiunii execute

immediate, ar trebui folosite întotdeauna cereri parametrizate în locul concatenării părților ce

formează stringul SQL.

Procedura prezentată mai jos foloseşte pachetul DBMS_SQL şi este vulnerabilă la atacuri:

CREATE OR REPLACE PROCEDURE demo(name IN VARCHAR2) AS

cursor_name INTEGER;

rows_processed INTEGER;

sqlstr VARCHAR2(150);

code VARCHAR2(2);

BEGIN

...

sqlstr := 'SELECT postal-code FROM states WHERE state-name = ''' ||

name || '''';

cursor_name := dbms_sql.open_cursor;

DBMS_SQL.PARSE(cursor_name, sqlstr, DBMS_SQL.NATIVE);

DBMS_SQL.DEFINE_COLUMN(cursor_name, 1, code, 10); rows_processed :=

DBMS_SQL.EXECUTE(cursor_name);

DBMS_SQL.CLOSE_CURSOR(cursor_name);

...

END;

Page 14: 46735899 SQL Injection

14

În schimb, aceeaşi procedură care foloseşte cereri parametrizate nu mai este susceptibilă

atacurilor, cum se vede în exemplul de mai jos:

CREATE OR REPLACE PROCEDURE demo(name IN VARCHAR2) AS

cursor_name INTEGER;

rows_processed INTEGER;

sqlstr VARCHAR2;

code VARCHAR2;

BEGIN

...

sqlstr := 'SELECT postal-code FROM states WHERE state-name = :name';

cursor_name := dbms_sql.open_cursor;

DBMS_SQL.PARSE(cursor_name, sqlstr, DBMS_SQL.NATIVE);

DBMS_SQL.DEFINE_COLUMN(cursor_name, 1, code, 10);

DBMS_SQL.BIND_VARIABLE(cursor_name, ':name', name); rows_processed :=

DBMS_SQL.EXECUTE(cursor_name);

DBMS_SQL.CLOSE_CURSOR(cursor_name);

...

END;

Cursoare dinamice

PL/SQL permite folosirea cursoarelor statice şi a celor dinamice. La fel ca şi instrucţiunea

execute immediate sau instrucţiunile DBMS_SQL, instrucţiunile cursor pot fi vulnerabile la

atacuri cum se vede în exemplul de mai jos. Însă ele pot fi generate în mod dinamic prin

folosirea cererilor parametrizate, ceea ce le protejează de atacurile SQL Injection.

CREATE OR REPLACE PROCEDURE demo(name IN VARCHAR2) AS

sqlstr VARCHAR2;

...

BEGIN

...

sqlstr := 'SELECT * FROM states WHERE state-name = ''' || name ||

'''';

Page 15: 46735899 SQL Injection

15

OPEN cursor_states FOR sqlstr;

LOOP

FETCH cursor_states INTO rec_state

EXIT WHEN cursor_states%NOTFOUND;

...

END LOOP;

CLOSE cursor_status;

...

END;

JDBC

JDBC (Java Database Connectivity) reprezintă o interfaţă Java standard ce gestionează

lucrul cu o bază de date relaţională. De asemenea, este folosită de foarte multe arhitecturi Java

pentru a realiza conectarea la o bază de date Oracle, cum sunt Java Server Pages (JSP), Java

Servlets, sau Enterprise Java Beans (EJB).

Prin definiţie toate instrucţiunile SQL dintr-o aplicaţie JDBC sunt dinamice. Acestea pot fi

executate cu ajutorul interfeţei Statement, mai precis a interfeţelor CallableStatement şi

PreparedStatement. Din perspectiva SQL Injection, atât Callable Statement cât şi

PreparedStatement pot fi vulnerabile.

În Oracle, în cadrul unui apel de tip PreparedStatement se poate executa o singură

instrucţiune SQL, spre deosebire de alte baze de date (ex: SQL Server) ce permit execuţia mai

multor instrucţiuni într-un singur apel.

PreparedStatement

Interfaţa PreparedStatement este folosită pentru execuţia instrucţiunilor de tip SQL

dinamic. De asemenea poate fi folosită interfaţa OraclePreparedStatement în cazul în care sunt

necesare tipuri de date specifice Oracle.

O instrucţiune PreparedStatement care e vulnerabilă la SQL Injection este prezentată în

exemplul de mai jos:

String name = request.getParameter("name");

Page 16: 46735899 SQL Injection

16

PreparedStatement pstmt =

conn.prepareStatement("insert into EMP (ENAME) values ('" + name +

"')"); pstmt.execute();

pstmt.close();

Pentru a preveni SQL Injection, o variabilă de legătură trebuie să fie folosită:

PreparedStatement pstmt =

conn.prepareStatement ("insert into EMP (ENAME) values (?)");

String name = request.getParameter("name");

pstmt.setString (1, name);

pstmt.execute();

pstmt.close();

CallableStatement

Interfaţa CallableStatement este folosită pentru execuţia procedurilor stocate PL/SQL şi a

blocurilor anonime PL/SQL. De asemenea poate fi folosită interfaţa OracleCallableStatement

dacă sunt necesare tipuri de date specifice Oracle.

Instrucţiunea CallableStatement are două forme de bază în funcţie de tipul de apel:

procedură stocată sau bloc PL/SQL anonim. Apelul de bloc PL/SQL anonim este mult mai

vulnerabil la SQL Injection întrucât permite execuţia instrucţiunilor SQL şi a comenzilor PL/SQL

multiple.

Procedura stocată

prepareCall( "{call proc (?,?)}" );

Bloc PL/SQL anonim

prepareCall("begin proc1(?,?); ? := func1(?);

...; end;");

Mai jos este prezentat un bloc PL/SQL anonim, care este vulnerabil la atacuri:

String name = request.getParameter("name");

String sql = "begin ? := GetPostalCode('" + name + "'); end;";

CallableStatement cs = conn.prepareCall(sql);

Page 17: 46735899 SQL Injection

17

cs.registerOutParameter(1, Types.CHAR);

cs.executeUpdate();

String result = cs.getString(1);

cs.close();

În cadrul unui atac, inputul ar putea fi cu mult diferit față de cel așteptat de către

dezvoltator:

begin ? := GetPostalCode('Illinois'); end;

begin ? := GetPostalCode(''); delete from users; commit; dummy('');

end;

begin ? :=

GetPostalCode(''||UTL_HTTP.REQUEST('http://192.168.1.1/')||''); end;

Cea mai simplă metodă de a preveni acest lucru este de a folosi cereri parametrizate:

String name = request.getParameter("name");

CallableStatement cs = conn.prepareCall ("begin ? :=

GetStatePostalCode(?); end;");

cs.registerOutParameter(1,Types.CHAR);

cs.setString(2, name);

cs.executeUpdate();

String result = cs.getString(1);

cs.close();

Prevenirea SQL Injection în Oracle

Cel mai eficient mod de a proteja o aplicaţie şi de a preveni atacurile rău intenţionate

asupra sa, este de a proiecta şi de a implementa un anumit nivel de securitate programului din

start. Din păcate, echipelor de dezvoltare, de obicei le lipsesc antrenamentul necesar şi

resursele pentru a lua o decizie satisfacatoare asupra proiectării securitaţii aplicaţiei.

Cereri parametrizate

Una dintre cele mai puternice tehnici de protecție împotriva atacurilor SQL Injection

folosește așa numitele cereri parametrizate. Utilizarea lor va îmbunătăți de asemenea

performanța aplicației.

Page 18: 46735899 SQL Injection

18

Interogările parametrizate tratează datele introduse ca pe nişte valori făcând parte din

comenzile SQL, în acest fel făcând imposibil ca serverul să trateze interogările parametrizate ca

şi cod executabil. Chiar dacă se utilizează procedurile stocate, parametrizarea inputului este

necesară, pentru că procedurile stocate nu oferă protecţie împotriva SQL Injection.

Scrierea codului standard Oracle al unei aplicații ar trebui să impună folosirea cererilor

parametrizate sau invocarea procedurilor stocate care sunt un caz particular de invocare al unei

cereri parametrizate. În cazul în care acest lucru nu este posibil, se recomandă crearea unor

interogări dinamice, dar cu argumentele transmise ca parametrii. Nici o comandă SQL nu

trebuie creată prin concatenarea șirurilor de caractere.

Cererile parametrizate trebuie folosite pentru fiecare comandă SQL indiferent de când sau

unde este executată această comandă.

Un atac SQL Injection foarte complex ar putea eventual să exploateze o aplicație prin

stocarea unui șir de atac în baza de date, care va fi executat mai târziu de o comandă SQL

dinamic. Acest gen de atac poartă numele de atac SQL Injection de ordinul 2.

În capitolele precedente PL/SQL și JDBC s-a demonstrat cât de folositoare sunt aceste

cereri parametrizate pentru eliminarea vulnerabilităților SQL Injection. Utilizarea cererilor

parametrizate este simplă, dar necesită cel puțin încă o linie de cod pentru fiecare variabilă.

Întrucât o comandă SQL tipică poate folosi până la 10-20 de valori, efortul depus pentru

realizarea codului suplimentar ce va securiza aplicația este substanțial.

Validarea datelor de intrare

Cea mai utilizată metodă şi mai puţin costisitoare ca timp, o reprezintă validarea datelor

primite la intrare prin identificarea tuturor posibilelor meta-caractere care ar putea fi utilizate

de către sistemul de baze de date şi de filtrare a acestora, atunci când sunt transformate în

comenzi ce vor accesa baza de date.

Orice date de intrare introduse de către utilizatori, fie direct în aplicaţia web sau deja

stocate, trebuie să fie validate după tipul serverului, lungime sau format, înainte de a fi trimise

mai departe.

În cazul bazelor de date Oracle, caracterul ce ar putea pune în pericol securitatea bazei de

date, este apostroful. Oracle interpretează ghilimelele simple consecutive ca un literal SQL, iar

cea mai simplă metodă de a rezolva această problemă este de a le elimina.

De exemplu, dacă dintr-un motiv sau altul, în loc de numele de utilizator, cineva introduce

șirul de caractere ' OR 1 = 1 -- , comanda SQL procesată devine:

Page 19: 46735899 SQL Injection

19

SELECT COUNT(*) FROM users

WHERE username = '' OR 1 = 1 -- AND password = '...'

În acest exemplu, problema apare la primul apostrof care va deveni perechea celui care

deschide șirul reprezentând numele utilizatorului. Condiția 1=1 este adevărată întotdeauna, iar

operatorul OR este adevărat dacă unul din membri este adevărat. Șirul de caractere --

reprezintă un comentariu, iar restul textului după acesta va fi ignorat. Atunci expresia din clauza

WHERE va forța alegerea unui nume de utilizator valid, deoarece intrucțiunea SQL este

adevărată tot timpul.

Folosirea cererilor parametrizate și eliminarea apostrofurilor nu trebuie folosite

concomitent pentru același șir de caractere. O cerere parametrizată va stoca în baza de date

exact datele primite la intrare, iar eliminarea apostrofurilor va avea ca rezultat stocarea

ghilimelelor duble în baza de date.

Securitatea funcțiilor apelate

Funcțiile standard de creare și executare a instrucțiunilor SQL pot fi exploatate în atacurile

SQL Injection. Multe dintre aceste funcții pot fi folosite eficace într-un atac.

Oracle are la bază sute de funcții standard, care implicit, pot avea acordate drepturi

PUBLIC. Aplicația trebuie să conțină funcții suplimentare care să execute operații precum

schimbarea parolelor sau crearea unor useri care ar putea să fie exploatați printr-un eventual

atac.

Toate funcțiile care nu sunt absolut necesare aplicației ar trebui limitate.

Mesajele de eroare

Vulnerabilitățile SQL Injection pot fi testate trimițând aplicației date care vor genera

interogări SQL invalide. Dacă în urma unui atac SQL Injection, serverul returnează mesaje de

eroare, informația poate fi folosită pentru a obține sursa codului aplicației sau pentru a avea un

acces necontrolat la baza de date.

Acesta este punctul de plecare pentru cele mai populare atacuri SQL Injection.

Însă, ascunderea mesajelor de eroare nu are ca efect oprirea atacului. În cazul în care un

atac eşuează, atacatorul poate utiliza informaţia din mesajele de eroare furnizate de server sau

aplicaţie, pentru a lansa un alt atac.

Page 20: 46735899 SQL Injection

20

Un atac ce utilizează vulnerabilitatea SQL Injection ar putea dezvălui structura unui tabel,

a bazei de date, sau să expună logica de interogare, şi posibil chiar parole sau informaţii

sensibile utilizate în interogare.

Datele obţinute din exploatarea acestei vulnerabilităţi pot avea impact ridicat sau chiar

critic asupra confidenţialităţii sistemului. Însă, aceste date la rândul lor reutilizate într-un nou

atac, fie similar, fie altul complet diferit, care ar putea compromite sistemul informaţional din

punct de vedere al confidenţialităţii, integrităţii şi disponibilităţii.

De exemplu, dacă în codul aplicației există o cerere de genul:

SELECT username

FROM users

WHERE userid = '<user_input>';

Un posibil atacator va introduce următorul cod:

10 union select top 1 table_name from information_shema.tables

va avea ca rezultat, după concatenarea string-urilor:

SELECT username

FROM users

WHERE userid = 10

UNION SELECT top 1 table_name

FROM information_shema.tables;

Serverul va eșua în efectuarea operației UNION între 10 și coloanele de tip varchar din

comanda select și va returna ca eroare : eroare de sintaxa în convertirea

coloanei din tabelul ”mytable” la o coloană de tipul int,

dezvăluind faptul că în baza de date există un tabel cu numele ”mytable”.

Pentru a evita un atac SQL Injection bazat pe mesajele de eroare primite de la serverul

aplicației, programatorul trebuie să aibă în vedere:

mesajele de eroare să conțină cât mai puține de detalii cu privire la baza de date, care pot fi utilizare pentru a compromite întreg sistemul.

mesajele de eroare nu trebuie să conțină numele metodelor, funcțiilor în care a avut loc eroarea.

mesajele de eroare trebuie păstrate într-un fișier log, însă trebuie restricționat accesul la ele pentru a evita un posibil nou atac.

Page 21: 46735899 SQL Injection

21

în fișierele log nu trebuie reținute informații precum parolele userilor.

mesajele de eroare nu trebuie să conțină informații privind evenimente interne ale sistemului, ca de exemplu, în caz de logare nereușită, utilizatorul nu trebuie să fie informații dacă există sau nu userul respectiv, ci doar că autentificarea nu a fost posibilă.

Excepții

Cererile parametrizate trebuie folosite pentru fiecare comandă SQL in PL/SQL sau Java, cu

toate că, rareori acestea nu pot fi utilizate, ca de exemplu inserarea dinamică de tabele sau

nume de coloane.

Nume de tabele dinamice

Atunci când se generează o instrucțiune SQL dinamică, variabilele de legătură nu pot fi

folosite pentru nume de tabele sau nume de coloane.

În majoritatea aplicațiilor, numele obiectelor din baza de date (tabele, nume de coloane)

pot conține doar caracatere alfanumerice, sau caracterul underscore ( _ ), semnul dolar ($) sau

diez (#). Apostroful (') sau alte caractere speciale nu sunt valide.

Orice tabel dinamic sau nume de coloană trebuie să fie validate, iar toate caracterele

invalide ar trebui eliminate, în special apostrofurile. Pentru aceasta, în PL/SQL, poate fi utilizată

funcția TRANSLATE:

translate ( upper ( <input string> ),

'ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_#$@. `~!%^*()-

=+{}[];":''?/><,|\',

'ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_#$@.');

Clauza LIKE

Variabilele de legătură sunt valide în clauzele LIKE. Caracterele % și _ ar trebui adăugate

direct la șirul de caractere, decât prin concatenarea cu instrucțiunea SQL.

Umrătoarea concatenare nu ar trebui utilizată:

String name = request.getParameter("name");

conn.prepareStatement("SELECT id

FROM users

WHERE name LIKE '%" + name + "%'");

Page 22: 46735899 SQL Injection

22

Mai degrabă se folosesc comenzi multiple și o cerere parametrizată pentru a crea în mod

corespunzător o instrucțiune SQL

String name = request.getParameter("name");

name = query.append("%").append(name).append("%");

pstmt = conn.prepareStatement("SELECT id

FROM users

WHERE name LIKE ?");

pstmt.setString (1, name);

Funcții Oracle

Oracle are la bază peste 1000 de funcții în aproximativ 175 de pachete standard care pot fi

exploatate în atacurile SQL Injection.

Determinarea privilegiilor funcțiilor

Toate funcțiile disponibile PUBLIC pot fi găsite prin următoarea cerere:

SELECT *

FROM dba_tab_privs p, all_arguments a

WHERE grantee = 'PUBLIC'

AND privilege = 'EXECUTE'

AND p.table_name = a.package_name

AND p.owner = a.owner

AND a.position = 0

AND a.in_out = 'OUT'

ORDER BY p.owner, p.table_name, p.grantee;

Page 23: 46735899 SQL Injection

23

Restricționarea accesului la funcții

Accesul la o anumită funcție dintr-un pachet nu poate fi restricționat, ci doar accesul la

întreg pachetul. Pentru a restricționa accesul PUBLIC la un pachet se folosește următoarea

comandă:

REVOKE EXECUTE ON <package_name> FROM public;

Funcții standard

Supraîncărcarea bufferelor a fost descoperită în câteva funcții standard ORACLE:

BFILENAME, TZ_OFFSET, TO_TIMESTAMP_TZ, FROM_TZ, NUMTOYMINTERVAL,

și NUMTODSINTERVAL.

Aceste funcții aparțin pachetului STANDARD și nu există nici o modalitate de a restricționa

accesul la ele.

Funcții oferite de ORACLE

Oracle oferă sute de funcții în pachetele bazei de date standard. Majoritatea acestor

pachete sunt prefixate de DBMS_ și UTL_. Dacă un anumit pachet nu este folosit de aplicație,

accesul la el ar trebui limitat.

Exemple de pachete standard:

DBMS_JAVA_TEST

DBMS_LOCK

DBMS_PIPE

DBMS_RANDOM

UTL_FILE

UTL_HTTP

UTL_SMTP

UTL_TCP

Page 24: 46735899 SQL Injection

24

Exemple reale - SQL Injection

1 noiembrie 2005 : un elev de liceu a folosit o inserție SQL pentru a pătrunde în site-ul

unei reviste de securitate taiwaneze și a fura informațiile clienților.

13 ianuare 2006 : un grup de infractori ruși au pătruns într-un site al guvernului Rhode

Island, și se presupune că a furat datele cărților de credit de la persoane care au făcut

afaceri online cu agențiile de stat.

2 martie 2007 : Sebastian Bauer a descoperit un defect de inserție SQL în pagina de

login knorr.de.

29 iunie 2007 : un infractor a neutralizat site-ul Microsoft din Marea Britanie folosind

SQL Injection. Un purtător de cuvânt al Microsoft a recunoscut problema site-ului The

Register din U.K..

ianuarie 2008 : zeci de mii de PC-uri au fost infectate de un atac SQL Injection automat,

care a exploatat o vulnerabilitate în codul aplicațiilor ce utilizează Microsoft SQL Server

pentru stocarea bazei de date.

17 august 2009 : Departamentul de Justiție al Statelor Unite au acuzat un cetățean

american, Albert Gonzalez și doi ruși anonimi de furtul a 130 milioane de numere de

cărți de credit folosind un atac SQL Injection. În relatările presei apare că “cel mai mare

caz de furt de identitate din istoria Statelor Unite”, omul a furat carduri de la un număr

de victime corporative după cercetarea sistemelor de prelucrare a plății. Printre

companiile lovite se numără: procesorul de sisteme de plată Heartland Payment

Systems, lanțul de magazine economice 7-Eleven și lanțul de supermarketuri Hannaford

Brothers.

decembrie 2009 : un atacator a pătruns într-o bază de date RockYou! prin utilizarea unui

atac SQL Injection, care conținea în format text numele de utilizator și parolele

necriptate pentru aproximativ 32 milioane de utilizatori.

Page 25: 46735899 SQL Injection

25

Bibliografie

http://www.wikipedia.org

http://unixwiz.net/techtips/sql-injection.html

“Using Database Functions in SQL Injection Attacks”

http://www.integrigy.com/security-resources

“OWASP Guide to Building Secure Web Applications”

http://www.owasp.org/index.php/Category:OWASP_Guide_Project

Additional Information on SQL Injection Attacks –

http://www.securityfocus.com/infocus/1644

http://www.nextgenss.com/papers/advanced_sql_injection.pdf

http://www.spidynamics.com/whitepapers/WhitepaperSQLInjection.pdf

Oracle Database Security Checklist –

http://otn.oracle.com/deploy/security/