SQL Injection
SQL Injection
SQL injection je technika vkládání kódu, která může zničit vaši databázi.
SQL injection je jednou z nejběžnějších technik hackování webu.
SQL injection je umístění škodlivého kódu do příkazů SQL prostřednictvím vstupu na webové stránce.
SQL na webových stránkách
Vložení SQL obvykle nastane, když požádáte uživatele o vstup, jako je jeho uživatelské jméno/uživatelské jméno, a místo jména/id vám uživatel poskytne příkaz SQL, který nevědomky spustíte ve své databázi.
Podívejte se na následující příklad, který vytváří
SELECT
příkaz přidáním proměnné (txtUserId) do vybraného řetězce. Proměnná je načtena z uživatelského vstupu (getRequestString):
Příklad
txtUserId = getRequestString("UserId");
txtSQL = "SELECT *
FROM Users WHERE UserId = " + txtUserId;
Zbytek této kapitoly popisuje potenciální nebezpečí používání uživatelského vstupu v příkazech SQL.
SQL Injection založené na 1=1 je vždy pravda
Podívejte se znovu na výše uvedený příklad. Původním účelem kódu bylo vytvořit příkaz SQL pro výběr uživatele s daným ID uživatele.
Pokud uživateli nic nebrání v zadání „špatného“ vstupu, může uživatel zadat nějaký „chytrý“ vstup, jako je tento:
Uživatelské ID:
Potom bude příkaz SQL vypadat takto:
SELECT * FROM Users WHERE UserId = 105 OR 1=1;
Výše uvedené SQL je platné a vrátí VŠECHNY řádky z tabulky "Uživatelé", protože OR 1=1 je vždy PRAVDA.
Vypadá výše uvedený příklad nebezpečně? Co když tabulka "Uživatelé" obsahuje jména a hesla?
Výše uvedený příkaz SQL je téměř stejný jako tento:
SELECT UserId, Name, Password
FROM Users WHERE UserId = 105 or 1=1;
Hacker může získat přístup ke všem uživatelským jménům a heslům v databázi jednoduchým vložením 105 NEBO 1=1 do vstupního pole.
SQL Injection založené na ""="" je vždy pravda
Zde je příklad přihlášení uživatele na webové stránce:
uživatelské jméno:
Heslo:
Příklad
uName = getRequestString("username");
uPass = getRequestString("userpassword");
sql = 'SELECT * FROM Users WHERE Name ="' + uName + '" AND Pass ="' + uPass +
'"'
Výsledek
SELECT * FROM Users WHERE Name ="John Doe" AND Pass ="myPass"
Hacker může získat přístup k uživatelským jménům a heslům v databázi jednoduchým vložením "NEBO ""=" do textového pole uživatelského jména nebo hesla:
Uživatelské jméno:
Heslo:
Kód na serveru vytvoří platný příkaz SQL, jako je tento:
Výsledek
SELECT * FROM Users WHERE Name ="" or ""="" AND Pass ="" or ""=""
Výše uvedené SQL je platné a vrátí všechny řádky z tabulky "Users", protože NEBO ""="" je vždy PRAVDA.
SQL Injection na základě dávkových příkazů SQL
Většina databází podporuje dávkové příkazy SQL.
Dávka příkazů SQL je skupina dvou nebo více příkazů SQL oddělených středníky.
Příkaz SQL níže vrátí všechny řádky z tabulky "Uživatelé" a poté smaže tabulku "Dodavatelé".
Příklad
SELECT * FROM Users; DROP TABLE Suppliers
Podívejte se na následující příklad:
Příklad
txtUserId = getRequestString("UserId");
txtSQL = "SELECT *
FROM Users WHERE UserId = " + txtUserId;
A následující vstup:
Uživatelské ID:
Platný příkaz SQL by vypadal takto:
Výsledek
SELECT * FROM Users WHERE
UserId = 105; DROP TABLE Suppliers;
Použijte parametry SQL pro ochranu
Chcete-li chránit web před vložením SQL, můžete použít parametry SQL.
Parametry SQL jsou hodnoty, které se přidávají do dotazu SQL v době provádění řízeným způsobem.
Příklad ASP.NET Razor
txtUserId = getRequestString("UserId");
txtSQL = "SELECT *
FROM Users WHERE UserId = @0";
db.Execute(txtSQL,txtUserId);
Všimněte si, že parametry jsou v příkazu SQL reprezentovány značkou @.
Modul SQL kontroluje každý parametr, aby se ujistil, že je pro daný sloupec správný a že se s ním zachází doslovně, a nikoli jako součást SQL, který se má provést.
Další příklad
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);
Příklady
Následující příklady ukazují, jak vytvořit parametrizované dotazy v některých běžných webových jazycích.
VYBERTE VÝKAZ V ASP.NET:
txtUserId = getRequestString("UserId");
sql = "SELECT * FROM Customers WHERE CustomerId = @0";
command = new SqlCommand(sql);
command.Parameters.AddWithValue("@0",txtUserId);
command.ExecuteReader();
INSERT IN TO STATEMENT V 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();
VLOŽTE DO VÝKAZU V 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();