prevence injekcí SQL v PHP (a dalších zranitelnostech)

pokud jste už nějakou dobu kolem vývoje webu, téměř jistě jste slyšeli termín „SQL injection“ a některé děsivé příběhy o tom.

PHP, stejně jako mnoho jiných jazyků, není imunní vůči tomuto typu hrozby, což může být skutečně velmi nebezpečné. Naštěstí je však ochrana vašich webových stránek před injekcí SQL a dalšími podobnými hrozbami něco, k čemu můžete podniknout hmatatelné kroky.

v tomto příspěvku se dozvíte, co je SQL injection, jaké jsou důsledky úspěšného útoku, jak může útočník využít zranitelného kódu PHP, co můžete udělat, abyste tomu zabránili, a jaké nástroje můžete použít k detekci částí kódu, které by mohly být vystaveny tomuto druhu hrozby. Kromě toho se dozvíte o několika dalších běžných zranitelnostech, o kterých byste měli vědět, abyste mohli vytvářet bezpečnější aplikace.

jak funguje SQL injection?

první věc, kterou potřebujete vědět, abyste ochránili svůj kód před SQL injection, je pochopit, jak by mohl být útočníkem zneužit.

myšlenka zneužití je poměrně jednoduchá: útočník spustí škodlivý kód SQL ve vaší databázi prostřednictvím vaší aplikace.

jak by toho mohl někdo dosáhnout? Zneužitím vstupů vaší aplikace.

podívejme se na jednoduchý příklad. Předpokládejme, že máte aplikaci zobrazující seznam uživatelských jmen, kde každý uživatel má odkaz na své údaje, jako je tento:

a pak v souboru user_details.php máte toto:

<?php $sql = "SELECT * FROM user WHERE id = ".$_GET;

pokud uživatel jedná podle očekávání a klikne na jméno uživatele, adresa URL požadavku bude vypadat takto: http://domain.com/user_details.php?id=8.

takže, co je na tom špatného?

hodnota $sql bude řetězec "SELECT * FROM user WHERE id = 8" a dotaz bude spuštěn v pohodě.

problém je v kurzívou této věty: pokud uživatel jedná podle očekávání a klikne na jméno uživatele, adresa URL požadavku bude vypadat takto:

http://domain.com/user_details.php?id=8.

co když uživatel nejedná podle očekávání?

co kdyby někdo vyrobil adresu URL a poslal jako ID něco jiného než číslo?

vyrobené adresy URL

pokud by Adresa URL byla něco jako http://domain.com/user_details.php?id=Peanuts, výsledný řetězec SQL by byl: "SELECT * FROM user WHERE id = Peanuts".

v tomto případě by problém byl pro uživatele. Dotaz by jednoduše selhal a v nejhorším případě by uživatel viděl nějakou podivnou zprávu.

ale co když URL vypadalo spíše takto:

http://domain.com/user_details.php?id=1+OR+1%3B? (Toto je výsledek urlencode('1 OR 1;'), mimochodem.)

v tomto případě by výsledný SQL byl "SELECT * FROM user WHERE id = 1 OR 1;". To znamená, že výsledkem dotazu by byl každý uživatel v databázi místo pouze uživatele, jehož ID se rovná 1. AU.

ale to stále není tak špatné, že?

nyní zkusme extrémnější příklad.

předpokládejme, že URL bylo něco jako

http://domain.com/user_details.php?id=1%27%3B+DROP+TABLE+users%3B--+, což se promítá do id=1; DROP TABLE users;--, což účinně vytváří tento příkaz SQL:

"SELECT * FROM users WHERE id = 1; DROP TABLE users;-- ". A pokud spustíte tento dotaz … velký AU.

v případě, že nejste 100% obeznámeni se syntaxí SQL, DROP TABLE by tabulku úplně smazal. Bylo by to, jako by nikdy neexistovalo.

nedávná záloha by samozřejmě pomohla snížit poškození,ale přesto. Tohle je špatné.

pokud se chcete dozvědět více o tomto druhu útoku, je zde skvělý příspěvek.

ale myslím, že to je dost špatných zpráv. Pojďme na veselejší místo: jak můžete zabránit těmto typům injekcí SQL ve vašich aplikacích PHP.

jak zabránit SQL injekcím v PHP

jak jste viděli, problém je, když útočník má schopnost spouštět SQL kód, aniž byste si toho byli vědomi.

tato situace se projevuje jako důsledek vytváření dotazů za běhu pomocí zřetězení řetězců a zahrnutí dat získaných z externích vstupů (obvykle vstup uživatele, ale také další externí zdroje, jako jsou soubory, odpovědi na volání API atd.).

abyste zabránili této chybě zabezpečení ve vašem kódu, musíte opravit zdroje potenciálních problémů.

ověřte své vstupy

jednoduchým způsobem, jak opravit chybu zabezpečení ve výše uvedeném příkladu, by bylo zkontrolovat, zda je parametr ID tím, co se od něj skutečně očekává (tj., kladné celé číslo):

dalším způsobem, jak provést tento druh ověření, je využít vestavěné filtry PHP:

<?php
$id = filter_input( INPUT_GET, 'id', FILTER_VALIDATE_INT);

tím, že ověřujete své vstupy, zabráníte útočníkům v provádění škodlivého kódu vedle vašeho vlastního.

neexistuje snadný způsob, jak jim zabránit v pokusu, ale pokud jejich pokusy nejsou úspěšné,je dobré jít.

použijte připravené příkazy

dalším způsobem, jak můžete chránit svůj kód před injekcemi SQL, je použití připravených příkazů. Připravené příkazy jsou předkompilované příkazy SQL.

mohou být použity s konkrétní knihovnou pro přístup k databázi (například mysqli) nebo s obecnější knihovnou chop.

pojďme se podívat na příklad pomocí mysqli:

pokud zkusíte tento kód (samozřejmě nahrazujete přihlašovací údaje databáze), uvidíte, že pokud budete přistupovat prostřednictvím legální adresy URL, jako je http://domain.com/user_details.php?id=1, získáte stejný výsledek jako kterákoli z výše uvedených škodlivých adres URL (což jsou informace o uživateli přidruženém k ID 1 a nic jiného).

pokud dáváte přednost použití chop, kód bude vypadat spíše takto:

není to opravdu velký rozdíl, že?

stručně řečeno, připravená prohlášení nabízejí skvělý způsob, jak zabránit injekcím SQL. Také obvykle fungují lépe než on-the-fly SQL.

Nyní, když znáte nástroj, stačí jej použít.

jak zjistit PHP kód, který je zranitelný vůči SQL injekcím

jakmile je chyba zabezpečení nalezena, oprava není opravdu komplikovaná. Jak ale najdete tyto typy zranitelností ve vašem kódu?

pokud máte štěstí a vaše kódová základna je dostatečně malá, provede se jednoduchá revize kódu.

ale pokud je vaše aplikace středně velká až velká, budete potřebovat další pomoc.

jedním z velmi populárních (a open-source) nástrojů, které můžete použít pro tento účel, je sqlmap, jednoduchý Python skript, který se pokusí zaútočit na jakoukoli adresu URL, kterou do ní vložíte, a podat zprávu o svých zjištěních.

zde je ukázkový výstup z běhu proti mé webové stránce založené na PHP:

dalším nástrojem s otevřeným zdrojovým kódem, který můžete použít, je Arachni, sofistikovanější nástroj, který obsahuje webové GUI a byl napsán v Ruby.

zde je ukázkový výstup z běhu přes CLI:

kromě kontroly a testování kódu byste měli zvážit použití řešení RASP, jako je Sqreen, ke sledování výrobních prostředí, abyste zastavili provádění všech exploitů, které se dostanou do fáze kontroly a testování.

jaké další chyby zabezpečení byste měli vědět?

kód injekce

SQL injekce je jen jeden člen větší rodiny zranitelností: kód injekce.

myšlenka různých technik vstřikování kódu je vždy stejná. Je to všechno o podvádění nevinné aplikace do spuštění škodlivého kódu.

to lze provést několika způsoby.

v PHP existují funkce navržené tak, aby jednoduše vydávaly příkazy přímo do operačního systému, například funkce exec.

zde je jednoduchý příklad toho, jak by to mohlo být využito:

<?php
exec( 'cp uploads/'.$_GET.' /secure/');

pokud by někdo požádal http://domain.com/exec.php?file=a.txt%3B+rm+-Rf+%2A+%23, výsledkem by bylo provedení tohoto příkazu:

cp uploads/a.txt; rm -Rf * # /secure/

a to by mohlo zničit celý disk na serveru-nevalidovaný vstup udeří znovu!

Cross-site scripting

další velmi častou zranitelností je cross-site scripting (XSS). V tomto případě je obětí uživatel navštěvující váš web.

XSS je, když útočník vloží škodlivý kód JavaScript do běžného formuláře HTML, který bude později vykreslen prohlížečem jiného uživatele.

podívejte se na tento PHP skript:

<?php
echo "<html><p>Hello {$_GET}!</p></html>";

je zřejmé, že záměrem je vytvořit jednoduchou stránku, která pozdraví uživatele.

ale když se k tomu dostanou baddies, co jim brání požadovat

http://domain.com/greet.php?name=Mauro%3Cscript+language%3D%22javascript%22%3Ealert%28%22You+are+hacked%21%22%29%3B%3C%2Fscript%3E? Tento požadavek bude produkovat následující HTML jako výstup:

<html><p>Hello Mauro<script language="javascript">alert("You are hacked!");</script></p></html>

to je zjevně velmi naivní zneužití – koneckonců, jaká je škoda, když někomu ukážete jednoduché „jste hacknuti!“zpráva? Ale věci mohou být docela vážné s trochou fantazie. Mějte na paměti, že každý požadavek na server obsahuje soubor cookie relace, takže tato chyba zabezpečení může být viníkem únosu relací vašich uživatelů.

pak znovu, zatímco problémy vypadají ošklivě, opravy jsou opravdu jednoduché: je to všechno o validaci a dezinfekci.

v případě XSS se provede jednoduché volání na htmlentities před vytvořením skutečného výstupu.

Oprava vs. detekce bezpečnostních chyb

jak jste viděli v tomto příspěvku, Oprava bezpečnostních chyb-injekce SQL i jiné typy-není hlavní výzvou. Uvědomit si, že váš kód je zranitelný a kde jej lze využít, je. Máte zde několik možností:

  • mají velmi silnou kódovací disciplínu
  • Otestujte své aplikace důkladně kvůli bezpečnostním problémům
  • využijte nástroje pro monitorování a ochranu, abyste zabránili zneužití a dostali upozornění včas

který z nich si vyberete, je na vás. Důležité je věnovat pozornost těmto problémům a jednat podle těchto znalostí. Zůstaň v bezpečí.

Leave a Reply

Vaše e-mailová adresa nebude zveřejněna.