Wstrzyknięcie SQL
Od końca lat 90. zastrzyk SQL znajduje się na szczycie każdej listy luk w zabezpieczeniach sieci Web lub w jego pobliżu. Poprawka — zapytania sparametryzowane — jest znana, prosta i zalecana od dwóch dekad. Jednak co tydzień odkrywane są nowe luki w zabezpieczeniach SQLi. Kategoria ta utrzymuje się, ponieważ tryb awarii jest subtelny, a wartości domyślne wielu platform są niedoskonałe.
Poniżej znajduje się pełna treść artykułu w języku angielskim.
SQL iniekcja (SQLi) to klasa luk w zabezpieczeniach, w przypadku której osoba atakująca może wstrzyknąć kod SQL do zapytania wysyłanego przez aplikację do swojej bazy danych. Jeśli się powiedzie, osoba atakująca może odczytać, zmodyfikować lub usunąć dane, do których nie ma uprawnień, czasami wykonać kod na serwerze bazy danych, a czasami przejść do ataków na samą aplikację.
Klasyczny błąd
Przykład podręcznikowy. Aplikacja przyjmuje nazwę użytkownika z formularza logowania i wyszukuje ją:
query = "WYBIERZ * FROM użytkowników WHERE nazwa użytkownika='" + wejście + "';"Jeśli input to alice, zapytanie staje się:
SELECT * OD użytkowników GDZIE nazwa użytkownika='alicja';Normal. Ale jeśli input to alice' LUB '1'='1, zapytanie będzie wyglądać następująco:
SELECT * FROM users WHERE nazwa_użytkownika='alicja' OR '1'='1';The OR '1'='1' jest zawsze prawdą. Zapytanie zwraca każdego użytkownika w tabeli. W przypadku bardziej wyrafinowanych ładunków osoba atakująca może zrzucić tabele, zmodyfikować rekordy lub dalej eskalować.
Kategorie ataku
- Klasyczny / in-band SQLi. Wyniki wstrzykniętego zapytania pojawiają się w odpowiedzi aplikacji. Osoba atakująca bezpośrednio odczytuje dane.
- Blind SQLi. W odpowiedzi nie pojawiają się żadne dane, ale zachowanie aplikacji zmienia się w zależności od tego, czy wprowadzone zapytanie zwróci wartość true, czy false. Osoba atakująca wyodrębnia dane pojedynczo, zadając pytania typu „czy pierwszym znakiem hasła administratora jest „a”?”
- Ślepe SQLi. Osoba atakująca używa
SLEEP()lub równoważnego, aby baza danych odpowiadała powoli, gdy warunek jest spełniony. Jeszcze wolniejsza eksfiltracja danych, ale działa, gdy aplikacja nie przekazuje informacji zwrotnej. - SQLi poza pasmem. Osoba atakująca oszukuje bazę danych, aby nawiązała połączenie z siecią zewnętrzną (wyszukiwanie DNS, żądanie HTTP), co powoduje wyciek danych do kontrolowanego przez siebie serwera.
- SQLi drugiego rzędu. Złośliwe dane wejściowe jest najpierw przechowywany w bazie danych, a następnie odczytywany i używany w innym zapytaniu w sposób niebezpieczny. Wstrzyknięcie odbywa się w kontekście innym niż dane wejściowe.
Poprawka: sparametryzowane zapytania
Właściwy sposób wysyłania zapytań do bazy danych z danymi wejściowymi użytkownika polega na użyciu symboli zastępczych parametrów, a nie na łączeniu ciągów. W zasadzie w każdym języku:
// Python (psycopg2)
kursor.execute("WYBIERZ * OD użytkowników GDZIE nazwa użytkownika=%s", (wejście))
// Jawa
stmt = conn.prepareStatement("WYBIERZ * OD użytkowników GDZIE nazwa_użytkownika=?");
stmt.setString(1, wejście);
// JavaScript (str.)
klient.query("WYBIERZ * OD użytkowników GDZIE nazwa użytkownika=1$", [wejście]);Sterownik wysyła osobno wartość SQL i wartości parametrów. Baza danych nigdy nie myli danych wejściowych ze składnią SQL. Nawet jeśli dane wejściowe zawierają cudzysłowy, średniki, klauzule OR lub jakąkolwiek inną składnię SQL, są traktowane jako dane.
To działa. Jest to podejście zalecane od dwóch dekad. Wyzwaniem nie jest technika; zapewnia, że każde zapytanie w bazie kodu go używa.
ORM nie są automatycznie bezpieczne
Object-Relational Mappers (ActiveRecord, Sequelize, Hibernate, SQLAlchemy) domyślnie używają sparametryzowanych zapytań, co jest świetne. Ale każdy ORM ma luki ratunkowe:
raw()metody pobierające dowolne ciągi SQL- klauzule ORDER BY oparte na łańcuchach (nie można parametryzować nazw kolumn)
- Tnazwy tabel interpolowane do zapytania
- Procedury składowane, które same się łączą
Błędy współczesnego SQLi zwykle pojawiają się w tych przypadkach brzegowych, a nie w głównej ścieżce kodu CRUD.
Zastrzyk NoSQL
Wzorzec nie jest unikalny dla SQL. MongoDB, Redis, ElasticSearch, GraphQL — każdy język zapytań, który akceptuje ustrukturyzowane dane wejściowe od użytkowników, może zostać wstrzyknięty, jeśli dane wejściowe nie zostaną zweryfikowane. Operatory $ne, $gt, $regex MongoDB są powszechnymi wektorami wstrzykiwania, gdy ładunki JSON nie są ściśle sprawdzane według schematu.
Dogłębna obrona
Poza parametryzacją zapytania:
- Lkonta bazy danych z uprawnieniami typu East. Aplikacja powinna połączyć się z użytkownikiem posiadającym jedynie potrzebne jej uprawnienia. Ścieżki tylko do odczytu korzystają z poświadczeń tylko do odczytu. Ogranicza szkody w przypadku wykorzystania SQLi.
- Weryfikacja danych wejściowych. Ogranicz dane wejściowe do oczekiwanych formatów. Pomocne, ale same w sobie niewystarczające.
- Zapory sieciowe aplikacji internetowych (WAF). Oczywiste próby SQLi polegające na dopasowywaniu wzorców. Można ominąć, ale spowalniają atakujących.
- Analiza statyczna. Narzędzia skanujące źródło w poszukiwaniu zapytań połączonych ciągami znaków. Nowoczesne IDE oznaczają to.
- Twardość bazy danych. Wyłącz niepotrzebne funkcje (
xp_cmdshellw MSSQL, niebezpieczne rozszerzenia w PostgreSQL).
Famous SQLi incydenty
- 2007 TJX — 94 miliony kart kredytowych. Zaczęło się od kompromisu w Wi-Fi, ale do ekstrakcji wewnętrznych baz danych użyto SQLi.
- 2008 Heartland — 130 milionów rekordów kart. SQLi udzieliło wstępnego dostępu do sieci.
- 2012 LinkedIn — 117 milionów skrótów haseł zostało wyodrębnionych za pośrednictwem SQLi.
- 2017 Equifax — luka w Apache Struts, ale SQLi był częścią danych po kompromitacji eksfiltracja.
- TPrzez cały rok 2020 — niezliczone mniejsze naruszenia w firmach SaaS, witrynach handlu elektronicznego i agencjach rządowych.
Kategoria ma kilkadziesiąt lat i wciąż jest bardzo żywa.
Często zadawane pytania
- Czy zastrzyk SQL jest nadal powszechny?
- Tak. Lista OWASP Top 10 co roku umieszcza Injection (w tym SQLi) w trzech najważniejszych kategoriach. Programy nagród za błędy widzą raporty SQLi co tydzień. Nowoczesne frameworki zmniejszyły częstotliwość występowania w głównych ścieżkach kodu, ale starsze aplikacje, przypadki brzegowe i luki ratunkowe ORM utrzymują tę kategorię przy życiu.
- Czy zapora aplikacji sieci Web może zatrzymać wszystkie zastrzyki SQL?
- Nie. Mechanizmy WAF wyłapują oczywiste wzorce i powstrzymują niewyrafinowanych atakujących, ale doświadczeni napastnicy mogą opracować obejścia — różne kodowania, wstawianie komentarzy, alternatywną składnię SQL. WAF są przydatną warstwą; nie zastępują one bezpiecznego konstruowania zapytań w aplikacji.
- Czy HTTPS zapobiega wstrzykiwaniu SQL?
- Nie. SQLi to luka w warstwie aplikacji. HTTPS chroni przesyłane dane, ale nie sprawdza ich zawartości. Złośliwe dane wejściowe osoby atakującej docierają za pośrednictwem protokołu HTTPS, tak jak wszystkie inne osoby; aplikacja jest tym, co przetwarza ją bezpiecznie lub nie.
- Czy bazy danych NoSQL są odporne?
- Nie. Wstrzykiwanie NoSQL to osobna kategoria. MongoDB, Elasticsearch i inne akceptują ustrukturyzowane dane wejściowe zapytań, którymi można manipulować, jeśli nie są one ściśle sprawdzane. Wzorce ochronne są podobne (traktuj dane wejściowe użytkownika jako dane, nigdy jako strukturę zapytania), ale konkretne ataki są różne.
- Jak przetestować własną witrynę pod kątem iniekcji SQL?
- Narzędzia takie jak sqlmap automatyzują testowanie typowych wzorców SQLi; OWASP ZAP i Burp Suite zawierają skanery. Dla programistów najbardziej niezawodnym sprawdzeniem jest przegląd kodu i analiza statyczna zapytań połączonych ciągami. Zadania testów penetracyjnych obejmują w szczególności ocenę SQLi.