Risiko eigene Webseite

Wir unterhalten und simmer über externe Angreifer, die in unser Netzwerk und unsere Systeme einbrechen wollen. Bei der Arbeit zum Artikel Autodiscover Sicherheit im Zuge der Autodiscover Guardicore-Veröffentlichung ist mit eine ganz andere Lücke aufgefallen, die ich lange nicht gesehen habe. Es ist meine eigene Webseite der eigenen Firma.

Wenn Sie eine Webseite mit ihrer Firmendomain betreiben, dann kann eine Lücke darauf zum Verlust von Zugangsdaten ihrer Benutzer führen.

Die Seite gilt nicht nur für Autodiscover sondern auch andere Dienste aber hat mit Autodiscover Guardicore Aktualität gewonnen.

www.firma.tld und firma.tld

Es gehört zum guten Ton, dass eine Firma auch eine Präsenz im Internet bereithält und historisch hat sich das Prefix "www." für "World Wide Web" etabliert. Die meisten Seiten nutzen auch heute noch das Schema "www.<firmendomain.tld>". Allerdings ist auch der Name ohne "www" davor ein gültiger Hostname. Die meisten Provider und Webhoster tragen beide Schreibweisen im DNS ein.

PS C:\> nslookup www.msxfaq.de

Name:    www.msxfaq.de
Addresses:  2a01:488:42:1000:b24d:7562:25:6783
          178.77.117.98

PS C:\> nslookup msxfaq.de

Name:    msxfaq.de
Addresses:  2a01:488:42:1000:b24d:7562:25:6783
          178.77.117.98

Wer zwei Namen auf einer Webseite betreibt, muss natürlich auch hinsichtlich HTTPS-Zertifikate Vorkehrungen treffen. Damit bei einer Verbindung per HTTPS keine Zertifikatwarnung kommt, sind beide Namen auch im Zertifikat hinterlegt.

Soweit ist das aus Sicht des Marketing ja noch alles in Ordnung.

Autodisover

Wenn Sie nun Outlook nutzen, dann haben Sie sicher schon etwas über Exchange - Autodiscover erfahren. Outlook nutzt verschiedene Wege, um den Weg zum Postfach möglichst automatisch zu finden. Im internen LAN ist das unkritisch, da Outlook per LDAP einen "Service Connection Point" (Autodiscover und SCP) ermittelt und den Exchange Server befragt. Kritisch sind aber externe Clients im Homeoffice ohne VPN, oder mobile Geräte. Die erhalten keinen SCP und starten dann ihre Namensauflösung. Ein Exchange Admin kennt dazu schon den DNS-Eintrag "Autodiscover.<maildomain>". Aber vor dieser Anfrage prüft ein Autodiscover-Client auch noch einmal die Stammdomäne ab.

Genau hier ist das Risiko, dass ein Client diese URL anspricht und dort eine falsche Antwort kommt.

HTTP-Antwort
Beschreibung Status

2xx, 3xx, 404, u.a.

All diese Codes werden von Outlook verstanden und wenn die Rückantwort keine gültige Autodiscover.xml enthält, dann geht Outlook einfach zum nächsten Punkt über. In den meisten Fällen wird der Client zu "https://autodiscover.<domain>" weiter gehen.

401.x

Dies ist die einzige Antwort, die Outlook an der Stelle stört oder gefährdet. Ein "401 Unauthorized" bringt Outlook dazu, eine Anmeldung zu starten. Wenn die Gegenseite eine "sichere Anmeldung" (z.B. "Negotiate" oder "NTLM") anbietet, dann sendet Outlook diese Daten automatisch oder erfragt diese vom Anwender. (Siehe Kennwortbox) Das stört aber erst einmal nur. Gefährlich wird es, wenn die Webseite eine "BasicAuth" o.ä. anbietet und der Anwender dann seine Zugangsdaten nur BASE64-codiert überträgt. Dann hat der Webserver die Daten.

Im letzten Fall (401) könnte eine kompromittierte eigene Webseite einen Anwender dazu verleiten, seine Anmeldedaten an den Server zu senden.

Nun denken Sie daran, wie viele "Firmenseiten" mit Wordpress und Plugins betrieben werden, die irgendwann gekapert werden könnten. Ein Angreifer dann dort einen Autodiscover-Service installieren, der Zugangsdaten einsammelt und den Client zum nächsten Service weiter leitet.

Aus dem Grund ist es durchaus zu überlegen, ob sie diese Funktion ihrer Domain-Webseite zu prüfen. Das geht per PowerShell 7 sehr einfach.

Invoke-WebRequest `
   -uri "https://msxfaq.de/autodiscover/autodiscover.xml" `
   -method POST

Natürlich müssen wir noch etwas mehr Code aufwenden, um die verschiedenen Fehlercodes abzufangen und vor allem den beim 401 gelieferten Authentication-Header zu prüfen und den passenden UserAgent samt etwas Payload zu senden. Wir wollen ja nicht, dass eine hinterlegte Malware dieses Prüfskript direkt erkennt und sich anders verhält.

# Aufruf der regulären Autodiscover-URL. hier ist der Status OK
PS C:\> .\test-autodiscoverauth.ps1  -url https://autodiscover.netatwork.de/autodiscover/autodiscover.xml
CRITICAL - 401 Found on URL https://autodiscover.netatwork.de/autodiscover/autodiscover.xml, Credential Phishing with Auth  possible!

# Aufruf der Webseite, wenn es keinen autodiscover-Eintrag gäbe.
PS C:\> .\test-autodiscoverauth.ps1 -url https://netatwork.de/autodiscover/autodiscover.xml
OK- Statuscode 404 on URL https://netatwork.de/autodiscover/autodiscover.xml. No Credential phishing

# Aufruf der autodiscover.de - hier sollte kein 401 kommen und seit das BSI die Seite hostet, ist das auch 
PS C:\> .\test-autodiscoverauth.ps1  -url https://autodiscover.de/autodiscover/autodiscover.xml
OK- Statuscode 404 on URL https://autodiscover.de/autodiscover/autodiscover.xml. No Credential phishing

#Aufruf einer Domain ganz ohne Autodiscover-Eintrag
PS C:\> .\test-autodiscoverauth.ps1  -url https://autodiscover.msxfaq.de/autodiscover/autodiscover.xml
UNKNOWN : SocketException: Der angegebene Host ist unbekannt. (autodiscover.msxfaq.de:443)

Sie sollten nun natürlich nicht die ganze Welt und viele Domains abfragen sondern die URls, die für ihre Maildomänen relevant sind. Bei den meisten Firmen ist das die eigene Webseite, die unter "https://<firmenname.tld>" erreichbar sein wird. Und da sollte nie ein 401 kommen.

Das Skript ist relativ überschaubar und man könnte die Basisfunktion vermutlich auch in noch weniger Zeilen pressen. Allerdings unterscheidet sich für PowerShell 5 und früher oder 7 und höher die Fehlerbehandlung.

# Test-AutodiscoverAuth
#
# Module to check the public web page against autodiscover-responses
# Results to STDOUT and Exitcode
# 0 – Status OK.
# 1 – WARNUNG.
# 2 – KRITISCH
# 3 – UNBEKANNT
# 
# 20211009 Initial Version

#Requires -Version 7

[CMDLetBinding()]

param (
   $url = "https://autodiscover.de/autodiscover/autodiscover.xml",
   $proxy = $null
)

$finalexitcode=0
[string]$finalmessage = ""
Write-Verbose "Test-Autodiscover: Start"

Write-Verbose "Test-Autodiscover: Start Invoke-WebRequest"
$error.clear()
[string]$WwwAuthenticate= "<not found>"
[int32]$httpstatuscode = -1
[string]$xmlbody='<?xml version="1.0" encoding="utf-8"?>
                     <Autodiscover xmlns="http://schemas.microsoft.com/exchange/autodiscover/outlook/requestschema/2006">
                        <Request>
                           <EMailAddress>test@example.com</EMailAddress>
                           <AcceptableResponseSchema>http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a</AcceptableResponseSchema>
                        </Request>
                     </Autodiscover>'

try {
   $autodresult = Invoke-WebRequest `
                        -uri $url `
                        -method POST `
                        -Headers @{'UserAgent' = 'Microsoft Office/16.0 (Windows NT 6.2; MAPI 16.0.13127; Pro)'} `
                        -Body $xmlbody `
                        -ContentType "text/xml" `
                        -SkipHttpErrorCheck `
                        -proxy $proxy 
   Write-Verbose "  Returned without error"
   $WwwAuthenticate = $autodresult.Headers.WwwAuthenticate
   $httpstatuscode = $autodresult.StatusCode
}
catch [System.Net.WebException] {
   # normal not triggered with -SkipHTTPErrorCheck
   Write-Verbose "Exception: WebException: $($_.Exception.Message)"
   $WwwAuthenticate = $_.Exception.Response.Headers.WwwAuthenticate
   $httpstatuscode = $_.Exception.Response.StatusCode.value__
} 
catch [System.Net.Sockets.SocketException] {
   Write-Verbose "Exception: SocketException: $($_.Exception.Message)"
   $finalmessage = "UNKNOWN : SocketException: $($_.Exception.Message)"
   $finalexitcode = [math]::max($finalexitcode,3)
}
catch {
   Write-Verbose "Exception: Other: $($_.Exception.Message)"
   $finalmessage = "UNKNOWN : OtherException: $($_.Exception.Message)"
   $finalexitcode = [math]::max($finalexitcode,3)
   $_
}

if ($finalmessage -eq "") {
   
   Write-Verbose " Result: WwwAuthenticate: $($WwwAuthenticate)"
   Write-Verbose " Result: httpstatuscode :$($httpstatuscode)"

   if ($httpstatuscode -eq 401) {
      Write-Verbose "401 found. parsing wwwauthenticat-header"
      if ($WwwAuthenticate -like "*basic*") {
         Write-Verbose "  BASIC found !"
         $finalmessage = "CRITICAL - 401 Found on URL $($url), Credential Phishing with BASIC AUTH possible!" 
         $finalexitcode = [math]::max($finalexitcode,2)
      }
      else {
         Write-Verbose "  BASIC NOT found"
         $finalmessage = "CRITICAL - 401 Found on URL $($url), Credential Phishing with Auth $($WwwAuthenticate) possible!" 
         $finalexitcode = [math]::max($finalexitcode,2)
      }
   }
   elseif ($httpstatuscode -eq 404) {
      Write-Verbose "  Found 404"
      $finalmessage = "OK- Statuscode 404 on URL $($url). No Credential phishing" 
      $finalexitcode = [math]::max($finalexitcode,0)
   }
   elseif ($httpstatuscode -le 0 ) {
      Write-Verbose "  No Status Code"
      $finalmessage = "UNKNOWN - No Status code. maybe no connection, proxy not working etc" 
      $finalexitcode = [math]::max($finalexitcode,3)
   }
   else {
      Write-Verbose "  Found $($httpstatuscode)"
      $finalmessage = "OK - Statuscode $($httpstatuscode) found on URL $($url)"
      $finalexitcode = [math]::max($finalexitcode,0)
   }
}
$finalmessage
Write-Verbose "Test-Autodiscover: End FinalExitCode:$($finalexitcode)"
exit $finalexitcode

Es steht ihnen natürlich frei, eine vergleichbare Logik in Perl, Python, als Bash-Shell mit CURL o.ä. Sprachen für ihr eigenes Monitoring zu erstellen.

Wichtig ist aus meiner Sicht nur, dass sie sehr schnell mitbekommen, wenn ihre "Werbe-Webseite" auf dem /Autodiscover-Pfad" plötzlich mit einem 401 antwortet.

AD-Domain und DNS

Es gibt sicher nicht wenige Firmen, deren lokale Active Directory den gleichen DNS-Namen hat, wie die Domäne im Internet. Es gibt sogar Firmen, die früher eine nicht benutze Top-Level-Domain verwendet haben, z.B. "firma.ads". ADS war als Abkürzung für Active Directory Services gedacht. Allerdings gibt es mittlerweile eine ADS-Root-Domain, die Google eingerichtet hat. ADS = Advertising (Werbung). Ganz schlimm sind Firmen dran, die intern eine Domain nutzen, die im Internet einer anderen Firma gehört. Auch das gibt es leider, weil man früher einen noch nicht belegten Namen verwendet hat und eigentlich nicht erwartet hat, dass jemand anderes diese Domain je registriert.

Firmen, die intern und extern die gleiche DNS-Domäne verwenden, müssen sich über "Split-DNS" und Proxy-Konfiguration Gedanken machen, damit auch interne Clients die externen Dienste erreichen. Auf der anderen Seite ist es gerade ideal, wenn Dienste unter dem gleichen Namen erreichbar sind, aber von intern oder extern unterschiedliche Wege gehen können.

Allerdings eröffnet die Nutzung von übereinstimmenden Domänen im internen LAN und im Internet die Tür für verschiedene Angriffspotentiale. Dies gilt insbesondere, wenn Anwender nun im Homeoffice arbeiten und ohne VPN einfach "am Internet" angeschlossen sind. Der Client kann erst einmal nicht unterscheiden, ob er nun im LAN oder im Internet ist und versucht diese Information zu erhalten. Schon diese Suche "verrät" das ein oder andere über den Client an den Internet Provider.

Hinweis
Sie können nicht alle Vektoren verhindern. Ihre Mailadresse muss eine öffentliche Domain haben und auch ihr UPN muss für Office 365 eine eindeutige öffentliche Domain sein.

Homeoffice und Intranet/Internet

Windows klassifiziert Webseiten anhand ihrer Domain in verschiedene Zonen. Sie kennen sicher die Einstellungen zu "Intranet", "Vertrauenswürdige Sites", "Internet" und "eingeschränkte Sites"

Gewisse Einstellungen, z.B. die automatische Anmeldung, erfordern die "Intranet"-Zone. Normalerweise ist genau diese Einstellung aber der Default, wenn Sie in ihrem LAN und im Internet die gleiche DNS-Domain nutzen. Ein Mitarbeiter, der im LAN sich mit "<Servicename>netatwork.de" verbindet, erwartet natürlich eine automatische Anmeldung per Kerberos oder NTLM und keinen Kennwort-Dialog. Wenn er nun aber im Homeoffice sitzt, dann wird der PC weiterhin diese Adressen ansprechen und sich authentifizieren, wenn denn die Gegenseite einen 401 anfordert.

AD / LDAP

Das fällt insbesondere beim Active Directory auf. Jedes Domainmitglied sucht seine zum Active Directory dazugehörigen Domain Controller. Dazu dienen primär DNS-Anfragen und wenn Sie nicht im LAN oder per VPN verbunden sind, dann verraten ihre DNS-Abfragen schon die ein oder anderen Internas. Denken Sie daran, dass DNS-Abfragen meist unverschlüsselt sind und der DNS-Server, d.h. zumindest ihr Provider, diese Anfragen sehen und theoretisch auch verändern kann.

Ganz unangenehm kann es werden, wenn Sie intern eine DNS-Domain nutzen, die es auch im Internet gibt aber ihnen nicht gehört. Das sollten Sie unbedingt verhindern. Es ist zwar kein 100% Schutz aber Sie können jedem ihrer Clients z.B. die privaten IP-Adressen der DNS-Server ihrer Domäne per NRPT beibringen, was nicht nur mit Direct Access funktioniert.

Domain-DFS

Auch das "Distributed File System" ist davon betroffen, wenn Sie mit einem Client im HomeOffice sind und Domain-DFS nutzen. Domain-DFS schon schon mit ihrem Active Directory zum Einsatz, denn zwei prominente Verzeichnisse werden per DFS angesprochen

  • NETLOGON
    Hier liefen meist die Anmeldeskripte für Anwender
  • SYSVOL
    Zumindest die Gruppenrichtlinien sind hier einfach zu finden

Bei Net at Work haben wie vor langer Zeit, ehe wir dann auf SharePoint/OneDrive gewechselt sind, interne SMB-Freigaben per DFS verbunden. Der große Vorteil war die Abstraktion vom Servernamen. Wir konnten die Server dahinter im Laufe der Jahrzehnte einfach ändern ohne bei den Anwendern einen Link zu verlieren oder neue Namen zu lernen. Auch heute kann man diese Requests im Windows Explorer noch sehen:

Das bedeutet aber auch, dass ein Client im Homeoffice natürlich die gleichen Zugriffe durchführt aber in dem Fall auf der "öffentlichen Webseite" landet. Natürlich haben wir die Kontrolle über "netatwork.de" aber auch dort ist keine statische Webseite sondern ein CMS aktiv. Theoretisch ist es schon denkbar, dass ein Angreifer irgendwann eine Lücke findet und die Webseite "anreichert". Sein Ziel könnte ja sein, die Webseite möglichst nicht zu verunstalten um unbemerkt Zugriffe auf solche URLs abzufangen, daraus zu lernen und vieleicht Anmeldedaten zu ermitteln. 

Das CMS hinter der Webseite

Damit richtet sich der Fokus auf die Software, die ihre "Marketing-Webseite" bereitstellt. Denn hier ist der interessante Ansatz für einen externe aber auch einen internen Angreifer. Wenn es hier jemandem gelingt, zusätzlichen Code einzubinden, den normale Besucher nie zu Gesicht bekommen, dann könnte er ihre Anwender glauben lassen, sie würden einen legitimen Server erreichen. Genau genommen ist es ja auch ihr eigener Server, nur dass eine Komponente falsch spielt.

Das ist leider gar nicht mal so abwegig, denn was früher eine statische Webseite war, ist heute dynamische generierter Content auf Basis eines Content Management Systems (CMS) wie z.B. Wordpress, Joomla, Drupal o.ä. All diese Content Management Systeme erlauben umfangreiche Erweiterungen durch  Plug-Ins für Werbung, Bildergalerien und vieles mehr. Das sind aber alles meist PHP-Seiten, die nicht immer die Parameter korrekt auswerten. Zudem sind einige Systeme noch "Open Source" oder liegen als Quellcode vor, so dass Angreifer sehr einfach nach Schwächen suchen können. Gehen Sie einfach davon aus, dass ihr CMS früher oder später einmal kompromittiert wird.

Dann ist es zwar wichtig, ein "Backup" zu haben um den letzten Stand wieder bereit zu stellen und hoffentlich habe der Angreifer keinen Zugriff auf schwach geschützte Zugangsdaten oder sogar Kundendaten, die auf so einer Webseite eigentlich nichts zu suchen haben.

Webserver Logs

Aus meiner Sicht sollten Sie die WebServerLogs entsprechend auf ungewöhnliche Aktivitäten oder besondere Zugriffe überwachen. Ganz besonders wichtig ist dabei der HTTP-Statuscode des Request. Wer eine Lösung einsetzt, welche die Zugriffe auf den Webserver quasi in Echtzeit/Neartime ermittelt, kann damit nicht nur fehlgeleitete Clients ermitteln sondern auch die Installation einer Backdoor erkennen.

Autodiscover-Melder

Im Hinblick auf Autodiscover könnten Sie sogar ein Verzeichnis "Autodiscover" mit einer entsprechenden Datei anlegen, die einen Redirect auf ihre richtige Autodiscover-Webseite ausführt oder Sie über einen erfolgten Zugriff informiert. Wenn Sie die Basisfunktion von Autodiscover korrekt umgesetzt haben, sollte ein interner Client per Service Connection Point nie auf der externen Webseite landen. Ein Homeoffice-User kann aber schon hier aufschlagen.

<html>
   <head>
      <title>Autodicover PHP Alerter</title>
   </head>
   
   <body>
      
      <?php
         $to = "autodreport@msxfaq.de";
         $subject = "Autodiscover triggered";
         
         $message = "<h1>Autodisover triggered.</h1>";
         $message .= "<pre>REMOTE_ADDR:" . getenv('REMOTE_ADDR');
         $message .= "REMOTE_PORT:" . getenv('REMOTE_PORT') . "</pre>";

         $header  = "From:web@msxfaq.de \r\n";
         $header .= "To:" . $to . " \r\n";
         $header .= "MIME-Version: 1.0\r\n";
         $header .= "Content-type: text/html\r\n";
         
         $retval = mail ($to,$subject,$message,$header);
         
         if( $retval == true ) {
            echo "Message sent successfully...";
         }else {
            echo "Message could not be sent...";
         }
         http_response_code(404)
      ?>
      
   </body>
</html>

Die Datei können Sie einfach auf ihrem Webserver unter folgenden Pfaden und Dateinamen speichern

/autodiscover/autodiscover.xml
/autodiscover/autodiscover.srv

Natürlich müssen Sie ihrem Webserver noch verraten, dass er diese Dateien in diesem Verzeichnis auch mit PHP interpretieren soll. Auf einem Apache macht das eine ".htaccess" im entsprechenden Verzeichnis,

AddType application/x-httpd-php .svr
AddType application/x-httpd-php .xml

Achtung:
Auch anonyme Zugriffe generieren so eine Mail. Das ist nur ein Sample und nicht als Dauerlösung gedacht, da ein bösartiger Anwender damit ganz viele Mails an ihre Adresse generieren kann. Sie sollten den Zugriff zumindest mit einer Drosselung pro Client-IP o.ä. versehen.

Weitere Links