SQL Injection v mobilním vývoji: co to je, metody útoků a ochrana

Autor: IT Sectr Publikováno: 2026-04-06 Doba čtení: 9 min

SQL Injection — typ útoku na databázi aplikace, při kterém útočník vkládá škodlivý SQL kód do parametrů dotazu, čímž získává neoprávněný přístup k datům nebo možnost jejich modifikace. Podle údajů OWASP (2025) zůstává SQL Injection jedním z kritických zranitelností, které mohou vést k úplnému kompromitování databáze. Injekce SQL kódu umožňuje útočníkovi číst, měnit a mazat záznamy a v některých případech — získat přístup k operačnímu systému serveru.

Hlavní body

  • SQL Injection — vkládání SQL kódu pomocí uživatelských parametrů, které mění logiku dotazu do databáze
  • Parametrizace dotazů — hlavní metoda ochrany: oddělení SQL kódu od dat pomocí prepared statements
  • Typy útoků — klasická injekce (přes WHERE), Blind SQLi (logické závěry), UNION-based (čtení cizích tabulek)
  • Error-based SQLi — získávání dat pomocí chybových hlášení databáze
  • ORM frameworky — snižují riziko SQLi při správném použití, ale zcela ho neodstraňují

Co je SQL Injection?

SQL Injection je zranitelnost, která vzniká, když aplikace vytváří SQL dotaz pomocí zřetězení řetězců s uživatelskými daty. Útočník odesílá do parametru dotazu speciálně vytvořený řetězec, který mění strukturu SQL příkazu. Místo dat se vložený řetězec stává součástí SQL kódu, což umožňuje útočníkovi provádět libovolné dotazy do databáze. Podle Verizon Data Breach Report (2025) je SQL Injection přítomen v 8 % všech zkoumaných úniků dat.

Proč je SQL Injection stále aktuální?

Navzdory známosti zranitelnosti (první zmínky — konec 90. let) se SQL Injection vyskytuje v moderních aplikacích. Důvod — lidský faktor: vývojáři připouštějí zřetězení řetězců v kódu, legacy kód není refaktorován a ORM frameworky jsou používány nesprávně (např. raw dotazy s dosazováním hodnot pomocí řetězců). Podle údajů Veracode (2026) obsahuje přibližně 14 % všech skenovaných aplikací alespoň jednu zranitelnost SQLi.

Co může útočník udělat?

Úspěšný SQL Injection poskytuje útočníkovi širokou škálu možností: čtení libovolných tabulek databáze, včetně hashů hesel a osobních údajů uživatelů; modifikace a mazání záznamů; provádění administrativních operací (DROP TABLE, TRUNCATE); v některých konfiguracích — vzdálené provádění příkazů přes xp_cmdshell (MSSQL) nebo INTO OUTFILE (MySQL). Následky — od úniku uživatelských dat až po úplnou ztrátu kontroly nad systémem.

Typy SQL injekcí

SQL injekce se klasifikují podle způsobu získávání dat z databáze. Volba metody závisí na tom, jak aplikace zpracovává výsledky dotazu a chybová hlášení. Klasifikace OWASP rozlišuje tři hlavní typy: In-band (data jsou získávána stejným kanálem), Inferential/Blind (logické závěry) a Out-of-band (data jsou přenášena jiným kanálem).

TypZpůsob získávání datSložitostČetnost
In-band (klasický)Přímo přes výsledek dotazuNízkáVysoká
Blind SQLiLogické závěry podle odpovědí serveruVysokáStřední
Out-of-bandPřes externí kanál (DNS, HTTP)StředníNízká

In-band SQL Injection (klasický)

Nejrozšířenější typ. Útočník vkládá SQL kód do parametru dotazu a výsledek injekce je přímo viditelný v odpovědi serveru. Dva podtypy: Error-based (přes chybová hlášení databáze) a UNION-based (přes operátor UNION SELECT). Error-based využívá informace z chybových hlášení, například syntaktickou chybu MySQL, která může odhalit název tabulky nebo strukturu dotazu. UNION-based umožňuje spojit výsledky legitimního dotazu s daty z jiných tabulek databáze.

Blind SQL Injection (slepá)

Používá se, když aplikace nezobrazuje výsledky dotazu nebo chybová hlášení. Útočník klade otázky typu „ano/ne”, odesílá dotazy s logickými podmínkami a analyzuje rozdíl v odpovědi serveru (např. dobu odezvy nebo obsah stránky). Time-based Blind SQLi používá funkci zpoždění (SLEEP, WAITFOR DELAY) k potvrzení podmínek — pokud se stránka načítá déle, podmínka je pravdivá. Tato metoda je velmi pomalá — získání jednoho záznamu může trvat hodiny.

python
# Příklad Blind SQL Injection (time-based)
# Pokud je SQLi zranitelný, SLEEP(2) se provede za podmínky
import requests
import time

payload = "' OR IF(SUBSTRING((SELECT password FROM users LIMIT 1),1,1)='a',SLEEP(2),0) -- "
url = "http://example.com/user?id=1" + payload

start = time.time()
response = requests.get(url)
elapsed = time.time() - start

# Pokud odpověď přišla po >2 sekundách — první písmeno hesla je 'a'
print(f"Time: {elapsed:.2f}s - First letter is 'a'" if elapsed > 2 else "First letter is not 'a'")

Out-of-band SQL Injection

Data jsou přenášena ne pomocí HTTP odpovědi, ale prostřednictvím alternativních kanálů: DNS dotazů, HTTP požadavků na externí server, SMTP. Používá se, když aplikace nevrací výsledky dotazu a nezobrazuje chyby. MySQL podporuje funkci LOAD_FILE(), která může iniciovat DNS dotaz, a MSSQL — xp_dirtree pro odesílání dat na vzdálený SMB server. Out-of-band SQL Injection je účinný, ale vyžaduje další nastavení na serveru útočníka a přítomnost určitých funkcí databáze.

Jak funguje SQL injekce?

Mechanismus SQL Injection je založen na tom, že SQL používá uvozovky pro řetězcové literály. Pokud aplikace dosazuje uživatelský vstup přímo do SQL dotazu bez escapování, útočník může „uzavřít” řetězec a přidat libovolný SQL kód. Například v dotazu SELECT * FROM users WHERE name = '$input' dosazení ' OR '1'='1 mění dotaz na SELECT * FROM users WHERE name = '' OR '1'='1', což vrací všechny uživatele.

Klasický příklad: obejití autentizace

Uvažujme přihlašovací formulář s dotazem SELECT * FROM users WHERE username = '$user' AND password = '$pass'. Pokud útočník zadá do pole username admin' -- a heslo nechá prázdné, výsledný dotaz se stane SELECT * FROM users WHERE username = 'admin' -- ' AND password = ''. Znaky -- komentují zbytek dotazu a podmínka kontroly hesla je deaktivována. Server vrátí záznam uživatele admin a útočník vstoupí do systému bez znalosti hesla.

python
# Příklad SQL Injection — obejití autentizace
# ZRANITELNÝ KÓD: přímé zřetězení řetězců
def login_vulnerable(username, password):
    query = f"SELECT * FROM users WHERE username='{username}' AND password='{password}'"
    cursor.execute(query)
    return cursor.fetchone() is not None

# username = "admin' --" ruší kontrolu hesla
# BEZPEČNÁ VERZE: parametrizovaný dotaz
def login_secure(username, password):
    query = "SELECT * FROM users WHERE username = %s AND password = %s"
    cursor.execute(query, (username, password))
    return cursor.fetchone() is not None

UNION-based: čtení cizích tabulek

Operátor UNION SELECT umožňuje spojit výsledky dvou SELECT dotazů. Pokud útočník najde zranitelný parametr, přidá UNION SELECT s dotazem z jiné tabulky. Příklad: ' UNION SELECT username, password FROM admins --. Podmínkou úspěchu je shodný počet sloupců v obou dotazech. Počet sloupců se určuje pomocí ORDER BY (dosazení ' ORDER BY 1--, poté 2, 3... až do chyby). Útočník, který zná počet sloupců, dosadí UNION SELECT se stejným počtem polí.

SQL Injection v mobilních aplikacích

Mobilní aplikace se setkávají s SQL Injection jak na straně serveru (API), tak na straně klienta — v lokálních databázích (SQLite, Realm). Ačkoli riziko serverového SQLi v mobilním API je podobné webovým aplikacím, lokální databáze vytváří dodatečný vektor. Pokud aplikace ukládá data v SQLite a provádí dotazy se zřetězením řetězců, škodlivá data, která se dostala do lokální databáze přes API, mohou při následném zpracování způsobit SQLi.

SQL Injection v SQLite na Android/iOS

Lokální databáze SQLite na zařízení je také zranitelná vůči SQL Injection, pokud aplikace vytváří dotazy zřetězením řetězců. Content Providers na Androidu a Core Data na iOS používají parametrizaci ve výchozím nastavení, ale raw dotazy vyžadují pozornost vývojáře. SQLite nepodporuje více dotazů přes středník, což omezuje možnosti útočníka, ale nechrání před čtením dat pomocí podmínek WHERE. Vždy používejte selectionArgs v Androidu a NSPredicate s parametry v iOS.

SQL Injection přes API mobilní aplikace

API, ke kterému se mobilní aplikace připojuje, je zranitelné stejně jako jakýkoli webový server. Mobilní vývojáři často považují SQLi pouze za problém backendu, ale zranitelnost vzniká na úrovni API endpointu, který přijímá parametry od klienta. Rozdělení odpovědnosti nechrání: pokud vývojář backendu zapomněl parametrizovat dotaz, mobilní aplikace uživatele se stává vektorem útoku. Požadujte od backendu použití ORM nebo prepared statements.

kotlin
// Příklad SQL Injection v lokálním SQLite na Androidu
// ZRANITELNÝ KÓD: přímé zřetězení
fun getUserVulnerable(db: SQLiteDatabase, userId: String): Cursor {
    return db.rawQuery(
        "SELECT * FROM users WHERE id = $userId", null
    )
}

// BEZPEČNÁ VERZE: parametrizace pomocí selectionArgs
fun getUserSecure(db: SQLiteDatabase, userId: String): Cursor {
    return db.rawQuery(
        "SELECT * FROM users WHERE id = ?",
        arrayOf(userId)
    )
}

Metody prevence SQL injekcí

Ochrana proti SQL Injection je založena na jednoduchém principu: nikdy nevěřte uživatelskému vstupu v SQL dotazech. Jedinou spolehlivou metodou je parametrizace dotazů (prepared statements), při které jsou SQL kód a data přenášeny odděleně. Všechny ostatní metody — escapování, validace, WAF — jsou další vrstvy ochrany, ale nenahrazují parametrizaci. Podle údajů OWASP (2025) parametrizace zabraňuje 100 % útoků SQL Injection.

Prepared Statements (parametrizované dotazy)

Při použití prepared statements je SQL dotaz nejprve zkompilován serverem databáze bez dat a poté jsou hodnoty parametrů přenášeny odděleně. Databáze považuje parametry za data, nikoli za spustitelný kód. I když útočník odešle ' OR '1'='1, databáze to interpretuje jako řetězcovou hodnotu, nikoli jako SQL kód. Prepared statements jsou podporovány všemi moderními jazyky a frameworky: PDO v PHP, PreparedStatement v Javě, cursor.execute v Pythonu.

ORM frameworky a Query Buildery

Moderní ORM (Hibernate, Entity Framework, SQLAlchemy, Room) automaticky používají parametrizaci při provádění dotazů, pokud vývojář nepřejde na raw dotazy. Nicméně ORM nechrání zcela: konstrukce jako @Query(value = "SELECT * FROM users WHERE name = :name", nativeQuery = true) v JPA vyžadují předávání parametrů prostřednictvím pojmenovaných parametrů, nikoli zřetězení. Query Buildery (Knex, jOOQ) také parametrizují dotazy ve výchozím nastavení, pokud se nepoužívají raw metody.

Escapování řetězců (nedoporučuje se jako hlavní metoda)

Escapování speciálních znaků (mysql_real_escape_string) — zastaralá metoda, která nechrání proti všem typům SQL Injection. Problém: escapování závisí na kódování a může být obejito pomocí vícebajtových kódování (např. GBK v asijských systémech). Používejte escapování pouze v legacy kódu, kde parametrizace není možná, a vždy v kombinaci s přísnou validací typu vstupních dat.

MetodaÚčinnostDoporučení
Prepared Statements100 %Povinné pro všechny dotazy
ORM (správné použití)99 %Doporučuje se
Escapování řetězců70 % (závisí na kódování)Pouze legacy
Validace vstupu (bílá listina)50 % (pouze pro čísla)Doplňkové
WAF (Web Application Firewall)60 %Doplňkové

Princip nejmenších oprávnění pro databázi

Účet aplikace by měl mít minimálně nezbytná oprávnění: SELECT, INSERT, UPDATE, DELETE — pouze na tabulky, které aplikace skutečně potřebuje. Zakážte použití DROP, TRUNCATE, CREATE pro účet aplikace. To omezí škody i v případě úspěšného SQL Injection: útočník nebude moci smazat tabulky nebo provádět administrativní operace.

Nástroje pro detekci SQL injekcí

Pravidelné testování na SQL Injection by mělo být součástí pipelines bezpečného vývoje. Kombinace statické analýzy, dynamického skenování a ručního penetračního testování poskytuje nejlepší výsledky. Podle Synopsys Cybersecurity Report (2025) automatické skenery najdou až 70 % zranitelností SQLi, ale složité Blind útoky vyžadují ruční testování.

  • sqlmap — nejpopulárnější nástroj pro automatickou detekci a zneužití SQL Injection
  • OWASP ZAP — bezplatný DAST skener s moduly aktivního skenování SQLi
  • Burp Suite Scanner — profesionální nástroj s automatickou detekcí SQL Injection
  • SonarQube — statická analýza kódu na zranitelnosti, včetně vzorů SQLi
  • CodeQL — sémantická analýza kódu pro hledání SQL injekcí ve zdrojovém kódu

Pro mobilní aplikace je důležitá také analýza lokálního SQLite: zkontrolujte všechna volání rawQuery, dotazy ContentProvider a dotazy Room s rawQuery. Nástroje: Android Studio Lint (detekuje SQLi v SQLite), MobSF (Mobile Security Framework) pro automatickou statickou a dynamickou analýzu APK/IPA. Doporučuje se také testování API endpointů pomocí sqlmap s proxy zachytáváním provozu mobilní aplikace.

Často kladené otázky

Jaký je rozdíl mezi SQL Injection a NoSQL Injection?

SQL Injection útočí na relační databáze pomocí SQL dotazů. NoSQL Injection ovlivňuje nerelační databáze (MongoDB, Couchbase) prostřednictvím jejich operátorů dotazů ($gte, $ne, $where). V MongoDB je injekce možná, pokud aplikace vytváří BSON dokument z JSON řetězce. Ochranné mechanismy jsou podobné: parametrizace a validace typů.

Jak samostatně odhalit SQL Injection v kódu?

Najděte všechna místa, kde jsou SQL dotazy vytvářeny pomocí zřetězení řetězců s uživatelskými daty. Hledejte vzory jako "SELECT ... WHERE id = " + userId nebo f"UPDATE ... SET name = '{name}'". Každý takový řetězec je potenciální SQL injekce. Všechny nahraďte parametrizovanými dotazy nebo prepared statements.

Chrání ORM automaticky před SQL Injection?

ORM frameworky chrání automaticky pouze tehdy, pokud používáte jejich metody Query Builder a pojmenované parametry. Pokud používáte raw dotazy (nativeQuery v JPA, rawQuery v Room), ochrana nefunguje — parametry musíte předávat prostřednictvím připravených výrazů, nikoli zřetězením řetězců.

Co je Second-Order SQL Injection?

Second-Order SQL Injection je útok, při kterém jsou škodlivá data uložena v databázi jako bezpečná, ale poté použita v jiném dotazu bez escapování. Například útočník se zaregistruje s uživatelským jménem ' OR '1'='1. Data jsou uložena jako řetězec — při registraci nedochází k útoku. Pokud ale jiný dotaz dosadí uživatelské jméno do SQL bez parametrizace, injekce se aktivuje.

Může být NoSQL Injection nebezpečnější než SQL Injection?

NoSQL Injection je potenciálně nebezpečnější kvůli nižšímu povědomí vývojářů. Vývojáři vědí o SQL Injection a většina používá ORM, ale o NoSQL Injection ví málokdo. V MongoDB může nesprávně vytvořený dotaz vrátit všechny dokumenty kolekce. Ochrana — stejné prepared statements (BSON parametrizace) a přísná validace vstupních dat.

Shrnutí

  • SQL Injection — útok vkládáním SQL kódu prostřednictvím neescapovaných uživatelských parametrů v dotazech do databáze
  • Hlavní typy — In-band (klasický), Blind (slepý, časový), Out-of-band (přes externí kanál)
  • Parametrizace dotazů — jediná 100% spolehlivá metoda ochrany proti SQL Injection
  • Mýtus o ORM — ORM chrání pouze při použití vestavěných metod, raw dotazy se zřetězením jsou stále zranitelné
  • Princip nejmenších oprávnění — omezení práv účtu databáze minimalizuje škody při úspěšném útoku
  • Pravidelné testování — sqlmap, OWASP ZAP, SonarQube by měly být součástí CI/CD pipeline
  • Lokální SQLite — mobilní aplikace by také měly parametrizovat dotazy do lokální databáze

Vyvineme mobilní aplikaci na klíč

IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.

Prodiskutovat projekt

Přečtěte si také