Die Geschichte eines Schülers in der 12. Klasse, der während Covid mehr Zeit hatte, auf Bug-Bounty-Jagd ging und für einen Bug Bounty in privaten GitHub Pages 35.000 Dollar erhielt.
Er meldete den Bug Bounty für private GitHub Pages, und es gab zwei CTF-Boni.
-
10.000 Dollar: Die Flag von
flag.private-org.github.ioohne Benutzerinteraktion lesen. Wenn diese Flag von einem Account außerhalb der Organisationprivate-orggelesen werden kann, gibt es einen zusätzlichen Bonus von 5.000 Dollar. -
5.000 Dollar: Die Flag von
flag.private-org.github.iomit Benutzerinteraktion lesen.
Authentifizierungsablauf
GitHub Pages wird auf der separaten Domain github.io gehostet, daher werden die Authentifizierungs-Cookies von github.com nicht an den Server für private Pages gesendet. Deshalb kann die Authentifizierung privater Pages die Identität eines Nutzers ohne zusätzliche Integration mit github.com nicht feststellen. Deshalb hat GitHub einen eigenen Authentifizierungsablauf gebaut.
-
Beim Besuch einer privaten Page prüft der Server, ob das Cookie
__Host-gh_pages_tokenvorhanden ist. -
Wenn das Cookie fehlt oder ungültig ist, leitet der Server der privaten Page auf
https://github.com/loginweiter. -
Diese Weiterleitung setzt außerdem eine Nonce im Cookie
__Host-gh_pages_session.- Dieses Cookie verwendet das Cookie-Präfix
__Host-, wodurch verhindert wird, dass es per JavaScript außerhalb der Host-Domain gesetzt wird.
- Dieses Cookie verwendet das Cookie-Präfix
-
/loginleitet auf/pages/auth?nonce=&page_id=&path=weiter. -
Dort wird über den Parameter
tokenein temporäres Authentifizierungs-Cookie erzeugt, das anhttps://pages-auth.github.com/redirectweitergegeben wird. -
/redirectleitet anhttps://repo.org.github.io/__/authweiter. -
Dieser letzte Endpunkt setzt auf der Domain
repo.org.github.iodie Authentifizierungs-Cookies__Host-gh_pages_tokenund__Host-gh_pages_id. -
Dabei wird auch die zuvor gesetzte
nonceaus__Host-gh_pages_sessiongeprüft.
Der ursprüngliche Anfragepfad und die Page-ID werden jeweils in den Query-Parametern path und page_id gespeichert, und die Nonce wird im Parameter nonce gespeichert.
Ausnutzung
CRLF-Rückgabe
-
Die erste Schwachstelle war eine CRLF-Injektion im Parameter
page_idvonhttps://repo.org.github.io/__/auth. -
Dabei wurde festgestellt, dass das Parsing von
page_idLeerraum ignoriert und dieser Wert direkt im HeaderSet-Cookiegesetzt wird. -
Mit klassischer CRLF-Injektion lässt sich das Parsing zwar brechen, aber es hat sonst keine weiteren Auswirkungen.
-
Da der Header
Location:hinter dem HeaderSet-Cookieangehängt wird, wird der Location-Header trotz 302-Redirect ignoriert und der Body gerendert.
Angriff
-
Durch Einsicht in den GitHub-Enterprise-Code wurde klar, dass der Server für private Pages mit openresty nginx implementiert ist.
-
Durch Hinzufügen eines Null-Bytes gelang eine XSS; dieses Null-Byte muss am Anfang des Bodys stehen, daher ist kein Header-Injection-Angriff möglich.
-
Damit konnte nun beliebiger JavaScript-Code auf der Domain der privaten Page ausgeführt werden.
-
Es blieb nur noch, einen Weg zu finden, die Nonce zu umgehen.
Umgehung der Nonce
-
Beobachtungen zeigten, dass private Sibling-Pages derselben Organisation gegenseitig Cookies setzen können.
-
Ein auf
private-org.github.iogesetztes Cookie wird anprivate-page.private-org.github.ioweitergegeben. -
Wenn sich der Schutz des Präfixes
__Host-umgehen lässt, kann die Nonce leicht umgangen werden. -
Das wird nicht von allen Browsern unterstützt; IE unterstützt das Präfix
__Host-nicht. -
Auf der Suche nach einer besseren Methode kam dann eine interessante Idee auf.
-
Beim Prüfen der Groß-/Kleinschreibung von Cookies stellte sich heraus, dass
__HOSTund__Hostunterschiedlich behandelt werden und GitHub private Pages beim Parsen von Cookies Großbuchstaben ignoriert. -
Dadurch ließ sich die Nonce per JavaScript festlegen.
-
Dafür gab es den Bonus von 5.000 Dollar.
Cache Poisoning
-
Die Antwort des Endpunkts
/__/auth?wird anhand des ganzzahligen Werts der gefälschtenpage_idgecacht. -
Dadurch sind auch Nutzer ohne Interaktion betroffen, wenn es gelingt, per XSS-Payload den Cache zu vergiften.
-
Wenn ein Angreifer
unprivileged.org.github.ioangreift und die Authentifizierung vergiftet, wird die XSS-Payload gecacht. -
Da Cookies auf der Parent-Domain
org.github.iogeteilt werden, kann der Angreifer auchprivileged.org.github.ioangreifen.
Öffentliche private Pages
-
Um den Bonus von 15.000 Dollar zu erhalten, musste ein Nutzer außerhalb der Organisation diesen Angriff ausführen können.
-
Möglich wurde das durch eine Fehlkonfiguration, bei der private Pages für ein öffentliches Repository eingerichtet waren.
- Gemeint ist, dass Pages in einem privaten Repository erstellt und das Repository anschließend auf public umgestellt wird.
-
Diese fehlkonfigurierten privaten Pages durchlaufen für alle Nutzer den Authentifizierungsablauf und gewähren auch Nutzern außerhalb der Organisation Leserechte.
Noch keine Kommentare.