PoPToken

Bei der Analyse des Zugriffs von Teams zu Exchange OnPremises (Teams und ExOnPrem Termine) habe ich das erste mal von einer weiteren Authentifizierung neben NTLM, Kerberos und vor allem Bearer erfahren. Da der Zugriff im gleichen Moment auch noch mit einem 500er Fehler quittiert wurde, bin ich etwas tiefer eingestiegen.

PoP-Token in FREB

Wie in der Einleitung beschrieben ging es um den Zugriff von Microsoft Teams auf ein lokales Exchange 2019 Postfach, um Informationen über anstehende Termine zu erhalten. In dem Zuge habe ich mit IIS Failed Request Tracing auf dem lokalen IIS die eingehenden Request analysiert. Eine Nutzung von Fiddler o.ä. ist ja nicht möglich, da der Client in der Cloud steht und unter Kontrolle von Microsoft ist. Ein MIMT-Proxy einzuschleusen, hätte den produktiven Betrieb vielleicht gestört und Zugriff auf den davor stehenden Loadbalancer und die Web Application Firewall hatte ich auch nicht. Aber der IIS kann das auch alleine.

Hier finde ich den eingehenden Request mit dem Header "Authorization: MSAuth1.0" und (aufgrund Zeilenumbruch) darunter den Eintrag zu PoPToken und dem type=AT_POP". Interessant ist auch die Information über den "User-Agent: SkypeSpaces/1.0a$*+" und auch das Feld "Prefer" enthält mit "outlook.diagnostics, outlook.data-source="CloudCache", exchange.behavior="EnableGCVOptimizations" einen interessanten String, der aber bislang im Internet keine Treffer bringt.

PoPTokens sind sicherer als Bearer Tokens

Zuerst habe ich mir die Frage gestellt, warum überhaupt noch ein weiteres Verfahren eingeführt wurde. Ist Bearer nicht sicher genug?. Bearer-Token sind doch schon kryptografisch durch eine digitale Signatur des Ausstellers und optional einer Verschlüsselung für den Empfänger gesichert und die Gültigkeitsdauer ist auch beschränkt. Fakt ist aber auch, dass das Bearer-Token an sich schon "transportabel" ist und eine Malware auf eine Client könnte ein ausgestelltes Bearer-Token relativ einfach kopieren und ausleiten. Damit könnt ein anderes Systeme so tun, als wäre es ich. Es gibt keine Bindung des Bearer-Tokens an das Endgerät. Und genau das sollen POP-Tokens lösen

Bearer tokens are the norm in modern identity flows; however they are vulnerable to being stolen from token caches. Proof-of-Possession (PoP) tokens, as described by RFC 7800, mitigate this threat. PoP tokens are bound to the client machine, via a public/private PoP key. The PoP public key is injected into the token by the token issuer (Entra ID) and the client also signs the token using the private PoP key. A fully formed PoP token has two digital signatures - one from the token issuer and one from the client. The PoP protocol has two protections in place:
Quelle: https://learn.microsoft.com/en-us/entra/msal/dotnet/advanced/proof-of-possession-tokens

Dazu werden zwei Methoden ergänzt:

  • Zusätzliche Signatur durch den Client
    Ein POP-Token ist im Grund schon ein Bearer-Token, welches aber nicht nur durch den Aussteller signiert wird, sondern danach auch noch einmal von dem Client. Im Token-Cache liegt weiter das normale signierte Token, welches aber von der anderen Seite nicht akzeptiert wird.
  • Server Nounce
    Um zu verhindern, dass nun jemand auf dem Übertragungsweg die Übermittlung des POP-Token abfängt, wird es mit einem "Nounce", quasi einer Zufallszahl des Servers versehen,

401 Authorization Header

Die Authentifizierung wird also etwas kniffliger, da der Client einen Public/Private-Key haben muss und zumindest den Public Key auch zum Ziel bringt. Das Ziel seinerseits muss einen Nounce an den Client bringen. Das ist aber relativ einfach, da ich auf HTTP Authentication schon ausgeführt habe, dass der erste Zugriff meist Anonym erfolgt und der Webserver dann mit einem 401 ab. Hier ist es aber so, dass ich schon ein "popToken" gesendet habe. Sie können recht einfach prüfen, ob eine Gegenseite auch "PoP" anbietet.

try{
   $result = Invoke-WebRequest `
                -UseBasicParsing  `
                -Headers @{'Authorization' = "Bearer"} `
                -Uri "https://graph.microsoft.com/v1.0/me"
}
catch {
   Write-Host "--- Exception ----" -foregroundcolor red
   ($_.Exception.Response.headers | where-object {$_.key -eq "WWW-Authenticate"}).value.split(".")
}

Der kurze PowerShell-Code stellt eine anonyme Anfrage an die Microsoft Graph API aber teilt über den Header "Authorization: Bearer" mit, dass er auch Bearer versteht. Die Antwort ist die erwartete 401-Meldung mit einem "WWW-Authenticate"-Header, der neben Bearer aber auch POP enthält.

Der lokale Exchange Server lehnt hier den Request mit einem "401 - Authentication Required" ab und übermittelt die von ihm unterstützten Anmeldeverfahren als "WWW-Authenticate"-Header. Die Cloud wird sicher nichts mit Negotiate oder NTLM anfangen können und evaluiert den "Bearer"-Anteil, mit dem Exchange dem anfragenden System mitteilt.

Aktuell bin ich noch nicht sicher, warum ein Exchange 2019 hier den PoPTokens nicht vertraut, denn diese Anfrage kommt z.B., wenn ich den "Teams Presence Based on Calendar Events"-Test auf https://testconnectivity.microsoft.com/tests/teams mit einem OnPremises Postfach starte.

Der nächste Request sollte dann ein passendes Token enthalten und bei erfolgreicher Anmeldung mit einem "200 OK" und den Daten beantwortet werden.

Microsoft und PoP SHR

Laut Microsoft kann es auch durchaus sein, dass ein Service mehrere "WWW-Authenticate"-Header liefert.


Quelle: https://learn.microsoft.com/en-us/entra/msal/dotnet/advanced/proof-of-possession-tokens

Microsoft Graph liefert BEARER und PoP

POPToken decodiert

Auf dem Request mit dem PoPToken habe ich mit den Payload geschnappt, welcher wieder nur ein "BASE64-codierter" JSON-String ist.

Hinweis:
Das Token ist nicht einfach ein BASE64-String, sondern es sind drei BASE64-Strings, die durch einen "Punkt" ('.') voneinander getrennt sind.

Über die bekannten Webseiten https://jwt.io  oder https://jwt.ms können Sie diese Strings im Browser einfach konvertieren lassen, Die erste Konvertierung zeigt aber nun nicht direkt das Bearer-Token an, wie ich auf Bearer Decoding gezeigt habe, sondern zwei weitere Tokens.

Die beiden Tokens enthalten unterschiedliche Informationen.

AT PFT

Das unter "AT" aufgeführt AccessToken lässt sich dann weiter decodieren zu:

Das unter "pft" hinterlegte Token enthält dann den Benutzer, in dessen Namen der Zugriff erfolgen soll.

Diese Decodierung können Sie mit Webseiten wie https://jwt.io und https://jwt.ms online ausführen. Das ist aber kritisch zu sehen, wenn es Tokens aus einem produktiven Netzwerk sind, denn wie können Sie sicher sein, dass die genutzte Webseite oder Webapplication die Daten nicht ausleitet?.

POP und Conditional Access

PoPTokens sind wie Bearer, NTLM, Kerberos u.a. erlaubte Anmeldeverfahren und damit auch für "Conditional Access" interessant. Sie können über Regeln z.B. als Administrator vorschreibebn, dass Zugriffe auf bestimmte Dienste nicht mehr mit einfachen Bearer-Tokens, sondern nur noch mit "Bound Tokens" möglich sind. Microsoft schreibt dazu

Token protection (sometimes referred to as token binding in the industry) attempts to reduce attacks using token theft by ensuring a token is usable only from the intended device. When an attacker is able to steal a token, by hijacking or replay, they can impersonate their victim until the token expires or is revoked. Token theft is thought to be a relatively rare event, but the damage from it can be significant.
Quelle: Conditional Access: Token protection (preview) https://learn.microsoft.com/en-us/entra/identity/conditional-access/concept-token-protection#known-limitations

Die Einstellung ist in den EntraID Conditional Access-Policies schon aktiviertbar:

Damit können Sie besonders sensible Anwender oder Applikationen besser absichern. Voraussetzung ist natürlich, dass die entsprechende Applikation auch PoPToken als Anmeldeverfahren unterstützt. Die Dokumentation von Microsoft listet einige Voraussetzungen und Einschränkungen auf

PoPToken nutzen

Aktuell habe ich neben Microsoft Graph noch keine anderen Systeme gefunden, die eine Anmeldung per PoPToken zulassen und entsprechende Bibliotheken sind noch sehr dünn gesät. Der Grund für diese Weiterentwicklung von Bearer Tokens ist natürlich wieder einmal die Sicherheit. Wenn ein Client ein Bearer-Token im Speicher hält und dies durch eine Malware abgegriffen werden kann, erhält der Angreifer die gleichen Berechtigungen. Dies lässt sich vermeiden, wenn sich Client Server zusätzlich gegenseitig absichern und das Token mit einer Information des Servers verschlüsselt ist.

Ähnliche Dinge sehen wir ja auch bei der Absicherung von NTLM-Anmeldungen mittels Extended Protection (IIS Extended Protection), um einen "Man in the Middle"-Angriff zu erkennen oder gleich zu verhindern. Solange aber Dienste neben POP auch immer noch "Bearer" anbieten, kann ein Man in the Middle natürlich schon die erste Antwort des Servers mit den gültigen Anmeldeverfahren verändern und sichere Wege einfach unterdrücken. Wenn der Client dann den Fallback auf Bearer akzeptiert, dann hat ein Angreifer natürlich auch wieder das Bearer Token in der Reinform oder auch Session Cookies etc. Dann müsste in den Tokens auch der Client z.B.: über seine IP-Adresse einbezogen werden. Damit würde aber bei einem Netzwerkwechsel auch wieder eine Reauthentifizierung erforderlich.

Letztlich ist es eine Risikoabschätzung, welche Mindeststandards ein Client umsetzt. Ich lasse mich von solchen Tokens bei der Fehlersuche nicht aus der Ruhe bringen und weiß nun, wie ich auch diese Tokens decodieren kann.

Weitere Links