Hlavní navigace

Na podceňovanou hrozbu SQL injection doplácí i řada českých webů

10. 6. 2008
Doba čtení: 11 minut

Sdílet

 Autor: 74287
Desítky tisíc hacknutých serverů po celém světě, včetně stále dokola se opakujících úspěšných průniků. Hromadné útoky na počítače návštěvníků důvěryhodných obsahových webů včetně českých. Za to všechno může maličkost jménem SQL injection.

V článku ČSOB podcenila zabezpečení svého webu věnovaném XSS (Cross Site Scripting) jsem nakousl problematiku vsouvání SQL kódu (SQL injection), takže je nejvyšší čas se podívat na to, co vlastně SQL injection je, k čemu slouží a co se s tím vším vlastně dá dělat. Pokud jsem u XSS naznačoval, že jde o bezpečnostní chybu s velkým rizikem pro uživatele, u SQL injection musím ještě přitvrdit. Mít na jakémkoliv webovém serveru SQL injection znamená, že se kdokoliv a odkudkoliv může „dívat“ na data v SQL databázích. A tato data pochopitelně nejenom prohlížet, ale také mazat či měnit. Tady tak nejspíš opravdu přestává jakákoliv legrace.

Základní princip SQL injection

Vsouvání SQL kódu je založeno na tom, že existuje webová aplikace, které je možné předávat bez omezení informace zvenčí. Nejčastěji s pomocí parametrů v URI nebo ve formulářích, ale cest, jak „dovnitř“ webového serveru dostat SQL kód, je daleko více. Pro vysvětlení principu všake bude nejjednodušší zůstat u parametrických URI. A rovnou si to ukážeme na jednom živém příkladu (provozovatel webu byl upozorněn na přítomnost SQL injection).

Když si otevřete http://www.ef­fatha.cz/ise/ak­cinfo.asp?id=, tak poněkud s překvapením ve spodní části stránky najdete chybovou hlášku:

Microsoft JET Database Engine error ‚80040e14‘
Syntax error (missing operator) in query expression ‚ID_akce= and ATvaz.id_typ=typ­.id_typ‘.
/ise/akcinfo.asp, line 206

a z ní už snadno odvodíte, že pomocí id= můžete snadno ovlivňovat, co vlastně bude SQL server vykonávat. To, co napíšete za id=, totiž bude přímo, beze změn, součástí SQL příkazu, který vypadá nejspíš nějak jako SELECT ..... WHERE ID_akce=_para­metr_and ATvaz.id_typ=typ­.id_typ. A v tomto případě máte od vlastního webu dokonce docela slušný návod k tomu, „jak“ vlastně můžete SQL injection využít.

Protože příkladů není nikdy dost, nabídnu ještě jeden – ten totiž demonstruje můj nejoblíbenější řetězec pro ruční testování na zranitelnost na SQL injection. Na www.estav.cz (správce serveru byl upozorněn) najdete formulářové pole pro vyhledávání ve zprávách. Pokud do něj zadáte „' or 1=1 ---“ (na začátku je apostrof, ty uvozovky se nezadávají), dostanete překvapivě povědomou odpověď:

Microsoft OLE DB Provider for SQL Server error ‚80040e14‘
Line 1: Incorrect syntax near ‚1‘.
/include/hled-zpravy.inc, line 11

I zde je tedy zřejmé, že SQL příkaz, který daná aplikace používá, rovnou přijímá vstup, aniž by ho nějakým způsobem sanitizoval (ošetřil a umravnil). Dobře cvičené opici (chcete-li také script kiddies) už pak stačí jenom příjít na to, jak je vlastně ten příkaz postavený. A pak ho patřičně zneužít. A nejlépe se podobné věci zneužívají třeba tam, kde se můžete přihlásit do redakčního systému – představte si, že existuje takováto konstrukce (v ASP, ale může to být jakýkoliv jazyk):

cSQL = „SELECT uniqueid FROM Users Where UserName=‚“ & request(„userid“) & „‘ and Pwd=‚“ & request(„pwd“) & „‘“

Takováto konstrukce se po použití mého oblíbeného ' or 1=1 promění na:

SELECT uniqueid FROM Users Where UserName='' or 1=1 –' and Pwd=‚heslo‘

Což bude znamenat, že bez zadání hesla (a dokonce i jména) se můžete snadno přihlásit do redakčního/pu­blikačního systému.

A do třetice všeho dobrého a zlého, jeden další příklad – www.svetsiti.cz nabízí pro špatně napsané parametry (http://www.svet­siti.cz/view.as­p?rubrika=Aktu­ality&clanekID=x663) také docela dobrý návod. A jak zjistíte později, právě Svět Sítí se stal obětí útoku pomocí SQL injection už několikrát – jeho provozovatelé o problému vědí, ale buď nemohou, nebo nechtějí sjednat nápravu (každopádně zcela ignorují jakékoliv e-maily s upozorněním na problém).

Microsoft OLE DB Provider for ODBC Drivers error ‚80040e14‘
[Microsoft][ODBC SQL Server Driver][SQL Server]Invalid column name ‚x663‘.
/view.asp, line 46

Pokročilejší SQL injection

Předchozí případ byl tak nějak až trapně jednoduchý. Ve skutečnosti je SQL injection daleko složitější a nebezpečnější. Málokdy se totiž použije pro něco tak hravého a nenápadného, jako je přihlášení do nějakého „bezpečného“ systému. Ve většině případů se používá v botnet aktivitáchvsouvání HTML kódu přímo do textových polí v tabulkách v dostupných databázích – dopadne to potom tak, že automatické systémy dokáží infikovat desítky tisíc webových serverů a uživatelům tak dodávat až miliony infikovaných stránek. Infikovaných týmž útočným kódem, o kterém byla řeč již dříve v ČSOB podcenila zabezpečení svého webu, a který slouží k napadení a hacknutí počítače nic netušícího návštěvníka. Něco podobného se před několika dny mohlo stát návštěvníkům www.svetsiti.cz (na screenshotu z Google si všimněte i toho, jak útok poškodil samotný titulek článku):

Svět sítí může hacknout váš počítač

a dokonce na České Škole (viz Pozor na napadení pomocí SQL injections!). V těchto (a řadě dalších) případech šlo o napadení v rámci masivních automatických botnet aktivit. A protože jsem v mezititulku slíbil něco o pokročilejší SQL injection, přidám rovnou detail toho, jak právě ten „mass SQL injection“ útok funguje – a je to docela zajímavé.

Především hledá s pomocí Google všechny weby používající ASP skripty a mající nějaké „obvyklé“ parametrické URI (například obsahující id=). Jakmile je najde, začne na vytvořeném seznamu zkoušet, jestli jsou napadnutelné SQL injection – v podstatě nědělá nic jiného, než že se snaží do URI vložit následující SQL kód:

Sql injection sample 1

Ten, jakkoliv vypadá podivně, je ve skutečnosti jenom reprezentací tohoto kódu (pokud byste ho nechtěli přepisovat, dejte vědět, pošlu vám ho):

Sql injection sample 2

Pokud vládnete jazykem SQL, tak začínáte tušit, jak velká je tohle zrada (a malér). Tenhle malý kousek skriptu prostě vezme všechny tabulky (které má smysl vzít) a v nich do všech textově použitelných polí připojí řetězec <script src= …></script>.

Pokud něco takového udělá na nějakém obsahovém webu (e-mag, zpravodajský web, diskusní fóra), tak je víc než zřejmé, že většina toho vsunutého kódu si najde cestu k návštěvníkům daného webu.

Na uvedené adrese (www.wowgm1.cn/m­.js) už mimochodem nic nenajdete, útočné skripty se mezítím přesměrovaly jinam a dnešní útoky používají jiné adresy. A za týden budou používat další (a ty staré, jako třeba www.nihaorr1.com/1­.js, www.ririwow.cn/in­dex.htm, zůstanou viditelné už jenom ve vyhledávačích). Pokud vás ale přesto zajímá, co vlastně na uvedené adrese bylo, tak zde na pooh.cz je to možné zjistit, případně se dozvědět i další věci u F-Secure (další F-Secure). S pomocí Google je stále ještě možné vidět, že různé varianty tohoto útoku napadly různé weby – mezi napadenými jsou (možná už nejsou, nebo možná znovu budou) Strabag.cz, Alza.cz, SvetSiti.cz, CDesign.cz či Cesky-Katalog.cz.

Doufám, že jste si dostatečně uvědomili, co vlastně uvedený malý kousek kódu dělá – on skutečně zcela nemilosrdně změní všechny vaše (vyhovující) tabulky (a v nich vyhovující pole). Po útoku tohoto typu vám zpravidla nezbude nic jiného, než obnovit data ze zálohy. Nebo se věnovat hodiny odstraňování kódu, který ve svých datech skutečně nechcete. Případně zkusit následující „reverzní“ kód:

DECLARE @T varchar(255), @C varchar(255); DECLARE Table_Cursor CURSOR FOR SELECT a.name, b.name FROM sysobjects a, syscolumns b WHERE a.id = b.id AND a.xtype = 'u' AND (b.xtype = 99 OR b.xtype = 35 OR b.xtype = 231 OR b.xtype = 167); OPEN Table_Cursor; FETCH NEXT FROM Table_Cursor INTO @T, @C; WHILE (@@FETCH_STATUS = 0) BEGIN EXEC( 'update ['+@T+'] set ['+@C+'] = left( convert(varchar(8000), ['+@C+']), len(convert(varchar(8000), ['+@C+'])) - 6 - patindex(''%tpircs<%'', reverse(convert(varchar(8000), ['+@C+']))) ) where ['+@C+'] like ''%<script%</script>''' ); FETCH NEXT FROM Table_Cursor INTO @T, @C; END; CLOSE Table_Cursor; DEALLOCATE Table_Cursor;

SQL injection je ale nejenom skvělý nástroj pro vsouvání útočného kódu na miliony webových stránek – díky další skvělé vlastnosti SQL, řetězení, můžete SQL server přimět k věcem, které jeho správce určitě neuvidí rád. Můžete smazat všechny tabulky, můžete zkusit SQL server vypnout, přidávat nové SQL uživatele. Všechno pochopitelně záleží hlavně na tom, jestli správce SQL a webové aplikace má vše zabezpečeno nad úroveň stavu „otevřený systém, vítejte“. A pokud zabezpečeno nemá, tak dokonce můžete spouštět z (zejména) Microsoft SQL příkazy „DOSu“ (rozuměj příkazové řádky operačního systému). V historii Internetu existují nespočty příkladů, kdy prostřednictvím webu a SQL došlo ke kompletní kompromitaci počítače, na kterém daná webová aplikace běžela.  Pokud stále netušíte, tak možná napoví následující:

‚; exec master..xp_cmdshell '…‘ –

Přišli jednou, přijdou znovu

Už jsem to naznačil – například v případě SvětSiti.cz došlo několikrát k tomu, že jeho provozovatelé odstranili „aktuální“ hacknutí, aby server byl opět hacknut o pár minut či hodin později. Jako u všech bezpečnostních rizik je i zde platné zásadní pravidlo – přišli jednou, přijdou znovu. A pokud je ve hře botnet aktivita s tisícovkami počítačů, je jasné, že bude klidně pořád dokola zkoušet to samé – v případě těchto útoků nejde o žádné ohledy či čistotu řešení, jde pouze o možnost napadnout co nejvíce počítačů. Při použití Google na některé z uvedených čínských domén tak například zjistíte, že některé weby obsahují několikrát přidané útočné skripty.

Pokud nějaká podobná „věc“ napadla právě váš server a vy jste snad dokonce přišli na to, kudy k tomu došlo, neznamená to, že někde jinde neexistují další otevřená vrátka. Pokud máte webovou aplikaci napadnutelnou pomoci SQL Injection (ale i XSS), tak je více než pravděpodobné, že autoři byli nepořádní důkladně a zanechali otevřená vrátka všude, kde to jenom šlo. A z mých zkušenosti plyne, že je tomu přesně tak.

Klaus sql injection

Problémem jsou pochopitelně i řady starých webových aplikací – v nich bývají chyby zcela běžné a možnost jejich oprav bývá zpravidla ztížena tím, že neexistuje dokumentace, autoři jsou dávno někde uplně jinde, případně není ani nikdo, kdo by měl dostatečné znalosti kdysi napsané aplikace.  A problémy tohoto druhu se vyhýbají málokomu – Klaus.cz (SQL injection i XSS), TakeIT.cz, Stavit.cz, Svět outdooru, Server muzeí a galerií ČR, Ministerstvo dopravy, Žena-in, Innovatio.cz, Buh.cz (SQL injection i XSS).

Jak ale můžete vidět z odpovědi serveru eStav.cz, většinou je problém spíše někde jinde – v nepochopení toho, že SQL Injection je v podstatě ošetřitelná triviálně. A že dokonce ani neexistuje něco jako „méně“ či „více“ nebezpečná SQL injection. To, jestli někde SQL injection je, má dva prosté stavy – je / není. A v neposlední řadě, odstranění SQL injection nemůže být „dlouhodobý proces“ a neřídí se tím, jestli se „čelí útokům“.

Dobrý den,
děkujeme za upozornění – v poslední době skutečně čelíme útokům a snažíme se postupně nebezpečná místa řešit. Pokud máte tip na typ SQL injection, který je nejčastější/nej­nebezpečnější (pokud je Vaše upozornění na základě aktuální hrozby), budeme rádi.

S pozdravem

Jan Brich
ABF, a.s. – redakce eStav.cz

Jak se bránit SQL injection?

Existuje nespočet návodů, jak se SQL Injection vyhnout – pomocí Google a zadání „SQL Injection“ jich najdete řadu – budete si tak moci i vybrat, zda potřebujete návod pro Microsoft SQL, MySQL či pro něco jiného. Principy jsou ale všechny stejné – jde o ošetření (sanitizaci, konverzi,  filtraci, parametrizaci) všech vstupních parametrů aplikace, které jakkoliv mohou ovlivnit podobu či obsah SQL příkazů. V tom úplně správném řešení byste měli používat možnosti objektového programování i k tomu, abyste nevytvářeli SQL příkaz skládáním z několika částí doplněných parametry, ale používali parametrizaci a všechny předávané hodnoty důsledně převáděli na konkrétní a správné datové typy.

Nezapomeňte, že stejně jako v případě XSS může ohrožení příjít z každého místa, které nějak vstupuje zvenčí a poté je ukládáno do databáze. Nejenom tedy parametry URI a vstupy z formulářů, ale také třeba refereové informace, user-agent řetězce a cookies (obecně cokoliv, co je součástí HTTP požadavku). Stačí aby se kterákoliv z těchto věcí byť jen ukládala do databáze, a už je nutné mít vše ošetřené proti SQL injection.

Je důležité si uvědomit i to, že SQL injection nemá nic společného s jazykem, ve kterém je webová aplikace napsaná – týká se stejně tak ASP/Microsoft SQL kombinace jako PHP/MySQL. A jak se můžete poučit například na www.z1.cz, tak se týká i PostgresSQL (viz Z1 sql injection).

Mimořádně polopaticky je asi vhodné prostě zopakovat to, že pokud je vstupem do webové aplikace text, který se má dostat do SQL příkazu, jedním ze základních ochranných kroků je záměna všech ['] (apostrof) za [''] (dvojice apostrofů). V lepším případě je ještě navíc vhodné použít regulární výrazy (regexp) a případně zamezit tomu, aby se do případného textu mohlo dostat cokoliv jiného, než povolené znaky (např. do PSČ opravdu patří jenom číslice a mezera).

Pokud jde o netextové vstupy, tak je poměrně jasné, že čísla je více než vhodné nechat převést na čísla pomocí odpovídající konverzní funkce (např. int() nebo něco podobného) a vstupy s pevně daným výčtem (něco jako True/False, 0/1, on/off) prostě napevno testovat na správnou hodnotu. A nespoléhat se vůbec na nic.

Webová aplikace by navíc rozhodně neměla nikdy zobrazovat žádné detailní chybové hlášky (viz začátek tohoto článku pro opravdu odstrašující příklady) – nezamezí se tím sice SQL injection, ale alespoň se hodně znepříjemní případným pokušitelům jejich snahy. „SQL injection naslepo“ není zrovna nejzábavnější.

BRAND24

Přímo uvnitř SQL serveru byste navíc měli zajistit, aby pro práci s SQL daty byly případně důsledně používány uložené procedury (Stored Procedures) a účet, pod kterým k SQL přistupuje webová aplikace, měl minimální práva (potřebná práva mohou mít uložené procedury).

Doporučené čtení

 

Snažíte se zabezpečit své stránky proti SQL injection?

Byl pro vás článek přínosný?

Autor článku

Konzultant a publicista, provozuje www.pooh.cz. Podle některých si myslí, že rozumí všemu, sám je však přesvědčen o pravém opaku a ani v 30+ letech nedokázal přijít na to, jak mít peníze a nepracovat.
Upozorníme vás na články, které by vám neměly uniknout (maximálně 2x týdně).