it-swarm-eu.dev

Zabrání uložené procedury SQL injekci?

Je pravda, že uložené procedury zabraňují SQL injekčním útokům proti PostgreSQL databázím? Udělal jsem malý průzkum a zjistil jsem, že SQL Server, Oracle a MySQL nejsou bezpečné proti vstřikování SQL, i když používáme pouze uložené procedury. Tento problém však v PostgreSQL neexistuje.

Zabraňuje implementace uložené procedury v jádru PostgreSQL útokům SQL injekcí nebo je to něco jiného? Nebo je PostgreSQL také náchylný k SQL injekci, i když používáme pouze uložené procedury? Pokud ano, uveďte mi příklad (např. Kniha, web, papír atd.).

84
Am1rr3zA

Ne, uložené procedury nezabrání vstřikování SQL. Zde je skutečný příklad (z interní aplikace, kterou někdo vytvořil, kde pracuji) uložené procedury, která bohužel umožňuje vstřikování SQL:

Tento kód serveru SQL:

CREATE PROCEDURE [dbo].[sp_colunmName2]   
    @columnName as nvarchar(30),
    @type as nvarchar(30), 
    @searchText as nvarchar(30)           
AS
BEGIN
    DECLARE @SQLStatement NVARCHAR(4000)
    BEGIN
        SELECT @SQLStatement = 'select * from Stations where ' 
            + @columnName + ' ' + @type + ' ' + '''' + @searchText + '''' 
        EXEC(@SQLStatement)
    END      
END
GO

zhruba ekvivalentní postgresu:

CREATE or replace FUNCTION public.sp_colunmName2 (
    columnName  varchar(30),
    type varchar(30), 
    searchText  varchar(30) ) RETURNS SETOF stations LANGUAGE plpgsql            
AS
$$
DECLARE SQLStatement VARCHAR(4000);
BEGIN
    SQLStatement = 'select * from Stations where ' 
            || columnName || ' ' || type || ' ' || ''''|| searchText || '''';
    RETURN QUERY EXECUTE  SQLStatement;
END
$$;

Cílem vývojáře bylo vytvořit univerzální vyhledávací proceduru, ale výsledkem je, že klauzule WHERE může obsahovat cokoli, co uživatel chce, což umožňuje návštěvu z malé Bobby tabulky .

Nezáleží na tom, zda používáte příkazy SQL nebo uloženou proceduru. Záleží na tom, zda váš SQL používá parametry nebo zřetězené řetězce. Parametry zabraňují vstřikování SQL; zřetězené řetězce umožňují vstřikování SQL.

71
Kyralessa

Útoky SQL-Injection jsou útoky, kde nedůvěryhodný vstup je přímo připojen k dotazům, což uživateli umožňuje efektivně vykonávat libovolný kód, jak je znázorněno v tento kanonický komiks XKCD.

Takto získáme situaci:

 userInput = getFromHTML # "Robert ') Drop table students; -" 
 
 Query = "Vyberte * od studentů, kde studentName =" + userInput 

Uložené procedury jsou obecně dobré obrany proti SQL injekčním útokům , protože vstupní parametry nejsou nikdy analyzovány.

Ve uložené proceduře ve většině databází (a programů nezapomeňte, že předkompilované dotazy se počítají jako uložené procedury) vypadají takto:

 
 
 vytvoří Stored procdure foo (
 vyberte * ze studentů, kde studentName =: 1 
); 
 

Poté, když si program přeje přístup, zavolá foo(userInput) a výsledek šťastně načte.

Uložená procedura není kouzelnou obranou proti SQL-Injection, protože lidé jsou docela schopni psát špatné uložené procedury. Předkompilované dotazy, ať už jsou uloženy v databázi nebo v programu, je však mnohem obtížnější otevřít bezpečnostní díry v , pokud chápete, jak funguje SQL-Injection.

Můžete si přečíst více o SQL-Injection:

46

Ano, do určité míry.
Samotné uložené procedury nezabrání vstřikování SQL.

Dovolte mi nejprve citovat o SQL Injection od OWASP

Útok s injekcí SQL sestává z vložení nebo „injekce“ dotazu SQL prostřednictvím vstupních dat z klienta do aplikace. Úspěšné využití injekce SQL může číst citlivá data z databáze, upravovat data databáze (Vložit/Aktualizovat/Odstranit), provést administrační operace v databázi (jako je vypnutí DBMS), obnovit obsah daného souboru přítomného v souboru DBMS systému a v některých případech vydávají příkazy operačnímu systému. Útoky SQL injekcí jsou typ útoku injekce, ve kterém jsou příkazy SQL injektovány do vstupu datové roviny, aby se provedlo provádění předdefinovaných příkazů SQL.

Musíte dezinfikovat uživatelské vstupy a nespojovat příkazy SQL, i když používáte uloženou proceduru.

Jeff Attwood vysvětlil důsledky zřetězení sql v " Dejte mi parametrizovaný SQL, nebo mi dejte smrt "

Následuje zajímavá karikatura, která mi přijde na mysl, kdykoli uslyším SQL Injection alt text Myslím, že jsi pochopil :-)

Podívejte se na SQL Injection Prevention Cheat Sheet , metody prevence jsou úhledně vysvětleny ...

29
CoderHawk

Zřetězení řetězce je příčinou injekce SQL. Tomu se lze vyhnout pomocí parametrizace.

Uložené procedury přidávají další vrstvu zabezpečení vynucením neplatné syntaxe, když zřetězíte, ale nejsou „bezpečnější“, pokud v nich používáte, řekněme, dynamický SQL.

Takže váš výše uvedený kód je způsoben zřetězením těchto řetězců

  • exec sp_GetUser '
  • x' AND 1=(SELECT COUNT(*) FROM Client); --
  • ' , '
  • monkey
  • '

To dává neplatnou syntaxi, naštěstí

Parametrizování , které by to dalo

exec sp_GetUser 'x'' AND 1=(SELECT COUNT(*) FROM Client); --' , 'monkey'

To znamená

  • @UserName = x' AND 1=(SELECT COUNT(*) FROM Client); --
  • @Password = monkey

Nyní ve výše uvedeném kódu nezískáte žádné řádky, protože předpokládám, že nemáte žádného uživatele x' AND 1=(SELECT COUNT(*) FROM Client); --

Pokud uložené proc vypadalo takto (pomocí zřetězené dynamické SQL ), pak vaše parametrizované uložené proc volání stále umožní SQL Injection

...
SET @sql = 'SELECT userName from users where userName = ''' + 
               @UserName + 
               ''' and userPass = ''' +
               @Password +
               ''''
EXEC (@sql)
....

Jak je tedy ukázáno, zřetězení řetězců je hlavním nepřítelem pro SQL injekci

Uložené procedury přidávají zapouzdření, zpracování transakcí, snížená oprávnění atd., Ale mohou být stále zneužívány pro SQL injekci.

Další informace o parametrizaci naleznete na Stack Overflow

12
gbn

„K útokům SQL vstřikování dochází, když vstup uživatele je nesprávně kódováno. Vstupem uživatele jsou obvykle některá data, která uživatel pošle se svým dotazem, tj. Hodnoty v $_GET, $_POST, $_COOKIE, $_REQUEST nebo $_SERVER pole. Vstup uživatele však může také pocházet z mnoha jiných zdrojů, jako jsou sokety, vzdálené webové stránky, soubory atd. Proto byste tedy měli opravdu zacházet se vším kromě konstant (jako 'foobar') jako uživatelský vstup . "

Nedávno jsem důkladně zkoumal toto téma a chtěl bych se s ostatními podělit o docela zajímavý materiál, takže tento příspěvek je pro všechny kompletní a poučný.



z YouTube


Z Wikipedie


od OWASP


Od PHP Manual


od společnosti Microsoft a Oracle


Přetečení zásobníku


SQL injekční skener

10
Ilia Rostovtsev

Uložené procedury magicky nezabrání vstřikování SQL, ale dělají z něj mnohem snazší zabránění. Vše, co musíte udělat, je něco jako následující (příklad Postgres):

CREATE OR REPLACE FUNCTION my_func (
  IN in_user_id INT 
)
[snip]
  SELECT user_id, name, address FROM my_table WHERE user_id = in_user_id; --BAM! SQL INJECTION IMMUNE!!
[snip]

A je to! Problém nastává pouze při vytváření dotazu prostřednictvím zřetězení řetězce (tj. Dynamického SQL), a dokonce i v těch případech se budete moci vázat! (Závisí na databázi.)

Jak se vyhnout vstřikování SQL v dynamickém dotazu:

Krok 1) Zeptejte se sami sebe, zda skutečně potřebujete dynamický dotaz. Pokud strkáte struny dohromady, abyste nastavili vstup, pravděpodobně to uděláte špatně. (Existují výjimky z tohoto pravidla - jedna výjimka se týká hlášení dotazů v některých databázích, může dojít k problémům s výkonem, pokud jej nebudete nutit sestavit nový dotaz s každým spuštěním. Tento problém však prozkoumejte dříve, než do něj přejdete. )

Krok 2) Vyhledejte správný způsob, jak nastavit proměnnou pro konkrétní RDBMS. Oracle například umožňuje provádět následující akce (citovat z jejich dokumentů):

sql_stmt := 'UPDATE employees SET salary = salary + :1 WHERE ' 
           || v_column || ' = :2';
EXECUTE IMMEDIATE sql_stmt USING amount, column_value; --INJECTION IMMUNE!!

Zde stále ještě nespojuje vstup. Jste bezpečně vázáni! Hurá!

Pokud vaše databáze nepodporuje něco jako výše (doufejme, že žádný z nich není stále tak špatný, ale nebyl bych překvapen) - nebo pokud stále musíte zřetězit svůj vstup (jako v případě „někdy“ hlášení dotazů jako Naznačil jsem výše), pak musíte použít správnou funkci útěku. Nepište to sami. Například postgres poskytuje funkci quote_literal (). Takže byste běželi:

sql_stmt := 'SELECT salary FROM employees WHERE name = ' || quote_literal(in_name);

Tímto způsobem, pokud je jméno in_name něco jako '[snip] nebo 1 = 1' (část „nebo 1 = 1“ znamená vybrat všechny řádky, což uživateli umožní vidět platy, které by neměl!), Pak quote_literal uloží zadek výsledný řetězec:

SELECT salary FROM employees WHERE name = '[snip] or 1=1'

Žádné výsledky nebudou nalezeny (pokud nemáte nějaké zaměstnance se skutečně podivnými jmény.)

To je podstata! Nyní mi dovolte, abych vás nechal s odkazem na klasický příspěvek od guru Oracle Toma Kyteho na téma SQL Injection, abych získal místo domů: Linky

2
MWDB