Password Spray

Wer heute Dienste im Internet bereit stellt und natürlich eine Authentifizierung anfordert, muss damit rechnen, dass auch kriminelle Personen diesen Zugang ausprobieren. Das kann dann auch dazu führen, dass Konten wegen zu vielen Fehlversuchen gesperrt werden (Siehe DoS mit Account Lockout und Account Lockout durch AzureVM) oder ganz modern ist das durchprobieren verschiedener bekannter Kombinationen aus Benutzernamen und Kennwort in der Hoffnung ein System zu finden. Ich bin sicher, dass Webhoster mit ganz vielen Kunden damit konfrontiert sind. Aber dass es auch eine kleine Umgebung erwischt, ist neu.

Alarm durch AzureATP

Durch die Installation von Azure ATP auf meinen Domain Controllern werden u.a. auch die Anmeldeprotokolle überwacht. Sobald also hier sehr viele "fehlerhafte Anmeldungen" aufschlagen, kann das recht einfach erkannt werden. So kam dann eines Tages folgende Mail in meinem Postfach an:

Es scheint so, dass hier ein Windows-Client versucht sich anzumelden und über die AzureATP-Konsole konnte ich nach der Anmeldung auch die Details sehen:

Die Versuche habe da schon 22 Minuten gedauert und waren immer noch aktiv. In Panik musste ich aber erst mal nicht fallen, da es ja nur Versuche und keine Erfolge sind. Es ist doch eher unwahrscheinlich, dass hier ein Erfolg zu erwarten ist. Vor allem, wenn man die Liste der verwendeten Benutzernamen sich anschaut. Ich habe sie hier mal abgelegt:

password_spray-userliste.txt

Wenn ich mit die Strings in der Datei anschaue, dann sieht das eher nach einer Kennwortliste aus. Sollte der Angreifer tatsächlich so blöde sein und Kennworte als "Username" zu verwenden?

Der Angreifer hat sich also nicht mal die Mühe gemacht, irgendwelche sinnvollen Benutzernamen z.B. aus den öffentliche bekannten Mailadressen herzuleiten. Insofern ist das Risiko hier nur gegeben, wenn ein Anwender seine Zugangsdaten (Benutzername und Kennwort) auch bei einem anderen Service verwendet und diese dort abhanden gekommen sind und der Angreifer dann zufällig ein Pärchen findet.

Eventlog des DCs

Dennoch war ich natürlich neugierig und habe im Security Eventlog des meldenden DomainControllers auch die entsprechenden Einträge gefunden. Hier ein Beispiel:

Log Name: Security
Source: Microsoft-Windows-Security-Auditing
Date: 25.09.2019 21:46:12
Event ID: 4776
Task Category: Credential Validation
Level: Information
Keywords: Audit Failure
User: N/A
Computer: DC02.uclabor.de
Description:
The computer attempted to validate the credentials for an account.

Authentication Package: MICROSOFT_AUTHENTICATION_PACKAGE_V1_0
Logon Account: dreams
Source Workstation: WIN-4TV3LPVFJI2
Error Code: 0xC0000064
Event Xml:
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
<System>
<Provider Name="Microsoft-Windows-Security-Auditing" Guid="{54849625-5478-4994-A5BA-3E3B0328C30D}" />
<EventID>4776</EventID>
<Version>0</Version>
<Level>0</Level>
<Task>14336</Task>
<Opcode>0</Opcode>
<Keywords>0x8010000000000000</Keywords>
<TimeCreated SystemTime="2019-09-25T19:46:12.148389300Z" />
<EventRecordID>6614123</EventRecordID>
<Correlation />
<Execution ProcessID="528" ThreadID="4416" />
<Channel>Security</Channel>
<Computer>DC02.uclabor.de</Computer>
<Security />
</System>
<EventData>
<Data Name="PackageName">MICROSOFT_AUTHENTICATION_PACKAGE_V1_0</Data>
<Data Name="TargetUserName">dreams</Data>
<Data Name="Workstation">WIN-4TV3LPVFJI2</Data>
<Data Name="Status">0xc0000064</Data>
</EventData>
</Event>

Wenn Sie genau reinschauen, gibt es hier aber außer dem Client-Namen keine weiteren Quellen. Insbesondere eine IP-Adresse, von der der Authentiation-Requests gestellt wurde, ist hier nicht sichtbar.

DC02: C:\Windows\debug\netlogon.log

Aber ich habe ja schon etwas Erfahrung mit dem Nachtracken von Anmeldungen. Weitere Details finden Sie auf DoS mit Account Lockout, Account Lockout mit Docker und Account Lockout durch AzureVM. Natürlich ist auf dem Server auch das "NETLOGON-Debugging" aktiv und dort findet sich

09/25 21:46:12 [LOGON] [4416] UCLABOR: SamLogon: Transitive Network logon of (null)\dreams from WIN-4TV3LPVFJI2 (via EX01) Entered
09/25 21:46:12 [LOGON] [4416] UCLABOR: NlPickDomainWithAccount: dreams: Algorithm entered. UPN:0 Sam:1 Exp:0 Cross: 0 Root:1 DC:0
09/25 21:46:12 [LOGON] [4416] UCLABOR: SamLogon: Transitive Network logon of (null)\dreams from WIN-4TV3LPVFJI2 (via EX01) Returns 0xC0000064

Der Text "Via EX01" sagt mir, dass die Anforderung zur Verifikation über den Server EX01 angekommen ist. Also nichts wie los zu dem Server.

Eventlog des EX01

Auch hier gilt mein erster Blick ins Eventlog und natürlich werde ich auch hier fündig:

Log Name: Security
Source: Microsoft-Windows-Security-Auditing
Date: 25.09.2019 21:46:12
Event ID: 4776
Task Category: Credential Validation
Level: Information
Keywords: Audit Failure
User: N/A
Computer: EX01.uclabor.de
Description:
The computer attempted to validate the credentials for an account.

Authentication Package: MICROSOFT_AUTHENTICATION_PACKAGE_V1_0
Logon Account: dreams
Source Workstation: WIN-4TV3LPVFJI2
Error Code: 0xC0000064
Event Xml:
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
<System>
<Provider Name="Microsoft-Windows-Security-Auditing" Guid="{54849625-5478-4994-A5BA-3E3B0328C30D}" />
<EventID>4776</EventID>
<Version>0</Version>
<Level>0</Level>
<Task>14336</Task>
<Opcode>0</Opcode>
<Keywords>0x8010000000000000</Keywords>
<TimeCreated SystemTime="2019-09-25T19:46:12.114074200Z" />
<EventRecordID>3867753299</EventRecordID>
<Correlation />
<Execution ProcessID="572" ThreadID="24192" />
<Channel>Security</Channel>
<Computer>EX01.uclabor.de</Computer>
<Security />
</System>
<EventData>
<Data Name="PackageName">MICROSOFT_AUTHENTICATION_PACKAGE_V1_0</Data>
<Data Name="TargetUserName">dreams</Data>
<Data Name="Workstation">WIN-4TV3LPVFJI2</Data>
<Data Name="Status">0xc0000064</Data>
</EventData>
</Event>

Der Status "0xc0000064" besagt nur, dass der Benutzer nicht gefunden wurde, was ja auch richtig ist. Zu jedem dieser Events gehört auf dem Server aber noch ein zweiter Event:

Log Name: Security
Source: Microsoft-Windows-Security-Auditing
Date: 25.09.2019 21:46:12
Event ID: 4625
Task Category: Logon
Level: Information
Keywords: Audit Failure
User: N/A
Computer: EX01.uclabor.de
Description:
An account failed to log on.

Subject:
Security ID: NULL SID
Account Name: -
Account Domain: -
Logon ID: 0x0

Logon Type: 3

Account For Which Logon Failed:
Security ID: NULL SID
Account Name: dreams
Account Domain: 

Failure Information:
Failure Reason: Unknown user name or bad password.
Status: 0xC000006D
Sub Status: 0xC0000064

Process Information:
Caller Process ID: 0x0
Caller Process Name: -

Network Information:
Workstation Name: WIN-4TV3LPVFJI2
Source Network Address: -
Source Port: -

Detailed Authentication Information:
Logon Process: NtLmSsp 
Authentication Package: NTLM
Transited Services: -
Package Name (NTLM only): -
Key Length: 0

This event is generated when a logon request fails. It is generated on the computer where access was attempted.

The Subject fields indicate the account on the local system which requested the logon. This is most commonly a 
  service such as the Server service, or a local process such as Winlogon.exe or Services.exe.

The Logon Type field indicates the kind of logon that was requested. 
  The most common types are 2 (interactive) and 3 (network).

The Process Information fields indicate which account and process on the system requested the logon.

The Network Information fields indicate where a remote logon request originated. Workstation name is not 
  always available and may be left blank in some cases.

The authentication information fields provide detailed information about this specific logon request.
- Transited services indicate which intermediate services have participated in this logon request.
- Package name indicates which sub-protocol was used among the NTLM protocols.
- Key length indicates the length of the generated session key. This will be 0 if no session key was requested.
Event Xml:
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
<System>
<Provider Name="Microsoft-Windows-Security-Auditing" Guid="{54849625-5478-4994-A5BA-3E3B0328C30D}" />
<EventID>4625</EventID>
<Version>0</Version>
<Level>0</Level>
<Task>12544</Task>
<Opcode>0</Opcode>
<Keywords>0x8010000000000000</Keywords>
<TimeCreated SystemTime="2019-09-25T19:46:12.114074200Z" />
<EventRecordID>3867753300</EventRecordID>
<Correlation />
<Execution ProcessID="572" ThreadID="24192" />
<Channel>Security</Channel>
<Computer>EX01.uclabor.de</Computer>
<Security />
</System>
<EventData>
<Data Name="SubjectUserSid">S-1-0-0</Data>
<Data Name="SubjectUserName">-</Data>
<Data Name="SubjectDomainName">-</Data>
<Data Name="SubjectLogonId">0x0</Data>
<Data Name="TargetUserSid">S-1-0-0</Data>
<Data Name="TargetUserName">dreams</Data>
<Data Name="TargetDomainName">
</Data>
<Data Name="Status">0xc000006d</Data>
<Data Name="FailureReason">%%2313</Data>
<Data Name="SubStatus">0xc0000064</Data>
<Data Name="LogonType">3</Data>
<Data Name="LogonProcessName">NtLmSsp </Data>
<Data Name="AuthenticationPackageName">NTLM</Data>
<Data Name="WorkstationName">WIN-4TV3LPVFJI2</Data>
<Data Name="TransmittedServices">-</Data>
<Data Name="LmPackageName">-</Data>
<Data Name="KeyLength">0</Data>
<Data Name="ProcessId">0x0</Data>
<Data Name="ProcessName">-</Data>
<Data Name="IpAddress">-</Data>
<Data Name="IpPort">-</Data>
</EventData>
</Event>

Es war also eine "Netzwerkanmeldung" mittels NTLM und wenn man diese Eventlogs genauer anschaut, dann sieht man sie zeitliche Abfolge. Ca. alle 10 Sekunden wird eine Anmeldung versucht. Die Rate wird vermutlich absichtlich so niedrig gesetzt sein, damit Überwachungsprogramme nicht direkt hellhörig werden.

Ich habe dann per PowerShell die Eventlogs ausgelesen und bin auf 290 Anmeldeversuchen über einen Zeitraum von ca. 50 Minuten gekommen. Danach haben die Versuche wieder aufgehört. Ich wollte aber schon wissen. wo die Ursache ist.

EX01 NETLOGON

Als habe ich auf dem EX01 auch das NETLOGON-Debuglog gesucht aber leider nicht gefunden. Das Debugging ist per Default nämlich ausgeschaltet. Ich habe es also erst einmal eingeschaltet und muss hier nun auf den nächsten Angriff warten.

nltest /dbflag:0x2080ffff

Ich habe aber manuell mal eine falsche Anmeldung einfach per OWA produziert und der Versuch wird hier protokolliert:

09/25 22:43:06 [MISC] [18096] DsGetDcName function called: client PID=4280, Dom:uclabor.de Acct:dummyuser Flags: IP KDC 
09/25 22:43:06 [MISC] [18096] NetpDcGetName: uclabor.de cache doesn't have right account name.
09/25 22:43:06 [CRITICAL] [18096] NetpDcHandlePingResponse: uclabor.de: dummyuser: response says specified account not found.
09/25 22:43:06 [CRITICAL] [18096] NlPingDcNameWithContext: No such user dummyuser on dc02.uclabor.de.
09/25 22:43:07 [CRITICAL] [18096] NetpDcHandlePingResponse: uclabor.de: dummyuser: response says specified account not found.
09/25 22:43:07 [CRITICAL] [18096] NetpDcHandlePingResponse: uclabor.de: dummyuser: response says specified account not found.
09/25 22:43:07 [CRITICAL] [18096] NetpDcHandlePingResponse: uclabor.de: dummyuser: response says specified account not found.
09/25 22:43:08 [MISC] [18096] DsGetDcName function returns 1317 (client PID=4280): Dom:uclabor.de Acct:dummyuser Flags: IP KDC 

Der Exchange Server bzw. der Netlogon-Dienst versucht gleich mehrere DCs mehrfach aber bekommt immer ein "response says specified account not found" zurück. Soweit also auch in Ordnung. Leider steht hier aber weder eine IP-Adresse noch der auslösende Prozess drin. Also muss ich weiter schauen.

EX02: IISlog (Sackgasse)

Ich habe natürlich zuerst an den IIS gedacht, denn der Exchange Server ist über HTTPS aus dem Internet erreichbar. Das Zeitfenster der Angriffe hatte ich und so konnte ich die IISLogs schnell sichern

Tipp: Sie können im IISLog die ersten drei Zeilen einfach löschen und aus der vierten Zeile mit dem Header das führende "#". Dann lassen sich die Loft mit import-csv -delimiter " " sehr einfach parsen

# Vorher die Datei für Import-CSV schick machen.
$iislog = Import-Csv .\20190925-passwordspray-iis.log -Delimiter " "

Wenn ich die Daten in einer Variable habe, dann spare ich mir das wiederholte importieren. Das sollten Sie aber nicht mit allzu großen Dateien machen oder am besten nicht auf dem Exchange Server selbst

Zuerst habe ich mir die IIS-Error-Codes angeschaut, ob es viele 401 (Auth Required) oder 403 (forbidden) gibt.

# IIS Codes auflisten
$iislog | group sc-status

Count Name
----- ----
 3928 200
  308 401
  399 0
  180 302
    4 500
    5 404

Es gab keinen einzigen 403 aber schon ein paar 401-Fehler, die man etwas anschauen könnte. Über PowerShell geht das dann einfach.

PS C:\Temp> $iislog | where {$_.'sc-status' -eq '401'} | group cs-uri-stem -NoElement | ft -AutoSize

Count Name
----- ----
   47 /mapi/emsmdb/
  137 /autodiscover/autodiscover.xml
  120 /rpc/rpcproxy.dll
    4 /api

Hier ist aber schon zu sehen, dass man so nicht weiter kommt. So kann ich mir nur die 290 Anmeldeversuche erklären. Ich habe dann erst einmal selbst "Bösewicht" gespielt und mich von extern mit einem ungültigen Benutzernamen angemeldet. Die Requests in Fiddler waren:

Damit ist klar, dass ich keine 401/403-Fehler sehe, denn hier kommt gar keine IIS-Authentifizierung zustande. Die OWA-Anmeldeseite ist ein Formular, welche die Anmeldedaten per "FORM POST" an Exchange übermittelt. Und da der Exchange Server hinter einem "echten" Reverse Proxy steht, konnte ich auch per Auswertung der Client-IPs nicht mehr Informationen gewinnen.

$iislog

IIS ClientIPs "c-ip"
Count Name
----- ----
 3166 192.168.1.59
   80 192.168.1.33
  412 fe80::ecaa:7119:4be6:4...
  372 192.168.1.1
  463 ::1
  331 127.0.0.1

Wohl dem, der seinem Proxy beigebracht hat, die originale Client-IP z..B in das Feld "X-Forwarded-For" zu schreiben und im IISlog dieses Feld mit protokollieren lässt.

Das sind ganz viele interne Adressen und natürlich die Firewall (192.168.1.1). Also habe ich die URLs von der Firewall angeschaut.

PS C:\> $iislog | where {$_.'c-ip' -eq '192.168.1.1'} | group cs-uri-stem -NoElement | ft -AutoSize

Count Name
----- ----
  112 /mapi/emsmdb/
  142 /autodiscover/autodiscover.xml
  104 /Microsoft-Server-ActiveSync/default.eas
    5 /autodiscover/autodiscover.json
    9 /api

Das hilft auch nicht weiter. Hier gab es in der fraglichen Zeit gar keine Zugriffe auf "/owa/auth.owa".

Das habe ich aber schon erwartet, da man per Exchange OWA und FBA kein NTLM nutzen kann, bei dem man einen Client Computer Name übermittelt. Das wäre dann eher für EWS eine Option

SMTP-Logs

Der Server war neben HTTP nur noch per SMTP erreichbar. Hier kann aber eine Anmeldung per NTLM erfolgen und daher habe ich die SMTPReceive Logs des Exchange Servers angeschaut. Schon allein an der Dateigröße ist bei meinem "wenig genutzten" Server zu sehen, dass hier was passiert sein könnte.

Bei einem Server mit mehr Volumen wird das Erkennen natürlich nicht mehr so einfach möglich sein. Im Log zeigen sich dann schnell zwei Angriffsmuster:

>,"220 ex01.uclabor.de Microsoft ESMTP MAIL Service ready at Wed, 25 Sep 2019 21:02:22 +0200",
<,EHLO WIN-4TV3LPVFJI2,
>,250  ex01.uclabor.de Hello [185.208.211.135] SIZE 37748736 PIPELINING DSN ENHANCEDSTATUSCODES STARTTLS X-A
<,AUTH ntlm,
>,334 <authentication response>,
*,,Inbound Negotiate failed because of LogonDenied
*,,User Name: NULL
*,Tarpit for '0.00:00:05' due to '535 5.7.3 Authentication unsuccessful',
>,535 5.7.3 Authentication unsuccessful,
,<,MAIL FROM:<3vrgfqblaepzfoieznbfntmrpqyix@uclabor.de>,
,*,08D73E90EFB1C670;2019-09-25T19:02:22.962Z;1,receiving message
,>,250 2.1.0 Sender OK,
,<,RCPT TO:<martinlujan997@gmail.com>,
,*,Tarpit for '0.00:00:05' due to '550 5.7.54 SMTP; Unable to relay recipient in non-accepted domain',
,>,550 5.7.54 SMTP; Unable to relay recipient in non-accepted domain,
,-,,Remote(SocketError)

Einmal versucht der Client (185.208.211.135), der hier wohl in Indien steht, sich per NTLM anzumelden, was aber misslingt. Dass er 5 Sekunden auf diese Meldung warten muss, hindert ihn aber nicht daran trotz fehlerhafter Anmeldung mit genau dem Usernamen gefolgt von der SMTP-Domain eine Mail zu starten. Auch die wird natürlich aufgrund der Relay-Konfiguration abgewiesen. Der Angreifer wartet dann aber nicht mehr und beendet den Socket aktiv um dann 12 Sekunden später wieder eine neue Verbindung nach dem gleichen Muster aufzubauen.

Schutz anpassen

In dem Fall war es ganz klar der Zugang per SMTP, der hier aber nicht erfolgreich missbraucht werden konnte. Aber es ist schon zu überlegen, wie der Schutz verbessert werden kann. Sie könnten z.B. das "Tarpit"-Intervall von Exchange einfach etwas höher als die 5 Sekunden setzen. Gute Clients verhalten sich korrekt und melden sich sauber an oder versuchen den Server nicht als Relay zu missbrauchen. Dumm nur, wenn Sie das Intervall auf z.B. 30 Min gestellt haben und es doch mal ihren eigenen Service erwischt. Das lässt sich dann aber über mehrere Receive-Connectoren lösen, indem nur die von unsicheren Netzwerken erreichbar Connectoren so scharf eingestellt werden.

Für andere Dienste müssen natürlich andere Gegenmaßnahme angewendet werden. Es gibt bei den meisten Firmen ja eine ganze Menge von Zugängen mit Authentifizierung, z.B.

  • Mobilgeräte mit ActiveSync
  • Outlook mit RPC/HTTP oder MAPI/HTTP
  • VPN/Dialin-Zugänge
  • Beliebige Webseiten (SharePoint, GIT, TFS, Confluence etc.
  • Terminal Server Gateway / Citrix Gateway

Für jedes System muss individuell geschaut, werden, wie Anmeldungen protokolliert und Missbrauch verhindert wird.

Bewertung

Ein echtes Risiko habe ich nicht erkannt, da der Mailserver kein offenes Relay war und auch keine gültigen Username/Kennwort-Kombinationen gefunden wurden. Insofern war die Meldung von AzureATP zwar nett aber auch nur mit dem Schweregrad "Mittel" versehen.

Angriffe dieser Art sind nicht neu und werden vermutlich nie aufhören. Dazu sind Bandbreite und Rechenleistung zu günstig und es wird immer Dienste geben, die über das Internet erst nach vorheriger Authentifizierung erreichbar sind. Das ist auch der Grund, warum Conditional Access und Multi Faktor Authentifizierung (MFA) in aller Munde sind. Verhindern Sie doch den Zugriff durch nicht qualifizierte Endgeräte oder einen zusätzlichen Schutz für das Konto.

Durch die besseren Schutzmaßnahmen wie Tarpitting und Account Lockout können Angreifer nicht mehr viele Kennworte mit einem einzelnen bekannten Konto durchprobieren. Die Frage ist natürlich, wie Provider sich hier positionieren, wenn Sie ausgehende Mails auf Port 25 zulassen. Azure unterbindet das zurecht und auch hier scheint es sich um einen Windows 10 Desktop bei einem Hoster zu handeln, der vielleicht sogar per PowerShell versucht die Mails zu versenden.

Allerdings sollten Sie erkannt haben, dass eine angemessene Protokollierung und Eskalation von Vorgängen immer wichtiger wird. Es reicht nicht, wenn nur ein Domain Controller die fehlerhalten Anmeldungen überwacht. Damit wissen sie zwar an einer zentralen Stelle, dass Sie unter Beschuss stehen. Sie hören den Donner aber wissen noch nicht, woher er kommt. Es ist mehr als nur unschön, dass das Windows Eventlog auf dem DC oder zumindest auf dem Memberserver keine Informationen zur Client-IP und dem Service enthält. Das würde die Suche sicherlich vereinfachen.

Daher ist es so wichtig, die "Stadttore" zu überwachen, also der Eingänge" an vorderster Front hinsichtlich solcher Unregelmäßigkeiten. Neben der Überwachung könnten hier dann auch Abwehrstrategien angewendet werden. ADFS kennt z.B. die Funktion ADFS Extranet Lockout, um zu viele Fehlversuche bei einem Konto zu blockieren. Für Password Spay-Attacken könnte eine Filterung nach Quell-IP-Adresse helfen, um die Anmeldungen zu blockieren. Allerdings ist das deutlich schwerer, da Angreifer ja einfach ganz viele Endgeräte mit vielen IP-Adressen betreiben können.

Das Logging ist natürlich eine Steilvorlage für ein Logmanagement a wie Azure Sentinel, ELK-Stack, Splunk u.a., bei dem Logs zentral eingesammelt werden. Wenn Sie dann auf den verschiedenen Servern auch noch das Logging entsprechend einstellen und die Quellen (Eventlog, netlogon.log, SMTP-Logs, IISLogs, u.a.) hinzufügen, dann können manuell oder per Regeln solche Angriffe noch besser einschätzen.

Allein durch die Analyse dieses Threads habe ich natürlich wieder viele Log-Quellen mit Events gefunden, anhand denen das Enterprise Monitoring verbessert werden kann. Ich bin sicher, dass AzureATP mir auch in Zukunft immer mal wieder solche Alerts senden wird. Dann wäre es doch nett, wenn ich einfach so einen Benutzername aus einem Anmeldeversuch als Abfrage im Logmanagement eingebe und direkt sehe, wo dieser Eintrag überall aufgetreten ist.

Denken Sie aber daran, dass auch legitime Anwender manchmal ihren Benutzernamen oder Kennwort falsch eingeben. Hier sollten Sie dann nicht gleich mit der großen Keule gegenhalten und die Source-IP oder das AD-Konto blockieren. Auch eine Sparkasse oder Bank muss zwar ein Sicherheitsniveau erreichen aber dennoch muss es Türen für den Kundenkontakt geben. Auch wenn ein Bandräuber den gleichen Weg nutzen kann.

Weitere Links