Zdravím,
je to nějakou dobu co sem tady postl něco užitečného..poslední dobou sem se zabýval penetrací na jednotlivé WoW servery, které nemají valnou ochranu. Podařilo se mi najít nespočet děr, na množství českých webů. A proto sem vyhledal a upravil návod z nejmenovaného bezpečnostního webu. A proto, pokud nechcete aby někdo díky díře na Vašem webu získal přístup i do DB(což je díky webu velice snadné) Přečtětesi článek níže.
SQL Injection je na Internetu hojně používaný pojem, najdete ho jak na různých stránkách rádoby hackerů, tak i na fórech programátorů. Pro hackery je to užitečná bezpečnostní díra a pro programátory noční můra. Pod tímto pojmem se skrývá podvržení vstupních dat z formulářů nebo jiných vstupů s cílem změnit výsledek SQL dotazu. Tato chyba se nachází na spoustě webových aplikací, a proto jsou ohroženy.
Co vám hrozí
Přinejlepším se útočník dostane tam, kam nemá, ale neprovede nic s vaší aplikací; v horším případě se dostane třeba k uživatelským heslům (spíše hashům hesel) a v nejhorším případě vám smaže tabulky nebo upraví jejich obsah.
Příklady a obrana
Teď si ukážeme několik příkladů, kde se dá aplikovat SQL injection, a povíme si něco o tom, jak tyto trhliny zabezpečit.
Zobrazení článku podle jeho ID
Pro zobrazení článku pomocí ID nám může posloužit tento dotaz:
//nezabezpeceny nachylny dotaz
$dotaz = "select * from clanky where id = '$_GET["d"]'";
Tento kód načítá vše z tabulky clanky kde id = proměnné id z adresy. Jak vidíte, tento vstup není nijak chráněný, a tak útočník může zadat tento dotaz do adresy:
clanek.php?id=1 and 1=1/*
Pokud se nám zobrazí článek, útočník pozná, že je zde chyba, které může zneužít:
clanek.php?id=1and truncate table clanky/*
Tímto dotazem vám vyprázdní tabulku clanky, ale může vám ji také smazat, vložit do ní nové údaje, no prostě fantazii se meze nekladou – vás spíš bude zajímat, jak se proti takovému útoku bránit:
Pokud má být id číslo, tak použijeme funkci is_numeric():
$id = $_GET["id"];
//kontrola, zda je id cislo
if(!is_numeric($id)):
echo"Toto ne!";
else:
$dotaz = "select * from clanky where id='$id'";
endif;
Tímto jsme zabránili vložení jakéhokoliv SQL dotazu do adresy, protože se kontroluje, jestli je proměnná idčíslo nebo ne, pokud ne, vypíše se: Toto ne!, pokud ano, proběhne dotaz na databázi.
Pokud ale má být id typu string, že by se vybíralo třeba podle názvu článku, tak zabezpečíme takto:
//kontrola, zda je id string
if (!is_string($_GET["id"])):
echo "Toto ne!";
else:
//escapovani nebezpecnych znaku
$id = mysql_real_escape_string($_GET["id"]);
$dotaz = "select * from clanky where id = '$id'";
endif;
Tímto jsme zabezpečili i aplikaci, kde má být id typu string.
Toto byl jednoduchý příklad SQL Injekce a také jednoduchý příklad ochrany. Zásadou při psaní každé webové aplikace je kontrola a zabezpečení všech vstupních polí od uživatele, tzn. escapování všech znaků, na některých serverech to za nás dělá direktiva magic_quotes_gpc, ale ne vždy je dobré se na toto spoléhat. Kontrolujte, zda proměnné jsou stejného typu, jaký vy požadujete (ukázáno v předchozím příkladu). Všechny výstupy, které nechcete formátovat pomocí HTML, například komentáře nechte ošetřit pomocí funkce html_entities() nebo pomocí html_specialchars(), abyste zabránili také XSS (Cross-site-scripting).
Pokud také programujete aplikaci, kde se ukládají hesla do databáze, hashujte je, aby se útočník dostal jen k hashům, které tak rychle nerozluští a i kdyby ano, je velká chyba programátora, když ukládá hesla jako plain text.
Funkce, které by vám mohly pomoci při zabezpečování svých aplikací:
is_string()
is_numeric()
mysql_real_escape_string()
addslahes()
html_specialchars()
html_entities()
SQLi Scannery
Pokud si někdo vyhlídne konkrétně váš web, pak vám následující ochrana příliš nepomůže, vhodná je ovšem k odfiltrování SQL Injection scannerů "běhajících" po Internetu bez interakce jejich majitelů. Takovým scannerům je totiž obvykle předložen seznam náhodně sesbíraných domén, které mají otestovat a v případě jakéhokoli problému skočí na další doménu v pořadí, aniž by se řešením vzniklých potíží zdržovali (nebylo by to totiž příliš efektivní). Hromadný scanner pracuje s různými hodnotami v URL parametrech a přitom porovnává kontrolní součty stránek, které načetl. Vyjdou-li mu ovšem s každým požadavkem na server jiné součty, pak vyhodnotí stránku jako nestabilní, neboť je její obsah neustále měněn a pro její exploitaci je nutná interakce člověka. To je samozřejmě v případě masového scanování neefektivní a naše doména se jednoduše přeskočí. Jak tedy můžeme docílit toho, aby byla webová prezentace vyhodnocena jako nestabilní? Přidejte do stránky, např. patičky, nějaký dynamický element, který se bude neustále měnit a ten pomocí kaskádových stylů skryjte. Nedoporučuji ovšem k tomuto účelu používat funkci time(), která pravděpodobně napadne každého nejdříve. Sofistikovanější scannery totiž při porovnávání stránek (respektive jejich kontrolních součtů) mohou vynechávat jakékoliv číselné hodnoty na stránce, čímž odfiltrují hodiny, veškerá počítadla a samozřejmě i výstup funkce time(), tudíž Vaše snaha přijde prakticky vniveč. Namísto zmíněné funkce zkuste použít něco obdobného, jako uvádím níže:
<span style="display:none"><?php echo substr(base64_encode(md5(time())), 0, mt_rand(5, 10)); ?></span>
<?php nebo <?, toť otázka
Zas tak příliš složitá otázka to není, rozhodně nebuďte líní a k uvození PHP kódu použijte výraz <?php namísto <?, což vám ostatně poradí i každá seriozní kniha či tutoriál o PHP. Možná se ale ptáte, co to má společného s bezpečností. Celkem dost, jste-li totiž líní ve svých scriptech používat delší z uvozovacích tagů a útočník na kompromitovaném serveru deaktivuje direktivu short_open_tag v php.ini, pak se všemi vašimi scripty bude nakládáno jako s obyčejnými textovými hodnotami a zobrazí se uživatelům v jejich prohlížečích. Heslo k databázi jim zcela jistě zvedne náladu
Include & Require
Bezpečné vkládání souborů pomocí pole očekávaných hodnot nebo cykluswitch by mělo být samozřejmostí. Co když ovšem předem seznam vkládaných hodnot neznáte, nebo se jednoduše chcete zbavit břemene neustálé nutnosti tento seznam aktualizovat? Pak rozhodně načítejte pouze lokální soubory (před proměnou nesoucí jméno vkládaného souboru vložte zástupný symbol pro aktuální adresář './'), deaktivujte direktivu allow_url_include, testujte existenci includovaného souboru (funkce file_exists()) a negativně reagujte na přítomnost určitých znaků, jakými jsou 'index' (vyhnete se tak zacyklení scriptu a následnému DoSu), null byte, bílé a řídící znaky (trim($promenna, " \t\n\r\0\x0B\xA0")), './', '../', ':', '://', 'sess_' (fyzické soubory sezení), 'environ' (viz útok pomocí /proc/self/environ) a veškeré názvy adresářů, kam směřuje upload ('files/', 'tmp/', 'temp/', 'images/', 'data/' atp.).
Kompilace zdrojových souborů
Máte-li na svém serveru možnost použít některý z kompilátorů jazyka PHP, pak rozhodně neváhejte, v opačném případě požádejte správce o doinstalování takového balíčku. Osobně používám BCompiler a jsem zcela spokojen. Nedoporučuji ovšem kompilovat veškeré vaše scripty, neboť taková aplikace se obtížně spravuje (je nutné mít zálohu nekompilovaných souborů a ty v případě potřeby aktualizovat, zkompilovat a následně nahrát na produkční server místo těch původních, dekompilace totiž není možná). Zkompilujte proto především soubory s citlivými údaji, tedy například script zajišťující přístup k databázi. Kompilace se provádí následovně:
Kompilovaný kód má ovšem jednu podstatnou nevýhodu, kterou jsem vám dosud zatajil, a sice, že při jeho otevření jsou ve změti tisknutelných i netisknutelných znaků čitelné stringy z nekompilované verze, tedy včetně přístupového hesla. Tato nechtěná vlastnost se dá ovšem snadno vyřešit např. tím způsobem, že namísto klasického zadávání přístupových údajů v řetězci
předáme přihlašovací údaje v polích obohacených o změť náhodných znaků ($mysqlDust):
V kompilovaném souboru database.php tak bude pouze změť písmen a znaků, ze které útočník heslo pouhým okem nezíská. Script zajišťující připojení k databázi by pak mohl vypadat nějak následovně:
Takto zkompilované přihlašovací údaje jsou v relativním bezpečí, ačkoliv se k nim šikovný útočník může teoreticky stále dostat. Přesto však zmíněný bezpečnostní prvek odfiltruje drtivou většinu záškodníků, a jeho nasazení vřele doporučuji, chcete-li v případě kompromitace zdrojových kódu ochránit alespoň svoji databázi. Zároveň opatřete zkompilovaný soubor nenápadným jménem, přeci jen v případě database.php neboconfig.php je to zcela jistě první soubor, na který se útočník zaměří. Volba zavádějícího jména (seo.php, style.php, tadyNicNeni.php, …) tak může rovněž kdejakému útočníkovi zamotat hlavu.
Závěr
Doufám, že jste v tomto článku našli odpověď na některé své otázky a stal se tak pro vás přínosem v oblasti zabezpečení webových aplikací. Pokud máte jakékoliv připomínky nebo znáte jiné zajímavé tipy a triky, neostýchejte se o ně podělit s ostatními v komentářích.
zdroje:hlava,google