it-swarm-eu.dev

SQL injection - proč už není únikové uvozovky bezpečné?

Raw SQL

Když píšete SQL - pro cokoli, co opravdu vyžaduje lidské vstupy, bylo vykonáno mnoho věcí, aby se zabránilo injekci.

Každý, kdo slyší o vstřikování SQL, to ví (já použiji jako ukázku PHP), dělat něco takového není bezpečné:

$sql = "SELECT * FROM `users` 
.  WHERE `userName` = "{$_POST["username"]}" 
.  AND `pass` = "{$_POST["pass"]}";";

Magie

Potom samozřejmě někdo přišel s myšlenkou použití "magických únikových nabídek" k řešení vstupů programu, které nebyly dezinfikovány správně a přímo vloženy do sql v důsledku špatných praktik. Ve skutečnosti to problém s injekcí SQL opravdu nevyřešilo, ale znamenalo to, že veškerý vstup uživatele byl zmatený.

Přidání lomítek

Někteří lidé tedy vypínali magické citace. Poté analyzovali vstup uživatele před bodem SQL prostřednictvím funkce addslashes(), která teoreticky unikne všem uvozovkám a váš hacker nemůže udělat ' OR 1=1, Ale i dokumentace pro addslashes je samozřejmé, že neměli byste používat addslashes, říká se, že používají funkci specifickou pro databázi, jako je mysql_real_escape_string(), ale někteří to stále tvrdí, že to nestačí.

Přidání lomítek specifických pro databázi

Nemůžeme tedy použít DBMS specifický *_real_escape_string, Nemůžeme použít add slashes, Věc „magických nabídek“ způsobila mnoho problémů a web je plný krátkých textových nabídek, jako je :

„Vyhrazený hacker najde způsob, jak přeskočit své smyčky unikající citace, stačí použít DBAL připravená prohlášení“ - John Q libovolný programátor

Dobře, takže mě to dost vyděsilo, abych použil přípravné výkazy a DBAL. Nic to nevysvětlilo, ale zní to dobře, protože jsem to hodně slyšel.

Připravená prohlášení

Takže nyní používáme PDO nebo DBAL z rámce, nebo něco jiného, ​​co zabalí všechny naše sql a zajistí, že někdo nemůže spustit injekci sql.

Moje otázka je v zásadě „proč ne?“, Ne „co mám použít?“. Na webu je mnoho lidí, kteří vám říkají, abyste to používali nebo používali cokoli cokoli , ale žádné vysvětlení, proč se tyto věci musely stát.

Přímé otázky

Špičaté otázky (připomenutí, ptám se na SQL, PHP byl příkladem jazyka kvůli špatnému opakování kolem SQL, pojmy jsou univerzální):

  1. Proč nemůžeme uniknout veškerým vstupům uživatelů pomocí „magie“?
  2. Proč nebyly lomítka „dost dobrá“?
  3. Co je špatného na použití únikových funkcí specifických pro DB a proč to bylo lepší než addslashes?
  4. Proč jsou připravená prohlášení s kostry a CHOP označována za zlatý standard SQL? Proč jsou lepší? Proč s nimi nemůžu provést SQL injekci, kde, jak jsem mohl s výše uvedenými prostředky? Dokáže programátor nějak podaří to pořád ještě zkomplikovat? Co by měli hledat?
  5. Nějaké další obavy, které jsem nevychovával?
78
Incognito

Proč nemůžeme uniknout veškerým vstupům uživatelů pomocí „magie“?

V době použití magie není známo, kde data skončí. Magické citáty tedy ničí data, pokud nejsou zapsána do databáze bez záznamu.

Může být použito pouze v odpovědi HTML odeslané zpět klientovi. Přemýšlejte o formuláři, který není plně vyplněn a je proto uživateli znovu zobrazen. U magických uvozovek budou data zadaná při prvním pokusu nyní vynechána SQL, což na stránce HTML nemá význam. Ještě horší: při druhém podání jsou data znovu SQL.

Proč nebyly lomítka „dost dobrá“?

Má problémy s vícebytovými znaky:

' 27
\ 5c
뼧 bf 5c

Jedná se o dva bajty, ale pouze jeden znak Unicode.

Protože addslashes neví nic o Unicode, převede vstup bf 27 to bf 5c 27. Pokud je přečtena programem podporujícím Unicode, je považována za 뼧 '. Výložník.

Dobré vysvětlení tohoto problému naleznete na http://shiflett.org/blog/2006/jan/addslashes-versus-mysql-real-escape-string

Co je špatného na použití únikových funkcí specifických pro DB a proč to bylo lepší než addslashes?

Jsou lepší, protože zajišťují, aby unikající interpretoval data stejným způsobem jako databáze (viz poslední otázka).

Z bezpečnostního hlediska jsou v pořádku, pokud je používáte pro každý jednotlivý vstup do databáze. Mají však riziko, že na některou z nich někde zapomenete.

Úpravy : Jak bylo přidáno getahobby: Nebo že pro čísla použijete xxx_escape_strings bez přidání uvozovek kolem nich v příkazu SQL a bez zajištění, že se jedná o skutečná čísla podle přetypování nebo převedení vstupu na příslušný datový typ /Upravit

Z pohledu vývoje softwaru jsou špatné, protože ztěžují přidávání podpory pro další software databázového serveru SQL.

Proč jsou připravená prohlášení s kostry a CHOP označována za zlatý standard SQL? Proč jsou lepší?

PDO je většinou dobré z důvodů návrhu softwaru. Usnadňuje podporu dalšího softwaru databázového serveru. Má objektově orientované rozhraní, které abstraktuje mnoho malých databázových specifických nekompatibilit.

Proč nemohu udělat SQL injekci s těmito [připravenými tvrzeními], kde, jak jsem mohl s výše uvedenými prostředky?

Důležitá je část „ konstantní dotaz s proměnnými parametry “ připravených příkazů. Ovladač databáze automaticky unikne všem parametrům, aniž by o tom musel vývojář přemýšlet.

Parametrizované dotazy jsou často snadněji čitelné než běžné dotazy s uniklými parametry ze syntaktických důvodů. V závislosti na prostředí mohou být o něco rychlejší.

Vždy používat připravené příkazy s parametry je něco, co lze ověřit pomocí nástrojů pro analýzu statického kódu . Chybějící volání na xxx_escape_string není tak snadno a spolehlivě spatřeno.

Dokáže to programátor nějak nějak vyřešit? Co by měli hledat?

"Připravené příkazy" znamenají, že jsou konstanta . Dynamicky generované připravené příkazy - zejména se vstupem uživatele - mají stále všechny problémy s injekcí.

52

[1.] Proč nemůžeme uniknout veškerým vstupům uživatelů pomocí „magie“?

Protože magické citace jsou rozděleny na dva počty:

  1. Ne všechna data $ _ (REQUEST/GET/POST) jde do DB. A abyste to pochopili, musíte uniknout vstupu.
  2. Jsou ekvivalentem addslashes (viz moje poznámka k [2.]), takže ve skutečnosti nejsou bezpečné.

[2.] Proč nebyly lomítka „dost dobrá“?

Existuje mnoho způsobů, jak se z omezení addslashes dostat, proto je to zásadně vadné, pokuste se ho však použít.

[3.] Co je špatného na použití únikových funkcí specifických pro DB a proč to bylo lepší než addslashes?

Fakt nic. To je prostě mantra o tom, proč jsou CHOP/připravené „lepší“. Jsou způsobem lepší než addslashes, protože se starají o mnoho faktorů, včetně kódování. Tady je trochu tajemství; PDO je používá interně, ale ne addslashes...

[4.] Proč jsou připravovaná prohlášení s kostry a CHOP označována za zlatý standard SQL? Proč jsou lepší? Proč s nimi nemůžu provést SQL injekci, kde, jak jsem mohl s výše uvedenými prostředky?

Nejsou zlatým standardem , nejsou „bezpečnější“ než funkce specifické pro DB a vy může s nimi také provádět SQL injekci . A ne, nemůžete udělat SQL injekci se správně dezinfikovaným vstupem.

Jako u všech technologií tam, vývojáři mají tendenci rozvíjet náboženské (fanatické?) Tendence k čemukoli „novému“. To je důvod, proč jste ostřílený Zend Certified Engineers (TM) radí -no- nutí vás přejít na připravená prohlášení.

Realita je však taková, že vše záleží na tom, co víte. Pokud načítáte článek podle jeho číselného ID, nepotřebujete žádný únik, ještě méně CHOP. Musíte jednoduše zajistit, aby ID bylo skutečně celé číslo.

Z realističtějšího hlediska není obecným pravidlem použití PDO/připravených příkazů, ale použití správných funkcí, to znamená, že musíte použít mysql_real_escape_string() místo addslashes() nebo mysql_escape_string().

[5.] Může se programátorovi nějak nějak podařit, aby to ještě zkomplikoval? Co by měli hledat?

Samozřejmě! Ale nejde o „co dávat pozor“, ale spíše „vědět, co děláte“.

Uvidíte, že eval($_GET['code']) * je zcela legitimní, pokud je použit na správném místě (jako je místní PHP Testovací běžec).

Pokud používáte ORM ke spuštění podmíněného dotazu, zadáváte kód přímo, proto může existovat šance na získání SQL injekce, pokud to neuděláte správně (záleží na dotyčném ORM). (Hypotetický) Příklad:

// update() sets the value of a column given a condition
//
//                         .--escaping is automatic here
//                         |                           .--hypothetical SQL injection
//                         v                           v
Db()->update('name',$_GET['newname'])->where(' id = '.$_GET['id']);

(* Dokážu si představit jen nespočet profesionálů , kteří na to bijí hlavou)

13
Christian

Na konci dne musí být provedeno únikové vstupy, aby byly vaše dotazy chráněny formou SQL Injection. Knihovny parametrizovaných dotazů, jako je PDO a ADODB , používají escape , vše, co dělají, je vynucení této praxe způsobem, který je implicitně bezpečný. Constrast magic_quotes_gpc dělá [~ # ~] ne [~ # ~] , je to zásadně chybný přístup k problému.

1) Útěk může být problematický, pokud nerozumíte tomu, co děláte. Tento typ problému je stále využitelný, pokud je povolen magic_quotes_gpc.

mysql_query("select * from users where id=".addslashes($_GET[id]));

Využití PoC: http: //localhost/vuln.php? Id = sleep ( )

oprava:

mysql_query("select * from users where id='".addslashes($_GET[id])."'");

Lekce: Pro využití injekce sql nepotřebujete úvodzovky.

2) Řekněme, že uniknete pouze uvozovkám:

mysql_query("select * from users where name='".htmlspecialchars($_GET[name],ENT_QUOTES)."' and id='".htmlspecialchars($_GET[id],ENT_QUOTES)."'");

Využití PoC: http: //localhost/vuln.php? Name = \& id = + nebo + spánek (30)/*

Oprava:

mysql_query("select * from users where name='".addslashes($_GET[name])."' and id='".addslashes($_GET[id])."'");

Lekce : Zpětná lomítka jsou stejně nebezpečná jako uvozovky.

3) A co kódování jazyka?

mysql_query("SET CHARACTER SET 'gbk'");
mysql_query("select * from user where name='".addslashes($_GET[name])."'");

Využití PoC: http: //localhost/vuln.php? Name =% bf% 27 = spánek (30)/*

Oprava:

mysql_query("SET CHARACTER SET 'gbk'");
mysql_query("select * from user where name='".mysql_real_escape_string($_GET[name])."'");

Závěr:

Únik je nezbytně nutný, aby se zabránilo aplikaci injekce sql v aplikaci. V PHP PDO a ADOB jsou skvělé parametrizované knihovny dotazů, které vynucují unikání uživatelských vstupů. Problém je v tom, že mnoho programátorů nechápe, co je to útěk. nejlepší metoda obrany, protože nemusíte rozumět únikovým pravidlům.

9
rook

O funkcích escape specifických pro DB. Existuje mnoho scénářů, za kterých může dojít ke vstřikování SQL, přestože bylo použito mysql_real_escape_string (). LIMIT a OBJEDNÁVKA BY jsou opravdu ošidné!

Tyto příklady jsou zranitelné vůči SQL injection:

$offset = isset($_GET['o']) ? $_GET['o'] : 0;
$offset = mysql_real_escape_string($offset);
$sql = "SELECT userid, username FROM sql_injection_test LIMIT $offset, 10";

nebo

$order = isset($_GET['o']) ? $_GET['o'] : 'userid';
$order = mysql_real_escape_string($order);
$sql = "SELECT userid, username FROM sql_injection_test ORDER BY `$order`";

V obou případech nemůžete použít 'k ochraně zapouzdření.

zdroj : Neočekávaná SQL injekce (když Escaping nestačí) <- Přečtěte si

5
Cut Copy

Filtry lze obejít a data, která vstupují do příkazů SQL, mohou pocházet z více míst, než jen ze vstupu uživatele. Vstupní body do zdroje/dřezu ovlivňovaného SQL lze jako jeden příklad uložit (vyšší řád), ale jednoznačně parametry HTTP GET a POST parametry z formulářů HTML) nejsou jedinými způsoby uživatele vstup.

Parametrizované dotazy nutně nezbavují vaše příkazy SQL bez injekcí. Vyžadují také variabilní vázání, odstraňování řetězcových operací/zřetězení a vyhýbání se určitým problémům s bezpečností s velkým množstvím klauzulí SQL.

Většina vývojářů také zapomíná kontrolovat své součásti třetích stran a jiné závislosti na problémech s SQL injekcí a někdy si neuvědomuje, že tyto inkluze mohou způsobit zranitelnost jejich vlastního kódu.

Nejlepší věc, kterou musíte udělat, je najmout poradenskou společnost zabývající se bezpečností aplikací, která připraví vaši aplikaci (aplikace) na připravenost výroby a zaškolí váš tým (y) appdev na vytváření bezpečnostních kontrol aplikací do jejich procesů a vývojových technologií.

4
atdre

Rozšiřovat Hendrickovu odpověď. Je snadné si představit real_escape_string jako kouzelnou kulku, když ve skutečnosti není. Viděl jsem, jak lidé tuto funkci používají, když chtějí místo toho použít intval nebo vrhnout vstup na celé číslo. Pokud použijete řetězec escape v nesprávném kontextu, můžete si jej i nadále aplikovat.

3
getahobby