Konferencja Mega Sekurak Hacking Party w Krakowie – 26-27 października!
Mikołajki z sekurakiem! od 2 do 8 grudnia!
Konferencja Mega Sekurak Hacking Party w Krakowie – 26-27 października!
Mikołajki z sekurakiem! od 2 do 8 grudnia!
Z artykułu dowiesz się:
Wyobraźmy sobie sytuację, gdy ujawniony zostaje kod exploita, który jest w stanie zaatakować naszą aplikację. Informacja taka mogłaby na przykład pochodzić od zespołu CERT, z własnych systemów honeypot lub z serwisów publikujących informacje o zagrożeniach sieciowych. Producent danego oprogramowania nie przygotował jeszcze nowej wersji oprogramowania, odpornej na działanie exploita. Mamy tu do czynienia z klasycznym przykładem exploita typu 0-day, gdzie moment ujawnienia podatności jest różny od wydania oficjalnej łatki. W sytuacji, gdy procedury aktualizacji oprogramowania wymagają przeprowadzenia żmudnych testów, czas niezbędny do zaaplikowania tej poprawki może się znacznie wydłużyć. Zespół odpowiedzialny za zagadnienia ochrony aplikacji webowych powinien w takiej sytuacji skorzystać z możliwości, jakie oferują wirtualne poprawki, ponieważ cechują się one:
Jak widać, wirtualne poprawki mają wiele zalet, jednak należy mieć stale na względzie, że bezpieczeństwo informatyczne to proces wielopłaszczyznowy, nie należy więc polegać wyłącznie na wirtualnym patchowaniu jako alternatywie dla aktualizacji oprogramowania w celu redukcji kosztów.
ModSecurity jako moduł serwera WWW (tu Apache, ale możliwa jest też integracja z NGINX i IIS) jest w stanie przechwytywać i analizować zapytania/odpowiedzi, pracując w dwóch trybach z punktu widzenia architektury bezpieczeństwa:

Rysunek 1. Poglądowy schemat działania reverse proxy z ModSecurity.
ModSecurity może również działać w dwóch podstawowych trybach z punktu widzenia powstrzymywania ataków:
ModSecurity „rozumie” protokół HTTP, a poszczególne zapytania i odpowiedzi łączy w odpowiadające sobie transakcje, dlatego też jest w stanie filtrować złośliwą aktywność na różnych etapach ataku. W przetwarzaniu reguł można rozróżnić pięć faz:
W konfiguracji ModSecurity definiuje się domyślną akcję, jaką nasz WAF będzie realizował w przypadku, gdy reguła zostanie dopasowana do danego zapytania lub odpowiedzi HTTP, przykładowo:
SecDefaultAction „phase:2, deny, log, status:403”
Co należy interpretować: gdy zostanie wczytane zapytanie w fazie drugiej (nie tylko HEADER, ale też BODY) i zostanie dopasowane do którejś z reguł SecRule, ModSecurity odrzuci takie zapytanie, zapisze zdarzenie do logu, a klientowi zwróci odpowiedź z kodem 403 – Forbidden. Zastosowanie akcji drop zamiast deny spowoduje wysłanie pakietu TCP z flagą FIN, co może być bardziej skuteczne w przypadku ataków Denial of Service.
Ingerencja w ruch HTTP w czasie każdej z wyżej wymienionych faz, pozwala na bardzo elastyczne sterowanie akcjami w ramach implementowania własnych reguł. Jeśli chcemy, aby dana reguła została sprawdzona w innej fazie niż określona w domyślnej akcji, to dopisujemy numer fazy (phase) np.:
SecRule REMOTE_ADDR „^192\.168\.” „phase:1, pass, log, msg: 'Podejrzany ruch IP'”
Powyższa reguła zostanie sprawdzona w pierwszej fazie, zapytanie będzie przekazane do następnej fazy, ale jeśli będzie wysłane z adresu IP rozpoczynającego się od „192.168” to zdarzenie to zostanie zapisane w logu.
ModSecurity przetwarza każde zapytanie w cyklu pięciu faz. W ramach każdej z nich reguły są sprawdzane w kolejności, w jakiej są wpisane w pliku konfiguracyjnym reguł, a ModSecurity wybiera tylko te reguły, które odpowiadają danej fazie. Zapytanie, które zostało przepuszczone w ramach fazy 1, może zostać odrzucone na późniejszych etapach – np. po analizie parametrów zapytania POST, co odpowiada fazie 2.
Oprócz tworzenia własnych reguł, ModSecurity posiada możliwość dołączania do konfiguracji predefiniowanych reguł przygotowanych na znane ataki webowe. Reguły te można pobrać ze stron:
ModSecurity można zainstalować jako moduł serwera WWW (tu przykład dla serwera Apache w dystrybucji Debian):
$ sudo apt-get install libapache2-mod-security2 Czytanie list pakietów… Gotowe Budowanie drzewa zależności Odczyt informacji o stanie… Gotowe Zostaną zainstalowane następujące dodatkowe pakiety: modsecurity-crs Sugerowane pakiety: lua geoip-database-contrib Zostaną zainstalowane następujące NOWE pakiety: libapache2-mod-security2 modsecurity-crs $ sudo a2enmod mod-security
Pliki konfiguracyjne umieszczone są w trzech lokalizacjach:
Podstawowa konfiguracja silnika ModSecurity znajduje się w pliku modsecurity.conf, a wraz z modułem zostaje doinstalowany dodatkowy pakiet reguł Core Rule Set.
Proces konfiguracji warto rozpocząć od zalecanych ustawień, które znajdują się w pliku z rozszerzeniem recommended:
$ sudo mv /etc/modsecurity/modsecurity.conf-recommended /etc/modsecurity/modsecurity.conf
W pliku tym decydujemy o podstawowych parametrach pracy ModSecurity, np. trybie detekcji lub prewencji:
SecRuleEngine DetectionOnly | On | Off
Zbiór reguł ModSecurity CRS zlokalizowany jest w /usr/share/modsecurity-crs/
$ ls /usr/share/modsecurity-crs/ activated_rules experimental_rules modsecurity_crs_10_setup.conf slr_rules base_rules lua optional_rules util
Reguły te dołączamy wpisami do pliku konfiguracyjnego modułu security2.conf
<IfModule security2_module> IncludeOptional /etc/modsecurity/*.conf IncludeOptional "/usr/share/modsecurity-crs/*.conf" IncludeOptional "/usr/share/modsecurity-crs/activated_rules/*.conf" </IfModule >
Reguły z katalogu base_rules należy przejrzeć i dołączyć do konfiguracji przez tworzenie linków symbolicznych w katalogu activated_rules:
$ cd /usr/share/modsecurity-crs/activated_rules $ ls ../base_rules/ modsecurity_35_bad_robots.data modsecurity_35_scanners.data modsecurity_40_generic_attacks.data modsecurity_50_outbound.data modsecurity_50_outbound_malware.data modsecurity_crs_20_protocol_violations.conf modsecurity_crs_21_protocol_anomalies.conf modsecurity_crs_23_request_limits.conf modsecurity_crs_30_http_policy.conf modsecurity_crs_35_bad_robots.conf modsecurity_crs_40_generic_attacks.conf modsecurity_crs_41_sql_injection_attacks.conf modsecurity_crs_41_xss_attacks.conf modsecurity_crs_42_tight_security.conf modsecurity_crs_45_trojans.conf modsecurity_crs_47_common_exceptions.conf modsecurity_crs_48_local_exceptions.conf.example modsecurity_crs_49_inbound_blocking.conf modsecurity_crs_50_outbound.conf modsecurity_crs_59_outbound_blocking.conf modsecurity_crs_60_correlation.conf $ sudo ln -s ../base_rules/modsecurity_crs_40_generic_attacks.conf
Po dołączeniu wszystkich niezbędnych plików konfiguracyjnych – w tym plików reguł – wymagany jest restart serwera:
$ sudo service apache2 restart
Aktualizacja reguł ModSecurity-CRS odbywa się poprzez apt-get upgrade lub aktualizację pojedynczego pakietu, w tym wypadku:
$ sudo apt-get install modsecurity-crs --only-upgrade
W zależności od specyfiki aplikacji, część reguł może generować fałszywe alarmy i reguły te powinny być wyłączane albo zmodyfikowane. W celu wyłączania reguł warto skorzystać z ich numerów id. Możemy wyłączać je globalnie, dla konkretnych wirtualnych hostów lub lokalizacji w aplikacji.
<LocationMatch "/wordpress/wp-login.php">
<IfModule security2_module>
SecRuleRemoveById 981134
</IfModule>
</LocationMatch>
Aby pisać własne reguły, należy przygotować osobny plik, który nie będzie nadpisywany w czasie aktualizacji pakietów.
$ sudo vi /etc/modsecurity/modsecurity_custom_rules.conf
Czytanie i pisanie reguł ModSecurity jest bardzo proste. Silnik WAF oferuje również kilka rozwiązań, które pomagają elastycznie pisać reguły tak, by mogły skutecznie powstrzymywać różne rodzaje ataków webowych, są to:
Poniższe przykłady powinny jednoznacznie przedstawić, w jaki sposób należy stosować wymienione funkcje w czasie definiowania reguł:
SecRule Target Operator [Transformation Action]
Przykłady: ARGS – kolekcja zawierająca wszystkie parametry zapytania GET i POST, np.
SecRule ARGS:username|ARGS:password „admin”
Reguła sprawdza, czy w parametrach zapytania, takich jak username lub password, przekazywane są wartości „admin”.
Inne często stosowane kolekcje: ENV, FILES, GEO, IP, REQUEST_*, SESSION, USER.
Istnieje specjalny rodzaj kolekcji TX pozwalających na definiowanie własnych zmiennych i na przechowywanie w nich danych. Często stosowane jest to do określania poziomu detekcji dla danego typu zagrożeń, tu chcemy wykryć podejrzane manipulacje parametrem id:
SecRule ARGS:id "@gt 5" "pass, t:none,t:length, tx.anomaly_score=+5" SecRule ARGS:id "!@rx ^[0-9]*$ " "pass, t:none,t:length, tx.anomaly_score=+5" SecRule TX:anomaly_score „@gt 5” „deny,log,msg: 'Podejrzana wartość parametru id'– znaki inne niż cyfry i więcej znaków niż 5'”
W wielu przypadkach – gdy chcemy budować reguły, w których musi zostać spełnione kilka warunków jednocześnie, należy użyć operatora chain. Ostatnia reguła w łańcuchu nie posiada już operatora chain. Dla przejrzystości zapisu, warto stosować wcięcia tekstu dla połączonych ze sobą reguł.
SecRule REQUEST_URI „/admin” „chain, deny, msg:'Próba logowania do panelu administratora z nieprzeznaczonych do tego adresów IP, po godzinie 16” SecRule REMOTE_ADDR „!@rx ^192\.168\.1\.[10-20]” „chain” SecRule TIME_HOUR „@gt 16”
ModSecurity domyślnie stosuje wyrażenia regularne (@rx) w celu dopasowania reguł. Implementacja tych wyrażeń odpowiada składni języka Perl. Inne sposoby dopasowania reguł do zawartości zapytań/odpowiedzi HTTP to stosowanie dopasowania łańcuchów znaków (bardziej precyzyjne, ale mniej uniwersalne rozwiązanie), a do dyspozycji twórcy przewidzieli następujące operatory: @beginsWith, @contains, @containsWord, @endsWith, @streq, @within.
Specyfika protokołu HTTP powoduje, że te same efekty można osiągnąć, używając różnych wartości w zapytaniach. Fakt ten jest podstawą stosowania przez atakujących różnego rodzaju technik omijających filtry. Najprostsze sposoby, to przesłanie wartości parametrów zapisanych wielkimi literami np. SCRIPT zamiast script.
Bardziej zaawansowane techniki to dodawanie znaków ucieczki „\”, kodowanie base64 lub URL, dodawanie białych znaków lub komentarzy, np. SEL/**/ECT.
W celu normalizacji wartości z zapytań HTTP, w ModSecurity stosowane są funkcje transformujące definiowane w polu Action i poprzedzone operatorem „t:”. W tym polu można zastosować kilka takich funkcji transformujących zapytanie.
SecRule ARGS "@rx (?i)^php://" \ "phase:2,t:none, t:base64Decode, t:lowercase,msg:'Wstrzyknięcie zakodowanego w base64 PHP streams'"
Użycie t:none czyści wcześniejsze funkcje transformujące.
Dla zwiększenia wydajności przetwarzania reguł, których zapytanie musi być porównane z dużą liczbą wzorców, warto stosować pattern matching – operator @pm lub @pmFromFile (wzorce zapisane są w osobnym pliku).
SecRule REQUEST_HEADERS:User_Agent „@pmFromFile /usr/share/modsecurity_extras/known_web_scanners.txt” „deny, msg: 'blokowanie webowych skanerów podatności na podstawie wartości User_Agent z nagłówka'”
Na podstawie zasad określonych przez OWASP wyróżnia się sześć faz procedury wirtualnego „patchowania”, są to:
W poszczególnych fazach realizowane są poniższe czynności.
Faza przygotowania obejmuje następujące zagadnienia:
Faza identyfikacji związana jest z poszukiwaniem i uzyskaniem informacji o podatności występującej w używanej aplikacji webowej. Rozróżnia się dwa podejścia:
W czasie analizy należy:
Wirtualna poprawka musi spełniać dwie podstawowe reguły:
Wirtualne poprawki mogą być budowane ręcznie zgodnie z dwoma modelami:
Wirtualne poprawki mogą być również generowane automatycznie na podstawie raportów o podatnościach w formacie XML za pomocą :
Po zaimplementowaniu reguły ModSecurity mającej wirtualnie załatać podatność w aplikacji webowej, należy przetestować, czy WAF poprawnie loguje (ale jeszcze nie blokuje, aby uniknąć fałszywych alarmów) ataki za pomocą znanych payloadów oraz wykorzystując techniki omijania filtrów WAF/IDS.
Stosowane mogą być następujące narzędzia:
Ostatnia faza cyklu wirtualnej poprawki to nadzór. W ramach tej fazy należy zaktualizować informacje w systemie śledzenia błędów, a w szczególności zgłosić potrzebę załatania podatności w kodzie źródłowym. Po wprowadzeniu nowej, poprawionej wersji oprogramowania można wycofać wirtualną poprawkę z WAF lub zachować ją w celu lepszej agregacji informacji bezpieczeństwa o próbach wykorzystania tej podatności i przygotowania odpowiednich raportów na temat skuteczności działań obronnych – za pomocą procedury wirtualnego „patchowania”.
Poniżej zostaną przedstawione scenariusze przygotowania wirtualnych poprawek dla podatnych aplikacji.
Atak Blind SQLi przez kontrolę parametru, względem którego sortowane są kolumny w zapytaniu bazodanowym (wyrażenie ORDER BY).
Podatność ta nagminnie występuje w wielu różnych pluginach do WordPressa.
Podatny jest parametr orderby w zapytaniu GET, przykład plugin SEO by YEOST wersja 1.7.3.3 (disclosure: 11.03.2015). Pomimo zastosowania prób filtracji – złe użycie funkcji esc_sql() – atakujący jest w stanie wykonać atak Blind SQL injection:
$orderby = ! empty( $_GET['orderby'] ) ? esc_sql( sanitize_text_field( $_GET['orderby'] ) ) : 'post_title';
$orderby = $this->sanitize_orderby( $orderby );
(...)
$query = "
SELECT ID, post_title, post_type, post_status, post_modified, post_date
FROM {$subquery}
WHERE post_status IN ({$all_states}) $post_type_clause
ORDER BY {$orderby} {$order}
LIMIT %d,%d
Po wartości parametru orderby=post_date (sortowanie po dacie postu), atakujący jest w stanie przez dodanie znaku przecinka „ ,” (%2C w notacji URL) dołączyć payload BlindSQLi, który zostanie przekazany do bazy danych.
&orderby=post_date%2C(select+*+from+(select(sleep(3)))a)
Odpowiednia filtracja danych przekazywanych w parametrze orderby jest w stanie powstrzymać wstrzyknięcie kodu i kontrolę nad zapytaniem bazodanowym. W tym przykładzie zastosujemy transformacje: dekodowania znaków w notacji URL do filtrowania znaku przecinka oraz łańcuch reguł, aby jednoznacznie zlokalizować podatne miejsce w aplikacji.
SecRule REQUEST_FILENAME "/admin.php" "phase:2, t:none, t:normalisePath, t:lowercase, t:urlDecodeUni, chain, deny, log, id:1001" SecRule ARGS_GET:orderby "," "t:urlDecode"

Rysunek 2. Powstrzymanie przez ModSecurity ataku BlindSQLi.
Alternatywnie można zastosować podejście positive security, w którym tylko dopuszczone nazwy kolumn mogłyby być przekazane do zmiennej orderby i druga część reguły wyglądałaby następująco:
SecRule ARGS_GET:orderby "!^((post_date)|(post_type)|(post_title)) "t:none"
Tylna furtka umożliwiająca upload PHP shell w pluginie Premium SEO Pack 1.8.0 do WordPressa (disclosure: 24.04.2015).
Klasa abmRemoteSupport umożliwia udzielenie zdalnej pomocy klientom, jednakże wymagany do uwierzytelnienia „klucz serwisowy” jest na stałe zapisany w kodzie źródłowym dodatku.

Rysunek 3. Fragment kodu klasy abmRemoteSupport z zaszytym „backdoorem” Atak RemoteKey.
Źródło: https://wpvulndb.com/vulnerabilities/7934.
Atakujący po analizie kodu źródłowego plugina Premium SEO Pack 1.8.0, jest w stanie przygotować zapytanie POST odwołujące się do zasobu plugins/premium-seo-pack/modules/remote_support/remote_tunnel.php, podając w parametrze connection_key wartość 69efc4922575861f31125878597e97cf, a w pozostałych parametrach – przykładowe wartości przedstawione na poniższym zrzucie.

Rysunek 4. Umieszczenie PHP shell na serwerze przez “tylną furtkę” w oprogramowaniu.
Po przesłaniu takiego requestu POST atakujący umieścił własny skrypt typu PHP shell, zakodowany w base64, i jest w stanie wykonywać zdalnie polecenia systemu operacyjnego z prawami właściciela procesu serwera webowego (RCE – remote code execution).

Rysunek 5. PHP shell zakodowany w base64.
Ponieważ SEO niestety często ma znacznie wyższy priorytet biznesowy niż bezpieczeństwo, często również nie ma możliwości wycofania plugina lub zgody na modyfikację jego kodu. Rozwiązaniem pozostaje wirtualne załatanie przez blokadę możliwości udzielenia „zdalnej pomocy” przez podmioty zewnętrzne.
Zastosowane zostanie podejście negative security – blokowane będą zapytania POST do zasobu remote_tunnel.php zawierające ciąg znaków klucza serwisowego connection_key. Podejście to zapewni zgodność z zasadami, według których nie może dojść zarówno do fałszywego alarmu, jak i fałszywego odrzucenia.
SecRule REQUEST_FILENAME "/remote_tunnel.php" "phase:2, t:none, t:normalisePath, t:lowercase, t:urlDecodeUni, chain, deny, log, id:1002" SecRule ARGS_POST:connection_key "69efc4922575861f31125878597e97cf" "t:none" Fragment logu modsec_audit.log --a1521748-H-- Message: Access denied with code 403 (phase 2). Pattern match "69efc4922575861f31125878597e97cf" at ARGS_POST:connection_key. [file "/etc/modsecurity/modsecurity_custom_rules.conf"] [line "4"] [id "1002"] Action: Intercepted (phase 2)
Aplikacja webowa jest podatna na wstrzyknięcie polecenia systemu operacyjnego, na którym jest uruchomiona – OS injection, brak jest odpowiedniego filtrowania danych wejściowych do aplikacji.
Podatność występuje w lokalizacji /webapp/analyse, a podatny jest parametr input w zapytaniu POST. Brak kodów źródłowych, kod napisany w języku Python został skompilowany. Wartości parametru input są kodowane base64. Z analizy aplikacji webowej wynika, że parametr ten do poprawnego działania aplikacji powinien przyjmować wyłącznie znaki alfanumeryczne do [a–z] lub [A–Z].
Atakujący za pomocą znaków kontrolnych wiersza poleceń w systemie LINUX < ` & | > jest w stanie przekazać do aplikacji komendę, która zostanie wykonana z prawami właściciela procesu serwera WWW. Podatność ta może posłużyć do umieszczenia tylnej furtki lub eskalacji uprawnień do użytkownika uprzywilejowanego, i w konsekwencji – pełnego przejęcia serwera.
&input=c2VrdXJha1ppbmU= base64decode(„c2VrdXJha1ppbmU=”) == sekurakZine &input=c2VrdXJha1ppbmV8aWQ= base64decode(„c2VrdXJha1ppbmV8aWQ=”) == sekurakZine|id
Po przeprowadzonym teście penetracyjnym stwierdzono występowanie opisanej podatności. Aplikacja jest częścią systemu krytycznego i nie może być wyłączona ani zaktualizowana bez odpowiednich testów poprawek kodu, co jednak może narazić aplikację na poważne w skutkach ataki typu RCE.
Zastosowane zostanie podejście positive security, zgodnie z którym ModSecurity będzie dopuszczał wyłącznie znaki alfanumeryczne z ograniczonego zbioru, co nie pozwoli przekazać znaków umożliwiających wstrzyknięcie komend wiersza poleceń LINUX. Jednak, z uwagi na kodowanie parametrów za pomocą base64, należy wcześniej znormalizować zapytanie, do czego służy transformacja base64decode na poziomie ModSecurity. Dopiero po odkodowaniu zapytania WAF analizuje, czy przekazane w parametrze input dane są zgodne z białą listą dopuszczonych znaków.
SecRule REQUEST_URI “/webapp/analyse” “phase:2, t:none, t:normalisePath, t:lowercase, t:urlDecodeUni, chain, deny, log, id:1003” (rysunek 6).

Rysunek 6. Zablokowanie ataku OS command injection.
SecRule ARGS_POST:input "!@rx ^[a-zA-Z]*$" "t:base64decode"
Log ModSecurity modsec_audit.log to kopalnia wiedzy, jednak łatwo też popaść w efekt przytłoczenia informacją.
Warto skorzystać z kilku rozwiązań, które pozwolą odfiltrować z tego logu niezbędne informacje o zdarzeniach bezpieczeństwa.
AuditViewer – aplikacja desktopowa (JAVA) do analizy logów, a także do ponownego wysyłania zmodyfikowanych zapytań w celu testowania zbioru reguł (rysunek 7).

Rysunek 7. Dane z logu modsec_audit.log zobrazowane w Audit Viewer.
Źródło: https://jwall.org/web/audit/viewer.jsp.
ModSecurity for Splunk – dodatek do Splunk prezentujący dane w formie tabelarycznej i graficznej (rysunek 8).

Rysunek 8. Aplikacja ModSecurity jako dodatek do Splunk. Źródło: https://splunkbase.splunk.com/app/880/.
Remo Rule editor – edytor reguł, projekt z 2007 (nierozwijany), rysunek 9.

Rysunek 9. Edytor do budowy reguł ModSecurity. Źródło: https://www.netnea.com/cms/remo-a-rule-editor-for-modsecurity/.
Stosowanie procedury wirtualnych poprawek buduje kolejną warstwę bezpieczeństwa w podejściu „defense in depth”, która jest w stanie skutecznie powstrzymać atak na infrastrukturę. Wirtualna łata umożliwia redukcję ryzyk związanych z exploitami typu 0-day. Za pomocą takich opensourcowych narzędzi jak ModSecurity, obrońcy są w stanie realizować ochronę aplikacji o zamkniętym kodzie. Szczególnie warto rozważyć wdrożenie w swoich organizacjach opracowanej przez OWASP procedury stosowania wirtualnych poprawek i wkomponować ją w cykl zarządzania bezpieczeństwem.
–Bartosz Jerzman
Kiedyś jeden z bardziej znanych dostawców hostingu w Polsce pochwalił się że jako pierwszy wprowadził mod_security dla wszystkich klientów. Zrobił to aż tak dobrze, że przez kilka dni nie działały skrypty mające formularz logowania z polami “username” i “password”…
Jako dodatek może być dobry, ale raczej nie jako pojedyncze narzędzie. Bardzo rozbudowany artykuł, duża ilość wiedzy i potrzebnych informacji. Pozdrawiam
Do części o zobrazowaniu logu modsecurity warto wspomnieć o Logstash+ElasticSearch+Kibana (ELK) oraz https://bitsofinfo.wordpress.com/2013/09/19/logstash-for-modsecurity-audit-logs/