Write-up CTFZone Quals 2019: Huhn

Trotz der Verschiebung der OFFZONE 2020- Konferenz wird es ein CTFZone- Finale geben ! Dieses Jahr wird es zum ersten Mal online stattfinden und aktiv in sozialen Netzwerken ausgestrahlt.

Wir werden die Details später bekannt geben, aber wir schlagen vor, das Webtask-Startup bereits in der Qualifikationsphase zu untersuchen. Die Analyse der Lösung wurde uns von Devand MacLean aus Kanada zugesandt . Speziell für Habr haben wir den Text des lokalen Startups übersetzt und laden Sie ein, herauszufinden, auf welche Kette von Schwachstellen die Teilnehmer gestoßen sind und was das Huhn damit zu tun hat.



allgemeine Informationen


Autor der Aufgabe: Pavel Sorokin
Punkte: 470
Anzahl der Teams, die die Aufgabe gelöst haben: 2

Nützliche Links:




, - :


  • (/Home/Index);
  • (/Home/Hens);
  • (/Home/Contact);
  • (/Auth/Login).

,   , :


  • ;
  •  API ,   .


Die Seite / Home / Hens enthält Links zum Herunterladen von Hühnerpässen.


Nach dem Decodieren von Base64 finden wir den Parameter Dateiname: 1.txt. Mit CyberChef codieren wir / etc / passwd in Base64 und folgen dem Link:

http://web-chicken.ctfz.one/File/Download?filename=L2V0Yy9wYXNzd2Q=

Der Inhalt der Datei / etc / passwd auf dem Server wird im Browser geöffnet Wir haben das Recht, beliebige Dateien im System zu lesen.

Wenn Sie versuchen, andere Dateien im System zu finden, stellen Sie möglicherweise einen Fehler fest, der jedes Mal auftritt, wenn Sie eine nicht vorhandene Datei anfordern (oder eine Datei, die mit den Benutzerrechten der Anwendung nicht gelesen werden kann):


Nachdem wir festgestellt haben , dass sich der Fehler auf die Umgebungsvariable ASPNETCORE_ENVIRONMENT bezieht , beginnen wir mit der Untersuchung der ASP.NET Core-Webanwendungslayouts. Und wir sehen folgendes:


Um die erforderlichen Pfade und Dateinamen zu konvertieren und in Base64 zu extrahieren, schreiben wir ein kleines Python-Skript ( fetch.py ):


Mit diesem Wissen über die Struktur der in ASP.NET Core erstellten MVC-Webanwendung erhalten wir mit fetch.py ​​den Quellcode für die folgenden Dateien:


  • ../Views/Shared/_Layout.cshtml
  • ../Views/Home/Index.cshtml
  • ../Views/Home/Contact.cshtml
  • ../Views/Home/Hens.cshtml
  • ../Views/Auth/Login.cshtml

Nachdem wir dies getan und den Quellcode jeder Seite studiert haben, finden wir ein interessantes Detail in Hens.cshtml


Zeile 1 enthält die Einschlussanweisung @ using StackHenneryMVCAppProject, die in ASP.NET einen Link zu einer DLL-Datei bedeutet.

Wir öffnen ../StackHenneryMVCAppProject.dll - aber nicht über das Python-Dienstprogramm in Kali Linux, sondern im Browser unter Windows, da wir diese Datei in Windows dekompilieren werden. Durch die Verwendung eines solchen URL:

http://web-chicken.ctfz.one/File/Download?filename=Li4vU3RhY2tIZW5uZXJ5TVZDQXBwUHJvamVjdC5kbGw=

Öffnen DLL-Datei in dnSpy (.NET - Decompiler), sieht sofort , dass bei dem Verfahren Initialize () der Klasse Config. Die Konfiguration , die beim Start der Webanwendung ausgeführt wird, liest den Inhalt der Datei horn_domains_internal.txt . Mit einem Python-Skript extrahieren wir den Inhalt dieser Datei:

Web-Chicken-Flag
web-Chicken-Auth

Die Initialize () -Methode stellt über Port 4321 eine Verbindung zum  Web-Chicken-Flag her und empfängt mehrere Parameter: secret_token , RSA_key und  flag .

Leider ist es nicht möglich, eine Verbindung zur Web-Chicken-Flagge herzustellen. Aber wenn wir den lokalen DNS - Hosts Rekord Web-Huhn-Auth an den Server des externen IP - Adresse (übersetzen 34.89.232.240 ) verwalten wir öffnen http: // web-Huhn-Auth / mit der Swagger UI - Schnittstelle , das verwendet wird Befehle über die REST-API beschreiben und ausführen.


Beim Durchsuchen der dekompilierten DLL-Datei können Sie feststellen, dass der AuthController- Controller nicht nur die Login () -Methode, sondern auch die Change_Password_Test () -Methode hatte :


Wenn wir zu / Auth / Change_Password_Test gehen,  sehen wir dieses Formular:


Wenn wir die Change_Password_Test () -Methode untersuchen, verstehen wir, dass sie vier Parameter vom Typ String über eine HTTP-POST-Anforderung verarbeitet:


  • Nutzername;
  • Neues Kennwort;
  • altes Kennwort;
  • base_url.


Etwas niedriger in der Change_Password_Test () -Methode, die wir sehen: Ohne einen Wert für base_url zu erhalten , nimmt die Methode den Wert conf.auth_server , dh Web-Chicken-Auth , und fügt dann / auth / login am Ende des base_url- Werts hinzu , wobei die resultierende Zeichenfolge der requestUri- Variablen zugewiesen wird :


Im nächsten wichtigen Teil des Codes werden die Zeichenfolgenwerte der Parameter username und  old_password aus der HTTP-POST-Anforderung und mit ihnen das  secret_token aus der Konfiguration in die JSON-Zeichenfolge eingefügt. Anschließend wird aus diesen Daten ein JSON StringContent- Objekt erstellt , das als HTTP-POST-Daten an die im vorherigen Schritt erstellte requestURI- Variable gesendet wird .


Jetzt wartet der Server auf die HTTP-POST-Anforderung, um  Uri aufzufordern, das JSON-Objekt mit dem Code- Parameter 0 zurückzugeben. Wenn dies nicht der Fall ist, gelangen wir zu dem Code-Zweig, der ab Zeile 6 beginnt und die Ansicht / Views / Auth / Login mit dem Fehler Ungültige Anmeldung / zurückgibt Passwort .

Wenn der HTTP - POST - Anforderung noch gibt ein JSON - Objekt mit dem Code - Parameter gleich 0, gehen wir zu dem Code - Zweig von Zeile 11. Dann wird die requestUri2 Variable den Wert bekommt http: // web-Huhn-Auth , eine andere JSON StringContent Objekt erstellt wirdmit den Parametern aus der ursprünglichen HTTP-POST-Anforderung wie im vorherigen Teil, und diese Daten werden an die requestUri2- Adresse  in der HTTP-PUT-Anforderung gesendet . Schließlich wird die Nachricht " Passwort geändert" an den Client zurückgegeben .


Kurz gesagt: Der gesamte Prozess beginnt mit einer HTTP-POST-Anforderung an  / Auth / Change_Password_Test , die eine bestimmte Anzahl von Parametern erwartet. Es nimmt diese Werte und erstellt ein JSON-Objekt, um es über HTTP POST an <base_url> / auth / login zu senden  . Wenn als Antwort JSON mit dem Code- Parameter 0 empfangen wird , erstellt es ein weiteres JSON-Objekt und sendet eine HTTP-PUT-Anforderung an  http: // web-Chicken-Auth / Auth / Change_password .

Beim Erlernen der REST-API in der Swagger-Benutzeroberfläche sehen wir, dass in der dekompilierten DLL-Datei nicht nur die Routen / auth / login und  / auth / change_password vorhanden waren , sondern auch die Route für / auth / password_recovery .


Diese API-Route erwartete ein JSON-Objekt mit zwei Parametern: email und  secret_token . Wenn er es erhalten hat, hat er ein JSON-Objekt mit der Code- Eigenschaft 0 und Nachrichten- und  Token- Zeichenfolgen zurückgegeben .


Es stellt sich heraus, dass es ausreicht, eine gültige E-Mail-Adresse einzugeben , wenn wir die Check_Password_Test () -Methode irgendwie zwingen, die Route / auth / password_recovery anstelle von / auth / login sofort anzufordern .

Wir untersuchen erneut den Teil des Codes, in dem die Check_Password_Test () -Methode den requestUri- Wert in der ursprünglichen HTTP-POST-Anforderung zuweist , und wir verstehen, dass wir den Wert http: // web-Chicken-auth / auth / password_recovery # als base_url-Parameter und requestUri im Finale senden müssen Das Ergebnis ist http: // web-horn-auth / auth / password_recovery # / auth / login .

Das Zeichen # in der HTTP-URL zeigt an, dass ein Teil der Anforderungsadresse beendet wurde. Daher ignoriert der Server, der die Anforderung empfängt, einfach den Teil / auth / login .


Das ist natürlich gut, aber wir müssen nur herausfinden, wie der REST-Endpunkt, an den wir jetzt die Anfrage umleiten, den E-Mail- Wert erhält . Ohne diesen Wert schlägt die Anfrage fehl und wir werden nicht weiter gehen.

Wir schauen uns genau an, wie die Check_Password_Test () -Methode JSON-Daten erstellt, und stellen fest, dass die Eingabedaten überhaupt nicht gelöscht werden, sodass Sie Ihre Parameter problemlos implementieren können. Es reicht aus, die folgenden Parameter in der HTTP-POST-Anfrage zu senden:

Benutzername = admin
old_password = pwned "," email ":" admin@chicken.ctf.zone "," lol ":"
new_password = p0tat0
base_url = http: // web-Chicken-auth / auth / password_recovery #

Das resultierende JSON-Objekt wird an / auth / password_recovery gesendet  :


Mit diesen JSON-Daten haben wir die Anforderungen erfüllt, dass / auth / password_recovery eine Antwort zurückgeben soll. Danach gibt der Server den Zweig für die Kennwortänderung ein (das JSON-Objekt enthält die E-Mail- Eigenschaft ). Jetzt brauchen wir den Wert von old_password nicht mehr. In diesem Codezweig haben wir alle Werte angegeben, die zum Ändern des Kennworts erforderlich sind (die Benutzername- Eigenschaft lautet admin und die Kennworteigenschaft ist p0tat0 ). Die Anfrage ist abgeschlossen und wir erhalten das Passwort als Antwort geändert .


Es bleibt nur noch ein neuer Benutzername und Passwort auf der Anmeldeseite einzugeben!


Und hier ist unsere Flagge:


All Articles