Wstrzyknięcie SQL
Wstrzyknięcie SQL
Wstrzyknięcie SQL to technika wstrzykiwania kodu, która może zniszczyć Twoją bazę danych.
Wstrzykiwanie SQL jest jedną z najczęstszych technik hakerskich.
Wstrzyknięcie SQL to umieszczanie złośliwego kodu w instrukcjach SQL za pośrednictwem danych wejściowych na stronie internetowej.
SQL na stronach internetowych
Wstrzyknięcie SQL zwykle występuje, gdy poprosisz użytkownika o wprowadzenie danych, takich jak nazwa użytkownika/identyfikator użytkownika, a zamiast nazwy/identyfikatora użytkownik podaje instrukcję SQL, którą nieświadomie uruchomisz w swojej bazie danych.
Spójrz na poniższy przykład, który tworzy
SELECT
instrukcję przez dodanie zmiennej (txtUserId) do wybranego ciągu. Zmienna jest pobierana z danych wejściowych użytkownika (getRequestString):
Przykład
txtUserId = getRequestString("UserId");
txtSQL = "SELECT *
FROM Users WHERE UserId = " + txtUserId;
Pozostała część tego rozdziału opisuje potencjalne zagrożenia związane z używaniem danych wejściowych użytkownika w instrukcjach SQL.
Wstrzykiwanie SQL oparte na 1 = 1 jest zawsze prawdziwe
Spójrz ponownie na powyższy przykład. Pierwotnym celem kodu było stworzenie instrukcji SQL w celu wybrania użytkownika o podanym identyfikatorze użytkownika.
Jeśli nic nie stoi na przeszkodzie, aby użytkownik wprowadził „złe” dane wejściowe, użytkownik może wprowadzić „inteligentne” dane wejściowe w następujący sposób:
Identyfikator użytkownika:
Wtedy instrukcja SQL będzie wyglądać tak:
SELECT * FROM Users WHERE UserId = 105 OR 1=1;
Powyższy kod SQL jest prawidłowy i zwróci WSZYSTKIE wiersze z tabeli „Użytkownicy”, ponieważ LUB 1=1 jest zawsze PRAWDĄ.
Czy powyższy przykład wygląda niebezpiecznie? Co się stanie, jeśli tabela „Użytkownicy” zawiera nazwy i hasła?
Powyższa instrukcja SQL jest bardzo podobna do tej:
SELECT UserId, Name, Password
FROM Users WHERE UserId = 105 or 1=1;
Haker może uzyskać dostęp do wszystkich nazw użytkowników i haseł w bazie danych, po prostu wstawiając 105 LUB 1=1 w polu wejściowym.
Wstrzykiwanie SQL oparte na „”=” jest zawsze prawdziwe
Oto przykład logowania użytkownika na stronie internetowej:
Nazwa użytkownika:
Hasło:
Przykład
uName = getRequestString("username");
uPass = getRequestString("userpassword");
sql = 'SELECT * FROM Users WHERE Name ="' + uName + '" AND Pass ="' + uPass +
'"'
Wynik
SELECT * FROM Users WHERE Name ="John Doe" AND Pass ="myPass"
Haker może uzyskać dostęp do nazw użytkowników i haseł w bazie danych, po prostu wstawiając „ LUB „”= w polu tekstowym nazwy użytkownika lub hasła:
Nazwa Użytkownika:
Hasło:
Kod na serwerze utworzy prawidłową instrukcję SQL, taką jak ta:
Wynik
SELECT * FROM Users WHERE Name ="" or ""="" AND Pass ="" or ""=""
Powyższy kod SQL jest prawidłowy i zwróci wszystkie wiersze z tabeli „Użytkownicy”, ponieważ LUB „”=” jest zawsze PRAWDA.
Wstrzykiwanie SQL na podstawie wsadowych instrukcji SQL
Większość baz danych obsługuje wsadowe instrukcje SQL.
Partia instrukcji SQL to grupa co najmniej dwóch instrukcji SQL oddzielonych średnikami.
Poniższa instrukcja SQL zwróci wszystkie wiersze z tabeli „Użytkownicy”, a następnie usunie tabelę „Dostawcy”.
Przykład
SELECT * FROM Users; DROP TABLE Suppliers
Spójrz na następujący przykład:
Przykład
txtUserId = getRequestString("UserId");
txtSQL = "SELECT *
FROM Users WHERE UserId = " + txtUserId;
Oraz następujące dane wejściowe:
Identyfikator użytkownika:
Poprawna instrukcja SQL wyglądałaby tak:
Wynik
SELECT * FROM Users WHERE
UserId = 105; DROP TABLE Suppliers;
Użyj parametrów SQL do ochrony
Aby chronić witrynę internetową przed wstrzyknięciem SQL, możesz użyć parametrów SQL.
Parametry SQL to wartości, które są dodawane do zapytania SQL w czasie wykonywania w kontrolowany sposób.
Przykład brzytwy ASP.NET
txtUserId = getRequestString("UserId");
txtSQL = "SELECT *
FROM Users WHERE UserId = @0";
db.Execute(txtSQL,txtUserId);
Zauważ, że parametry są reprezentowane w instrukcji SQL przez znacznik @.
Silnik SQL sprawdza każdy parametr, aby upewnić się, że jest on poprawny dla jego kolumny i czy jest traktowany dosłownie, a nie jako część wykonywanego kodu SQL.
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);
Przykłady
Poniższe przykłady pokazują, jak tworzyć sparametryzowane zapytania w niektórych popularnych językach internetowych.
WYBIERZ OŚWIADCZENIE W ASP.NET:
txtUserId = getRequestString("UserId");
sql = "SELECT * FROM Customers WHERE CustomerId = @0";
command = new SqlCommand(sql);
command.Parameters.AddWithValue("@0",txtUserId);
command.ExecuteReader();
WSTAW W OŚWIADCZENIE 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();
WPISAĆ DO OŚWIADCZENIA 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();