WYKAAD
Z
PROJEKTOWANIA SYSTEMÓW
BAZODANOWYCH
Dynamiczny SQL
SQL injection
(dwa słowa)
ALEKSANDRA STASIAK 2014 1
Dynamiczny SQL
Jest technologią (metodologią programowania) pozwalającą
na budowanie poleceń SQL w czasie wykonania programu (np.
gdy nie znamy całej instrukcji języka SQL w momencie
kompilowania programu)
na wykonanie bloku anonimowego PL/SQL, który jest budowany
w czasie wykonania programu
na wykonywanie instrukcji SQL, których nie można wykonywać
w statycznym SQL (np. poleceń z grupy DDL)
na odłożenie walidacji instrukcji SQL do momentu jej wykonania
ALEKSANDRA STASIAK 2014 2
Dlaczego nie można statycznie wykonać poleceń DDL?
Wynika to z faktu, iż w języku PL/SQL występuje tzw. wczesne
wiązanie zmiennych, tzn. zmienne są wiązane podczas
kompilacji, a nie podczas uruchamiania programu.
Wiązanie zmiennych jest mechanizmem zamiany identyfikatora
symbolicznego (nazwy) bytu programistycznego na wartość,
adres lub wewnętrzny identyfikator tego bytu [3]). W języku
Pl/SQL uwzględnia ono także sprawdzenie istnienia obiektów,
do których odwołuje się program w słowniku bazy danych,
a także sprawdzenia praw dostępu do danego obiektu.
Wczesne wiązanie sprawia, że wydłuża się czas kompilacji, ale
skraca czas wykonania programu. Ponieważ programy języka
SQL są składowane w bazie w postaci skompilowane, a po
wywołaniu są ładowane do pamięci i mogą być współdzielone
przez różne aplikacje, więc takie rozwiązanie jest najbardziej
efektywne.
ALEKSANDRA STASIAK 2014 3
Dlaczego nie można statycznie wykonać poleceń DDL?
Ponieważ instrukcje z grupy DDL modyfikują obiekty bazy, więc
proces sprawdzania nie może zachodzić na etapie kompilacji.
Dlatego jedyną możliwością wykonania poleceń tej grupy jest
dynamiczny SQL.
W dynamicznym SQL instrukcje są tworzone w trakcie
uruchamiania programu, potem są analizowane i wykonywane.
Na etapie kompilacji nie ma mowy o tych instrukcjach,
kompilator nie musi wiązać jej identyfikatorów i PL/SQL
pozwala na skompilowanie takich bloków.
Mimo, iż taki blok jest skompilowany, nie mamy pewności, że
zawarte w nim instrukcje będą prawidłowe.
ALEKSANDRA STASIAK 2014 4
Instrukcje dopuszczane w statycznym SQL
SELECT
INSERT, UPDATE, DELETE, MERGE,
LOCK TABLE,
COMMIT, ROLLBACK, SAVEPOINT, SET TRANSACTION
ALEKSANDRA STASIAK 2014 5
Walidacja
W przypadku statycznych instrukcji SQL ich walidacja następuje
w czasie kompilacji programu. Jeśli instrukcje odwołują się do
obiektów, które nie istnieją lub mają status INVALID, to
kompilacja zakończy się błędami.
Dzięki instrukcjom dynamicznym można przygotowywać kod,
który zostanie wykorzystany w przyszłości, gdy dane obiekty
będą już istniały lub zmienią status.
Minusem jest to, że nie mamy pewności, czy skompilowane
programy zawierają poprawne instrukcje.
ALEKSANDRA STASIAK 2014 6
Dynamiczny SQL
PL/SQL dostarcza dwóch sposobów tworzenia takich instrukcji:
pierwotny (natywny) dynamiczny SQL (część języka PL/SQL)
pakiet DBMS_SQL (specjalne API)
Są pewne sytuacje, kiedy można stosować jedynie jedno z tych
rozwiązań.
ALEKSANDRA STASIAK 2014 7
Statyczny a dynamiczny SQL
Jeśli coś da się zrobić za pomocą statycznego SQL, to lepiej
wykorzystać tę opcję niż stosować dynamiczny SQL.
Stosując statyczny SQL mamy pewność, że kompilacja
zakończona sukcesem oznacza, że instrukcje odwołują się do
istniejących, poprawnych obiektów bazy i dysponujemy
odpowiednimi przywileje, aby z nich korzystać.
ALEKSANDRA STASIAK 2014 8
EXECUTE IMMEDIATE (natywny dynamiczny SQL)
*
Jeśli instrukcja dynamicznego SQL jest samowystarczalna
(niezależna?) (ang. self-contained) (nie zawiera żadnych
znaczników zmiennych wiązanych i nie zwraca żadnych
wartości, co najwyżej może zakończyć się błędem), to wtedy
instrukcja EXECUTE IMMEDIATE nie potrzebuje żadnych
klauzul.
Jeśli instrukcja dynamicznego SQL zawiera znaczniki
zmiennych wiązanych, to każdy znacznik musi mieć
odpowiadającą mu zmienną wiązaną w odpowiedniej klauzuli,
przy czym, jeśli
instrukcją tą jest polecenie SELECT, które zwraca co najwyżej
jeden wiersz, to znaczniki zwracanych zmiennych wiązanych
(typu OUT) muszą się znalezć w klauzuli INTO, a znaczniki
zmiennych wiązane typu IN - w klauzuli USING.
ALEKSANDRA STASIAK 2014 9
EXECUTE IMMEDIATE
*
jeśli instrukcją jest polecenie SELECT zwracający wiele wierszy,
to znaczniki zmiennych wiązanych typu OUT muszą się znalezć
w klauzuli BULK COLLECTION INTO, a typu IN w klauzuli
USING.
Jeśli instrukcją dynamicznego SQL jest instrukcją DML
bez klauzuli RETURNING INTO, to znaczniki zmiennych
wiązanych muszą się znalezć w klauzuli USING.
z klauzulą RETURNING INTO, to znaczniki zmiennych wiązanych
typu IN muszą być w klauzuli USING, a typu OUT w klauzuli
RETURNING INTO.
Jeśli instrukcją dynamicznego SQL jest anonimowy blok
PL/SQL lub wywołanie CALL,to znaczniki wszystkich zmiennych
wiązanych muszą być w klauzuli USING.
ALEKSANDRA STASIAK 2014 10
EXECUTE IMMEDIATE
*
Jeśli instrukcja dynamicznego SQL odwołuje się do
podprogramu, to każda zmienna wiązana, którą odpowiada
znacznikowi parametru podprogramu musi mieć ten sam tryb,
co parametr podprogramu oraz typ danych, który jest
kompatybilny z typem parametrem podprogramu. Ponadto
żadna ze zmiennych nie może mieć przypisanego typu danych,
który nie byłby wspierany przez język SQL np. typu BOOLEAN.
Klauzula USING nie może zwierać literału NULL. Można
ominąć to ograniczenie, stosując w tej klauzuli niezainicjowaną
zmienną.
ALEKSANDRA STASIAK 2014 11
BEGIN
EXECUTE IMMEDIATE 'CREATE TABLE TEST123 (
id NUMBER CONSTRAINT test123_PK PRIMARY KEY,
nazwa VARCHAR2(30) NOT NULL)';
END;
/
BEGIN
EXECUTE IMMEDIATE 'GRANT SELECT ON TEST123 TO FIRMA';
END;
/
BEGIN
FOR R IN (SELECT OWNER, TABLE_NAME FROM ALL_TABLES
WHERE OWNER='UZYTKOWNIK') LOOP
EXECUTE IMMEDIATE 'GRANT SELECT ON '||R.OWNER||'.'||R.TABLE_NAME||' TO
FIRMA';
END LOOP;
END;
/
BEGIN
FOR R IN (SELECT TABLE_NAME FROM USER_TABLES) LOOP
--DBMS_OUTPUT.put_line('DROP TABLE '||R.TABLE_NAME||' CASCADE CONSTRAINTS;');
EXECUTE IMMEDIATE 'DROP TABLE '||R.TABLE_NAME||' CASCADE CONSTRAINTS';
END LOOP;
END;
/
ALEKSANDRA STASIAK 2014 12
Uwaga
Można
BEGIN
INSERT INTO TEST123 VALUES (1,'test1');
COMMIT;
END;
/
Ale nie można
BEGIN
EXECUTE IMMEDIATE 'CREATE TABLE TEST1234 (
id NUMBER CONSTRAINT test1234_PK PRIMARY KEY,
nazwa VARCHAR2(30) NOT NULL)';
INSERT INTO TEST1234 VALUES (1,'test1');
END;
/
Error report:
ORA-06550: line 6, column 13:
PL/SQL: ORA-00942: table or view does not exist
BEGIN
EXECUTE IMMEDIATE 'CREATE TABLE TEST1234 (
id NUMBER CONSTRAINT test1234_PK PRIMARY KEY,
nazwa VARCHAR2(30) NOT NULL)';
EXECUTE IMMEDIATE 'INSERT INTO TEST1234 VALUES (1,''test1'')';
COMMIT;
END;
/
ALEKSANDRA STASIAK 2014 13
DECLARE
z_nazwa_tabeli VARCHAR2(30):='test1234';
z_czy_istnieje NUMBER(1):=0;
BEGIN
SELECT COUNT(*)
INTO z_czy_istnieje
FROM USER_TABLES
WHERE TABLE_NAME=UPPER(Z_NAZWA_TABELI);
IF(z_czy_istnieje=1) THEN
DBMS_OUTPUT.PUT_LINE('Tabela istnieje. Usuwam...');
EXECUTE IMMEDIATE 'DROP TABLE ' || z_nazwa_tabeli;
DBMS_OUTPUT.PUT_LINE('Tabela została usunięta.');
END IF;
EXECUTE IMMEDIATE 'CREATE TABLE test1234 (
id NUMBER CONSTRAINT test1234_pk PRIMARY KEY,
data DATE NOT NULL)';
DBMS_OUTPUT.PUT_LINE('Nowa tabela została utworzona.');
EXCEPTION
WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('Błąd!');
END;
/
Tabela istnieje. Usuwam...
Tabela została usunięta.
Nowa tabela została utworzona.
ALEKSANDRA STASIAK 2014 14
DECLARE
z_polecenie VARCHAR2(255);
z_nazwa_tabeli VARCHAR2(20):= 'test12345';
z_czy_istnieje NUMBER(1);
z_kolumna1 VARCHAR2(50):= 'id NUMBER';
Z_kolumna2 VARCHAR2(50):= 'nazwa varchar2(20) NOT NULL';
z_kolumna3 VARCHAR2(50):= 'data DATE NOT NULL';
BEGIN
SELECT COUNT(*)
INTO z_czy_istnieje
FROM USER_TABLES
WHERE TABLE_NAME=UPPER(z_nazwa_tabeli);
IF(z_czy_istnieje=1) THEN
EXECUTE IMMEDIATE 'DROP TABLE ' || z_nazwa_tabeli;
DBMS_OUTPUT.put_line('Usuwam tabelę!');
END IF;
EXECUTE IMMEDIATE 'CREATE TABLE ' || z_nazwa_tabeli || '(' ||
Z_kolumna1 || ' CONSTRAINT ' || z_nazwa_tabeli || '_PK PRIMARY KEY,'
||
Z_kolumna2 ||' ,' || Z_kolumna3 || ')' ;
DBMS_OUTPUT.put_line('Tabela została utworzona.');
END;
/
ALEKSANDRA STASIAK 2014 15
Tworzenie instrukcji przez sklejanie łańcuchów
Należy pamiętać o tym, że tworzenie instrukcji poprzez
sklejanie łańcuchów jest niebezpieczne dla aplikacji.
W przypadku, gdy fragmenty kodu pochodzą od użytkownika
istnieje możliwość zaistnienia ataku SQL Injection.
Dlatego trzeba walidować dane oraz stosować zmienne
wiązane.
W przypadku EXECUTE IMMEDIATE można za pomocą
klauzuli USING podawać wartości odpowiednich znaczników
zmiennych wiązanych (według kolejności występowania), nie
można jednak w ten sposób przekazywać nazw obiektów, do
których się odwołujemy.
ALEKSANDRA STASIAK 2014 16
CREATE SEQUENCE owoce_seq START WITH 1 INCREMENT BY 1;
DECLARE
polecenie VARCHAR2(80);
*
BEGIN
polecenie:='INSERT INTO owoce VALUES(owoce_seq.NEXTVAL, :nazwa )';
EXECUTE IMMEDIATE polecenie USING 'gruszka' ;
EXECUTE IMMEDIATE polecenie USING 'śliwka' ;
EXECUTE IMMEDIATE polecenie USING 'malina' ;
COMMIT;
END;
/
CREATE SEQUENCE autorzy_seq START WITH 80 INCREMENT BY 1;
DECLARE
polecenie VARCHAR2(80);
BEGIN
polecenie:='INSERT INTO autorzy VALUES(autorzy_seq.NEXTVAL, :1, :2
)';
EXECUTE IMMEDIATE polecenie USING 'Alfred', 'Szklarski';
EXECUTE IMMEDIATE polecenie USING 'Zbigniew', 'Nienacki' ;
EXECUTE IMMEDIATE polecenie USING 'Karol', 'May';
COMMIT;
END;
/
ALEKSANDRA STASIAK 2014 17
DECLARE
z_nazwisko czytelnicy.nazwisko%TYPE;
z_rowid ROWID;
z_polecenie VARCHAR2(200);
*
BEGIN
z_polecenie:='UPDATE czytelnicy
SET imie1=:1
WHERE id_czytelnika=:2
RETURNING nazwisko, rowid INTO :3, :4';
EXECUTE IMMEDIATE z_polecenie USING 'HANNA', 12 RETURNING INTO
z_nazwisko, z_rowid ;
DBMS_OUTPUT.put_line('Nazwisko: ' || z_nazwisko || ', rowid: ' ||
z_rowid );
EXECUTE IMMEDIATE z_polecenie USING 'PAWEA', 5 RETURNING INTO
z_nazwisko, z_rowid ;
DBMS_OUTPUT.put_line('Nazwisko: ' || z_nazwisko || ', rowid: ' ||
z_rowid );
END;
/
Nazwisko: ZABAOCKA, rowid: AAAGd7AAEAAADy1AAL
Nazwisko: OKOC, rowid: AAAGd7AAEAAADy1AAE
ALEKSANDRA STASIAK 2014 18
DECLARE
z_liczba NUMBER;
z_polecenie VARCHAR2(200);
*
BEGIN
z_Polecenie:='SELECT COUNT(id_czytelnika)
INTO :ile
FROM czytelnicy
WHERE plec=:1';
EXECUTE IMMEDIATE z_polecenie INTO z_liczba USING 'K' ;
DBMS_OUTPUT.put_line('Ile: ' || z_liczba);
END;
/
Ile: 6
ALEKSANDRA STASIAK 2014 19
CREATE OR REPLACE PROCEDURE wydawnictwo_ile_ksiazek
(p_nazwa IN wydawnictwa.nazwa%TYPE, p_ile OUT NUMBER) IS
BEGIN
SELECT COUNT(id_ksiazki)
*
INTO p_ile
FROM ksiazki JOIN wydawnictwa USING(id_wydawnictwa)
WHERE nazwa=p_nazwa;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.put_line('Brak książek');
END;
/
DECLARE
z_nazwa wydawnictwa.nazwa%TYPE:='HELION';
z_ile NUMBER;
z_blok VARCHAR2(200);
BEGIN
z_blok:='BEGIN wydawnictwo_ile_ksiazek(:1, :2); END;';
EXECUTE IMMEDIATE z_blok USING IN z_nazwa, OUT z_ile ;
DBMS_OUTPUT.put_line('Ile: ' || z_ile);
END;
/
Ile: 2
ALEKSANDRA STASIAK 2014 20
Zmienne wiązane
Używanie zmiennych wiązanych zwiększa wydajność, gdyż nie
trzeba wielokrotnie przetwarzać tego samego polecenia (co
wpływa zarówno na szybkość jak i na ilość zużytej pamięci).
ALEKSANDRA STASIAK 2014 21
DECLARE
z_polecenie VARCHAR2(80);
z_numer_kursora NUMBER;
*
z_ile_wierszy NUMBER;
BEGIN
z_polecenie:='INSERT INTO autorzy VALUES(autorzy_seq.NEXTVAL, :imie, :nazwisko)';
z_numer_kursora:= DBMS_SQL.open_cursor;
DBMS_SQL.parse(z_numer_kursora, z_polecenie, DBMS_SQL.NATIVE );
DBMS_SQL.bind_variable(z_numer_kursora, ':imie', 'Erich' );
DBMS_SQL.bind_variable(z_numer_kursora, ':nazwisko', 'Segal' );
z_ile_wierszy := DBMS_SQL.execute(z_numer_kursora);
DBMS_SQL.bind_variable(z_numer_kursora, ':imie', 'Graham' );
DBMS_SQL.bind_variable(z_numer_kursora, ':nazwisko', 'Greene' );
z_ile_wierszy := DBMS_SQL.execute(z_numer_kursora);
DBMS_SQL.close_cursor(z_numer_kursora);
COMMIT;
END;
/
ALEKSANDRA STASIAK 2014 22
DECLARE
z_id czytelnicy.id_czytelnika%TYPE;
z_imie autorzy.imie%TYPE;
z_nazwisko autorzy.nazwisko%TYPE:='KOWALSKI';
*
z_polecenie VARCHAR2(80);
z_numer_kursora NUMBER;
z_ile_wierszy NUMBER;
BEGIN
z_polecenie:='SELECT id_czytelnika, imie1 FROM czytelnicy
WHERE nazwisko=:n';
z_numer_kursora:= DBMS_SQL.open_cursor;
DBMS_SQL.parse(z_numer_kursora, z_polecenie,DBMS_SQL.NATIVE);
DBMS_SQL.bind_variable(z_numer_kursora, ':n', z_nazwisko );
DBMS_SQL.define_column(z_numer_kursora, 1, z_id);
DBMS_SQL.define_column(z_numer_kursora, 2, z_imie, 15);
z_ile_wierszy:= DBMS_SQL.execute(z_numer_kursora);
WHILE (DBMS_SQL.fetch_rows(z_numer_kursora)>0) LOOP
DBMS_SQL.column_value(z_numer_kursora, 1, z_id);
DBMS_SQL.column_value(z_numer_kursora, 2, z_imie);
DBMS_OUTPUT.put_line(z_id ||' , ' || z_imie);
7 , BARTAOMIEJ
END LOOP; 9 , TOMASZ
DBMS_SQL.close_cursor(z_numer_kursora);
END;
/
ALEKSANDRA STASIAK 2014 23
SQL Injection kilka słów
Atak typu SQL Injection polega na takiej zmianie jednego lub
kilku parametrów zapytania (query) wysyłanego do bazy danych
typu SQL, że polecenie to staje się niezgodne z zamierzeniem
autora skryptu. [9]
Zamiast odpowiedniej wartości parametru przesyłany jest
odpowiednio skonstruowany łańcuch znaków.
Zazwyczaj taki atak jest możliwy z powodu braku odpowiedniej
walidacji wartości przekazywanych przez użytkownika.
ALEKSANDRA STASIAK 2014 24
SQL Injection
Może on doprowadzić do m. in. do
możliwości ominięcia mechanizmu uwierzytelnienia
nieautoryzowanego dostępu do danych (odczytywania lub
modyfikacji obiektów bazy danych, kradzież poufnych danych)
możliwości odczytania wybranych plików / tworzenia plików
w systemie operacyjny
możliwości wykonania kodu w systemie operacyjnym
ALEKSANDRA STASIAK 2014 25
Przykłady pochodzą z [12], zostały dostosowane do naszych potrzeb.
CREATE TABLE logowanie_test(
login VARCHAR2(40) CONSTRAINT logowanie_test_pk PRIMARY KEY,
haslo VARCHAR2(40) NOT NULL);
INSERT INTO logowanie_test VALUES ('admin', 'admin');
INSERT INTO logowanie_test VALUES ('user', 'user');
COMMIT;
CREATE OR REPLACE PROCEDURE logowanie_test1
(p_login logowanie_test.login%TYPE, p_haslo logowanie_test.haslo%TYPE) IS
z_polecenie VARCHAR2(200):='SELECT * FROM logowanie_test WHERE login = ''' || P_LOGIN ||
''' AND haslo = ''' || P_HASLO || '''';
z_dane logowanie_test%ROWTYPE;
BEGIN
DBMS_OUTPUT.PUT_LINE ('Polecenie: ' || z_polecenie);
EXECUTE IMMEDIATE Z_POLECENIE INTO Z_DANE;
DBMS_OUTPUT.PUT_LINE ('Poprawny');
DBMS_OUTPUT.PUT_LINE ('Witaj ' || z_dane.login || '!');
EXCEPTION WHEN OTHERS THEN
RAISE_APPLICATION_ERROR(-20000, 'Niepoprawny!');
END;
/
ALEKSANDRA STASIAK 2014 26
BEGIN
LOGOWANIE_TEST1('admin', 'admin');
END;
/
POLECENIE: SELECT * FROM LOGOWANIE_TEST WHERE LOGIN = 'admin' AND HASLO = 'admin'
Poprawny
Witaj admin!
BEGIN
LOGOWANIE_TEST1('admin', 'ffdfdfdf');
END;
/
POLECENIE: SELECT * FROM LOGOWANIE_TEST WHERE LOGIN = 'admin' AND HASLO = 'ffdfdfdf'
Error report:
ORA-20000: Niepoprawny!
ORA-06512: AT "UZYTKOWNIK.LOGOWANIE_TEST1", LINE 24
ORA-06512: AT LINE 2
BEGIN
LOGOWANIE_TEST1(''' or 1=1 and Rownum=1 --','ffhfffhf');
END;
/
Polecenie: SELECT * FROM logowanie_test WHERE login = '' or 1=1 and Rownum=1 --' AND haslo =
'ffhfffhf'
Poprawny
Witaj admin!
ALEKSANDRA STASIAK 2014 27
Na szczęście
BEGIN
LOGOWANIE_TEST1(''' or 1=1 and Rownum=1; DROP TABLE logowanie_test; --','ffhfffhf');
END;
/
Polecenie: SELECT * FROM logowanie_test WHERE login = '' or 1=1 and Rownum=1; DROP TABLE
logowanie_test; --' AND haslo = 'ffhfffhf'
Error report:
ORA-20000: Niepoprawny!
ORA-06512: at "UZYTKOWNIK.LOGOWANIE_TEST1", line 26
ORA-06512: at line 2
ALEKSANDRA STASIAK 2014 28
Przykłady pochodzą z [12], zostały dostosowane do naszych potrzeb.
CREATE OR REPLACE PROCEDURE pokaz_zawartosc_kolumny1 (p_nazwa_kolumny VARCHAR2, p_nazwa_tabeli
VARCHAR2) IS
TYPE t IS VARRAY(200) OF VARCHAR2(25);
wynik t;
Z_POLECENIE VARCHAR2(200) := 'SELECT '|| p_nazwa_kolumny || ' FROM '|| p_nazwa_tabeli;
BEGIN
DBMS_OUTPUT.PUT_LINE ('Polecenie: ' || z_polecenie);
EXECUTE IMMEDIATE z_polecenie BULK COLLECT INTO wynik;
FOR J IN 1..wynik.COUNT() LOOP
DBMS_OUTPUT.put_line(wynik(j));
END LOOP;
END;
/
Ponieważ zapytanie zwraca wiele wierszy, to jego wynik jest wrzucany do pewnej kolekcji
indeksowanej kolejnymi liczbami naturalnymi. Pętla for pozwala przejrzeć tę kolekcję,
COUNT() jest metoda zwracającą liczbę elementów w kolekcji.
ALEKSANDRA STASIAK 2014 29
BEGIN
pokaz_zawartosc_kolumny1('imie1', 'czytelnicy');
END;
/
Polecenie: SELECT imie1 FROM czytelnicy
ZOFIA
MAGDALENA
EWELINA
KRYSTYNA
PAWEA
HANNA
BARTAOMIEJ
JAKUB
TOMASZ
...
BEGIN
pokaz_zawartosc_kolumny1('imie1', 'czytelnicy WHERE 1=2 UNION SELECT USERNAME C1 FROM
ALL_USERS --');
END;
/
Polecenie: SELECT imie1 FROM czytelnicy where 1=2 union select Username c1 from All_Users --
ADMINISTRATORZY
ANONYMOUS
BIBLIOTEKA
...
ALEKSANDRA STASIAK 2014 30
Zapobieganie
Sprawdzanie wszystkich danych pochodzących z zewnątrz:
stosowanie funkcji sprawiających, że znaki apostrofu,
cudzysłowu, ukośnika nie są traktowane jako znaki specjalne
stosowanie wyrażeń regularnych
rzutowanie wartości na typ liczbowy (tam, gdzie wartość podana
przez użytkownika powinna być liczbą)
stosowanie funkcji dedykowanych dla danego sytemu
sprawdzających istnienie pewnych obiektów, do których się
odwołujemy
Stosowanie mechanizmu zmiennych wiązanych!!!
Udostępnianie użytkownikowi minimalnych uprawnień
potrzebnych do wykonywania jego działań.
ALEKSANDRA STASIAK 2014 31
Zapobieganie
Można badać zapytania pod względem składniowym (czy nie
zawierają --, UNION, itd.), ale można byłoby dojść do momentu,
kiedy tak obciążymy aplikację, że właściwie zablokujemy jej
działanie.
ALEKSANDRA STASIAK 2014 32
CREATE OR REPLACE PROCEDURE logowanie_test2
(p_login logowanie_test.login%TYPE, p_haslo logowanie_test.haslo%TYPE) IS
z_polecenie VARCHAR2(200):='SELECT * FROM logowanie_test WHERE login = :1 AND haslo =:2';
z_dane logowanie_test%ROWTYPE;
BEGIN
DBMS_OUTPUT.PUT_LINE ('Polecenie: ' || z_polecenie);
EXECUTE IMMEDIATE Z_POLECENIE INTO Z_DANE USING p_login, p_haslo;
DBMS_OUTPUT.PUT_LINE ('Poprawny');
DBMS_OUTPUT.PUT_LINE ('Witaj ' || z_dane.login || '!');
EXCEPTION WHEN OTHERS THEN
RAISE_APPLICATION_ERROR(-20000, 'Niepoprawny!');
END;
/
BEGIN
LOGOWANIE_TEST2('admin', 'admin');
END;
/
Polecenie: SELECT * FROM logowanie_test WHERE login = :1 AND haslo =:2
POPRAWNY
Witaj admin!
ALEKSANDRA STASIAK 2014 33
BEGIN
LOGOWANIE_TEST2('admin', 'ffdfdfdf');
END;
/
Polecenie: SELECT * FROM logowanie_test WHERE login = :1 AND haslo =:2
Error report:
ORA-20000: Niepoprawny!
ORA-06512: at "UZYTKOWNIK.LOGOWANIE_TEST2", line 25
ORA-06512: at line 2
BEGIN
LOGOWANIE_TEST2(''' or 1=1 and Rownum=1 --','ffhfffhf');
END;
/
Polecenie: SELECT * FROM logowanie_test WHERE login = :1 AND haslo =:2
Error report:
ORA-20000: Niepoprawny!
ORA-06512: at "UZYTKOWNIK.LOGOWANIE_TEST2", line 25
ORA-06512: at line 2
ALEKSANDRA STASIAK 2014 34
CREATE OR REPLACE PROCEDURE pokaz_zawartosc_kolumny2 (p_nazwa_kolumny VARCHAR2, p_nazwa_tabeli
VARCHAR2) IS
TYPE t IS VARRAY(200) OF VARCHAR2(25);
wynik t;
Z_POLECENIE VARCHAR2(200) := 'SELECT '|| dbms_assert.simple_sql_name(p_nazwa_kolumny) || '
FROM '|| dbms_assert.simple_sql_name(p_nazwa_tabeli);
BEGIN
DBMS_OUTPUT.PUT_LINE ('Polecenie: ' || z_polecenie);
EXECUTE IMMEDIATE z_polecenie BULK COLLECT INTO wynik;
FOR J IN 1..wynik.COUNT() LOOP
DBMS_OUTPUT.put_line(wynik(j));
END LOOP;
dbms_assert.simple_sql_name
END;
- sprawdza, czy jej argument jest poprawną nazwą SQL
/
BEGIN
pokaz_zawartosc_kolumny2('imie1', 'czytelnicy WHERE 1=2 UNION SELECT USERNAME C1 FROM
ALL_USERS --'); END;
/
Error report:
ORA-44003: invalid SQL name
ORA-06512: at "SYS.DBMS_ASSERT", line 146
ORA-06512: at "UZYTKOWNIK.POKAZ_ZAWARTOSC_KOLUMNY2", line 4
ORA-06512: at line 2
44003. 0000 - "invalid SQL name"
ALEKSANDRA STASIAK 2014 35
Bibliografia
1) Oracle Database PL/SQL Language Reference 11g Release 2 (11.2),
E25519-12
2) Andrzej Klusiewicz, Dynamiczny SQL w PL/SQL
http://andrzejklusiewicz.blogspot.com/search?q=dynamiczny
3) http://edu.pjwstk.edu.pl/wyklady/pri/scb/index34.html
4) Dynamiczny SQL i PL/SQL, transakcje, przykłady
http://kursy24.eu/plsql/view/item/prezentacje
5) Oracle TimesTen In-Memory Database PL/SQL Packages Reference 11g
Release 2 (11.2.2), E21645-03, 7 DBMS_SQL
http://docs.oracle.com/cd/E11882_01/timesten.112/e21645/d_sql.htm#TTPLP058
6) Anna Kowalczyk-Niewiadomy, Dominik Niewiadomy, Przetwarzanie poleceń
języka SQL wewnątrz kodu PL/SQL w Oracle Database 11g i dawniej
http://www.ploug.org.pl/plougtki.php?action=read&p=50&a=10
ALEKSANDRA STASIAK 2014 36
Bibliografia
7) Wykłady prof. dr. hab. T. Antczaka (Uniwersytet Aódzki)
8) Kevin Loney, Oracle Database 10g. Kompendium Administratora,
Helion 2005
9) http://pl.wikibooks.org/wiki/PHP/SQL_Injection
10) Czym jest SQL Injection?
http://www.securitum.pl/baza-wiedzy/publikacje/sql-injection
11) Atak SQL Injection
http://www.poradnik-webmastera.com/artykuly/bazy_danych/sql_injection.php
12) Tutorial on Defending Against SQL Injection Attacks!
http://download.oracle.com/oll/tutorials/SQLInjection/index.htm
ALEKSANDRA STASIAK 2014 37
Wyszukiwarka
Podobne podstrony:
wyklad pl sql7WYKŁAD PLWYKŁAD PLWYKŁAD PLWyklad 7 Nieparametryczne metody statystyczne PL [tryb zgodności]notatek pl wyklad 3 model krazenia odpadow wyklad04 PL wykladnotatek pl zarzadzanie jakoscia dr janusz niezgoda wykladynotatek pl chemia budowlana wykladyPrzestrzenie zakrzywione(Feynmana wyklad 44 z tomu drugiego)(osiolek pl)notatek pl wyklad 5 planowanie przestrzenne wyklad02 PL wyklad562 pl wyklady z dnia lutego 11Wyklad 8 iloczyn rozpuszczalnosci,koloidy antastic plnotatek pl wyklad 7 odpady torfowe weglowe wykladwyklad 9 Wnioskowanie o proporcjach PL [tryb zgodności]notatek pl teoria polityki wykladywięcej podobnych podstron