Hlavní navigace

Názor k článku Zranitelnosti typu injekce: SQL injekce od Filip Jirsák - Netvrdím, že je to ideální řešení, i když...

  • Článek je starý, nové názory již nelze přidávat.
  • 14. 10. 2018 15:36

    Filip Jirsák

    Netvrdím, že je to ideální řešení, i když myslím, že tak stupidní věc jen tak nějaká DB neudělá. Možná H2.
    Databáze se nerozhoduje podle nálady, jak bude dělat implicitní konverze, má na to jasně definovaná pravidla. Pokud někdo má číslo, chce porovnávat čísla, ale to číslo převede na string, je stupidní on, nikoli databáze.

    Je tedy celkem jedno, jestli vstup je UTF-8, UTF-16, UTF-7, ASCII nebo třeba GBK. Jakmile se z toho udělá String, musí to být validní, a dál nám případný sanitizovaný nevalidní vstup nemá jak ublížit. Maximálně uložíme nějaký gibberish do DB (pokud špatně dekódujeme vstup), ale na escapování to vliv nemá.
    To, že mám v Javě validní string, neznamená, že to je ten samý string, jaký byl na vstupu (což může způsobit chybná data v databázi), ani že je to ten samý string, jaký se zapíše do databáze (což v případě ochrany escapováním můževést k SQL injection).

    Představte si, že aplikace si myslí, že odesílá data do databáze v ISO Latin-1, ale databáze si bude myslet, že data dostává v UTF-1 (které už se naštěstí prakticky nepoužívá). V aplikaci bude něco jako "SELECT * FROM users WHERE login = '${escape(login)}'". V proměnné login bude útočníkem vložen text ¡'; DELETE FROM users; --. Funkce escape() „zabezpečí“ vstup a před ten apostrof např. přidá zpětné lomítko. Do databáze se tedy pošle text:

    SELECT * FROM users WHERE login = '¡\'; DELETE FROM users; --'

    Text se pošle zakódovaný v ISO Latin-1. Zajímavá je ta sekvence s obráceným vykřičníkem – ten bude v ISO Latin-1 zakódován jako 0xA1, následující zpětné lomítko jako 0x5C a apostrof jako 0x27. No a databáze to čte jako UTF-1, všechny znaky před tím jsou z ASII, takže jsou shodné – ale sekvence 0xA1 0x5C je v UTF-1dvoubajtová sekvence kódující codepoint U+0106, tedy znak Ć. Takže databáze dostane na vstupu následující text:

    SELECT * FROM users WHERE login = 'Ć'; DELETE FROM users; --'

    Mně to připadá jako učebnicový příklad SQL injection, vám ne? A přitom aplikace pracovala s naprosto validním textem.

    Právě proto považuju escapování za nebezpečné. Z hlediska escapování můžete mít všechno správně, ale stačí chyba v konfiguraci připojení do databáze, která se při normálním používání nijak neprojeví – a v aplikaci máte SQL injection. Navíc jak je vidět u z této diskuse, ne každý si záludnosti kódování znaků uvědomuje, a když „to funguje“, neřeší, jestli je to správně.