Najnowsze tutoriale tworzenie stron internetowych
 

SQL Iniekcja


SQL Injection może zniszczyć bazę danych.


SQL na stronach internetowych

W poprzednich rozdziałach, nauczyłeś się, aby pobrać (i aktualizację baz danych), za pomocą SQL.

Kiedy SQL służy do wyświetlania danych na stronie internetowej, to jest wspólne pozwolić wejściowe użytkowników Internetu własnych wartości wyszukiwania.

Ponieważ SQL są tylko tekst, to jest łatwe, z małym kawałkiem kodu komputerowego, aby dynamicznie zmieniać SQL, aby zapewnić użytkownikowi wybranych danych:

Kod Server

txtUserId = getRequestString("UserId");
txtSQL = "SELECT * FROM Users WHERE UserId = " + txtUserId;

W powyższym przykładzie, tworzy select dodając zmienną (txtUserId) do wybranej ciąg. Zmienna jest pobierany z wejścia użytkownika (request) do strony.

Pozostała część tego rozdziału opisuje potencjalne zagrożenia związane z wykorzystaniem danych wprowadzanych przez użytkownika w instrukcji SQL.


SQL Injection

SQL injection to technika, w której szkodliwi użytkownicy mogą wstrzyknąć poleceń SQL do instrukcji SQL, poprzez wejście stronie internetowej.

Wstrzykiwane polecenia SQL może zmienić zapytanie SQL i zagrozić bezpieczeństwu aplikacji internetowej.


SQL Injection na podstawie 1 = 1 jest zawsze prawdziwe

Spójrz na przykład powyżej, jeszcze raz.

Powiedzmy, że pierwotnym celem kodu było utworzyć instrukcję SQL, aby wybrać użytkownika z danym identyfikatorem użytkownika.

Jeśli nie ma nic do uniemożliwić użytkownikowi wpisanie "wrong" wejście, użytkownik może wprowadzić pewne "smart" wejście takiego:

Identyfikator użytkownika:

serwer Rezultat

SELECT * FROM Users WHERE UserId = 105 or 1=1

Powyższy SQL jest ważny. Będzie ona zwrócić wszystkie wiersze z tabeli Users, ponieważ WHERE 1 = 1 zawsze jest prawdziwe.

Czy powyższy przykład wydawać się niebezpieczny? Co zrobić, jeśli tabela zawiera nazwy użytkowników i hasła?

Instrukcja SQL powyżej jest taka sama jak ta:

SELECT UserId, Name, Password FROM Users WHERE UserId = 105 or 1=1

Inteligentny haker może uzyskać dostęp do wszystkich nazw użytkowników i haseł w bazie danych, po prostu wkładając 105 lub 1 = 1 w polu wprowadzania.


SQL Injection podstawie ""="" jest zawsze prawdziwe

Oto wspólna budowa, używane do weryfikacji użytkownika zalogować się na stronie internetowej:

Nazwa Użytkownika:

Hasło:

Kod Server

uName = getRequestString("UserName");
uPass = getRequestString("UserPass");

sql = "SELECT * FROM Users WHERE Name ='" + uName + "' AND Pass ='" + uPass + "'"

Inteligentny haker może uzyskać dostęp do nazw użytkowników i haseł w bazie danych, po prostu wkładając "lub ""=" w polu tekstowym Nazwa użytkownika lub hasło.

Kod na serwerze stworzy poprawną instrukcję SQL tak:

Wynik

SELECT * FROM Users WHERE Name ="" or ""="" AND Pass ="" or ""=""

Wynik SQL jest ważny. Będzie ona zwrócić wszystkie wiersze z tabeli Users, gdzie "od" = "" jest zawsze prawdziwe.


SQL Injection podstawie batched instrukcji SQL

Większość baz danych obsługują batched SQL, oddzielając je średnikiem.

Przykład

SELECT * FROM Users; DROP TABLE Suppliers

SQL powyżej zwróci wszystkie wiersze w tabeli użytkowników, a następnie usunąć tabelę zwanych dostawców.

Gdybyśmy mieli następujący kod serwera:

Kod Server

txtUserId = getRequestString("UserId");
txtSQL = "SELECT * FROM Users WHERE UserId = " + txtUserId;

Oraz następujące wejścia:

Identyfikator użytkownika:

Kod na serwerze by utworzyć prawidłowy instrukcję SQL tak:

Wynik

SELECT * FROM Users WHERE UserId = 105; DROP TABLE Suppliers

Parametry dla Ochrony

Niektórzy developerzy używać "blacklist" słów lub znaków, aby szukać na wejściu SQL, aby zapobiec atakom SQL injection.

Nie jest to bardzo dobry pomysł. Wiele z tych słów (jak usuwać lub spadek) oraz znaków (np średnikiem i cudzysłowów), są używane w języku potocznym, a powinno być dozwolone w wielu typów danych wejściowych.

(W rzeczywistości powinno być całkowicie legalne wejście instrukcji SQL w polu bazy danych.)

Jedynym sprawdzonym sposobem, aby chronić stronę internetową przed atakami SQL injection, jest wykorzystanie parametrów SQL.

SQL parametry są wartościami, które są dodawane do zapytania SQL w czasie wykonywania, w sposób kontrolowany.

Przykład ASP.NET Razor

txtUserId = getRequestString("UserId");
txtSQL = "SELECT * FROM Users WHERE UserId = @0";
db.Execute(txtSQL,txtUserId);

Należy zauważyć, że parametry są reprezentowane w instrukcji SQL przez @ markera.

Silnik SQL sprawdza każdy parametr, aby upewnić się, że jest to właściwe dla jego kolumny i są traktowane dosłownie, a nie jako część SQL do wykonania.

Inny przykład

txtNam = getRequestString("CustomerName");
txtAdd = getRequestString("Address");
txtCit = getRequestString("City");
txtSQL = "INSERT INTO Customers (CustomerName,Address,City) Values(@0,@1,@2)";
db.Execute(txtSQL,txtNam,txtAdd,txtCit);

Przed chwilą dowiedziałem się, aby uniknąć SQL injection. Jeden z najpopularniejszych luk witryn.


Przykłady

Poniższe przykłady pokazuje jak budować zapytania parametryzowane w niektórych popularnych języków internetowych.

Instrukcja SELECT w ASP.NET:

txtUserId = getRequestString("UserId");
sql = "SELECT * FROM Customers WHERE CustomerId = @0";
command = new SqlCommand(sql);
command.Parameters.AddWithValue("@0",txtUserID);
command.ExecuteReader();

INSERT INTO w ASP.NET:

txtNam = getRequestString("CustomerName");
txtAdd = getRequestString("Address");
txtCit = getRequestString("City");
txtSQL = "INSERT INTO Customers (CustomerName,Address,City) Values(@0,@1,@2)";
command = new SqlCommand(txtSQL);
command.Parameters.AddWithValue("@0",txtNam);
command.Parameters.AddWithValue("@1",txtAdd);
command.Parameters.AddWithValue("@2",txtCit);
command.ExecuteNonQuery();

INSERT INTO oświadczenie w PHP:

$stmt = $dbh->prepare("INSERT INTO Customers (CustomerName,Address,City)
VALUES (:nam, :add, :cit)");
$stmt->bindParam(':nam', $txtNam);
$stmt->bindParam(':add', $txtAdd);
$stmt->bindParam(':cit', $txtCit);
$stmt->execute();