
Webshell-Scanner und -Analysator.
Web Shell Analyzer ist eine plattformübergreifende, eigenständige Binärdatei, die ausschließlich zum Identifizieren, Dekodieren und Markieren von Dateien entwickelt wurde, bei denen es sich vermutlich um Web-Shells handelt. Der Web Shell Analyzer ist der große Bruder des Web-Shell-Scanner-Projekts (http://github.com/tstillz/webshell-scan), das Dateien nur per Regex scannt, ohne Dekodierung oder Attributanalyse.
Die mitgelieferten Regex und integrierten Dekodierungsroutinen des Scanners garantieren nicht, jede Web-Shell auf der Festplatte zu finden, und können möglicherweise einige Fehlalarme auslösen. Es wird außerdem empfohlen, den Analyzer zu testen und seine Auswirkungen zu bewerten, bevor Sie ihn in Produktionsumgebungen ausführen. Der Analyzer enthält keine Garantie, Verwendung auf eigene Gefahr.
PHP-, ASP/X-Web-Shells. JSP/X, CFM und andere Typen sind in Arbeit.Jede gescannte Datei kann durch PRE- und/oder POST-Aktionen verarbeitet werden:
Die Idee hinter den PreDecodeActions-Funktionen war es, Regex zu verwenden, um einen übereinstimmenden String oder ein Muster zu identifizieren, dessen Rohinhalt zu erfassen, definierte Dekodierungs-/Bereinigungsschritte durchzuführen und die endgültige Ausgabe zur erneuten Analyse/Verarbeitung an die Analyse-Engine zurückzusenden. Ein sehr einfaches Beispiel dafür ist die Base64-Decodierung. Um eine Erkennungslogik gegen eine base64-kodierte Web-Shell zu prüfen, müssen wir zuerst alle Ebenen von Base64 entfernen. Dazu könnten wir die folgende PreDecodeAction verwenden:
{
Name: "PHP_Base64Decode",
Regex: *regexp.MustCompile(`(?i)(?:=|\s+)(base64_decode\('('?\"?[A-Za-z0-9+\/=]+'?\"?))`),
DataCapture: *regexp.MustCompile(`(?i)((?:'|")[A-Za-z0-9+\/=]+(?:'|"))`),
PreDecodeActions: []cm.Action{
{Function: cm.StringReplace, Arguments: []interface{}{"\"", "", -1}},
{Function: cm.StringReplace, Arguments: []interface{}{"'", "", -1}},
},
Functions: []cm.Base_Func{cm.DecodeBase64},
},
Betrachtet man den obigen Block, so haben wir zuerst den Namen der Funktion, den zur Mustererkennung verwendeten Regex, den Daten-Erfassungs-Regex (manchmal möchte man anpassen, was erfasst wird im Vergleich zu dem, was erkannt wird) und die PreDecodeActions. In diesem Fall werden VOR der Anwendung der Funktion cm.DecodeBase64 auf den übereinstimmenden Text zuerst die folgenden Zeichen " und ' entfernt. PostDecodeActions funktioniert umgekehrt, wobei die Ausgabe NACH der Dekodierung überprüft wird. Mit diesem Modell können wir mehrere benutzerdefinierte Decoder erstellen, die unbegrenzte PRE/POST- und Dekodierungsfunktionen haben, um die meisten Web-Shell-Analyseanforderungen zu bewältigen.
Eine Erkennung ist ein Regex, der mit einem Namen und einer Beschreibung versehen ist. Die Idee hinter diesem Modell war, Erkennungen modular und skalierbar zu machen und den Kontext zur eigentlichen Erkennung zu bewahren. Erkennungen haben das gleiche Format wie Attribute, außer dass Attribute keine Erkennung auslösen können, sondern nur Kontext zu einer bestehenden Erkennung hinzufügen. Sehen wir uns den folgenden Beispiel-Erkennungslogikblock an:
{
Name: "Generic_Embedded_Executable",
Description: "Looks for magic bytes associated with a PE file",
Regex: *regexp.MustCompile(`(?i)(?:(?:0x)?4d5a)`),
},
Anhand des Regex erkennen wir, dass nach einer eingebetteten Windows-PE-Datei anhand der magischen Header-Bytes 4D 5A gesucht wird. Wird dies gefunden, führt es zu einer Erkennung und es würde ein JSON-Bericht für die Datei erstellt werden.
Derzeit werden Erkennungen basierend auf der Dateierweiterung oder generisch für alle Dateitypen angewendet. Beispielsweise sind Dekodierungsroutinen für PHP unter cm.GlobalMap.Function_Php definiert und Tags für Attribute unter cm.GlobalMap.Tags_Php. Die Funktionen cm.GlobalMap.Function_Generics und Tags unter cm.GlobalMap.Tags_Generics gelten für ALLE Web-Shell-Erweiterungen als Auffangregel.
Attributmarkierung ist ein neues Konzept, das ich entwickelt habe und das einer bestehenden Web-Shell-Erkennung "Kontext" hinzufügt. Attribute allein können derzeit keine Erkennung auslösen. In einer traditionellen Scan-Engine würde ein Scanner nur warnen, wenn eine Web-Shell erkannt wurde, aber wenig bis gar keinen zusätzlichen Kontext darüber liefern, welche Fähigkeiten (Attribute) die Web-Shell möglicherweise hat. Attribut-Tags funktionieren genauso wie die Erkennungslogik, erscheinen jedoch nur, nachdem eine Erkennung identifiziert wurde, und können keine eigenen Erkennungen auslösen. Sehen wir uns das folgende Beispiel an:
cm.GlobalMap.Tags_Php = []cm.TagDef{
{
Name: "PHP_Database_Operations",
Description: "Looks for common PHP functions used for interacting with a database.",
Regex: *regexp.MustCompile(`(?i)(?:'mssql_connect\|mysql_exec\()`),
Attribute: true,
},
}
Wir sehen, dass wir unter der Struktur Tags_Php einen neuen PHP-Tag erstellt haben. Wenn während des Scans eine Übereinstimmung gefunden wird, wird das Attribute-Flag überprüft, und wenn es auf True gesetzt ist, wird der erkannten Web-Shell der Tag PHP_Database_Operations zusammen mit der Häufigkeit und dem passenden Textblock an den JSON-Bericht angehängt, wie im folgenden Beispielausgabe gezeigt:
{
"filePath": "/testers/1.php",
"size": 66109,
"md5": "6793d8ebab93e5a0f91e5a331221f331",
"timestamps": {
"birth": "2019-02-03 02:02:22",
"created": "2020-07-29 02:50:15",
"modified": "2019-02-03 02:02:22",
"accessed": "2020-07-29 02:51:07"
},
"matches": {
"FilesMAn": 5,
"FilesMan": 29,
"cmd": 20,
"eval(": 4,
"exec(": 2,
"ipconfig": 1,
"netstat": 2,
"passthru(": 1,
"shell_exec(": 1
},
"decodes": {
"Generic_Base64Decode": 40,
"Generic_Multiline_Base64Decode": 165
},
"tags": {
"Generic_Embedding_Code_C": {
"bind(": 2,
"listen(": 2
},
"PHP_Banned_Function": {
"exec(": 3,
"get_current_user(": 1,
"getmyuid(": 1,
"link(": 7,
"listen(": 2,
"passthru(": 1,
"realpath(": 1,
"set_time_limit(": 1
},
"PHP_Database_Operations": {
"mysql_query(": 1
},
"PHP_Disk_Operations": {
"@chmod(": 1,
"@filegroup(": 4,
"@fileowner(": 4,
"@rename(": 2,
"fopen(": 7,
"fwrite(": 6
}
}
}
Diese Tags helfen nicht nur zu definieren, was eine Web-Shell tun kann, sondern bieten Teams wie IR-Beratern, die Live-Response-Einsätze durchführen, einen Anhaltspunkt für mögliche nächste Schritte.
Keine! Laden Sie einfach die Binärdatei für Ihr Betriebssystem herunter, geben Sie das zu scannende Verzeichnis an (andere Argumente sind optional) und lassen Sie es laufen.
Die Ausführung von wsa ohne Argumente zeigt die folgenden Optionen:
/Users/beastmode$ ./wsa
Options:
-dir string
Directory to scan for web shells
-pretty
If set to true, the analyzer will output the results in a json indented form
-raw_contents
If a match is found, grab the raw contents and base64 + gzip compress the file into the JSON object.
-size int
Specify max file size to scan (default is 10 MB) (default 10)
-verbose
If set to true, the analyzer will print all files analyzer, not just matches
Das einzige erforderliche Argument ist dir. Sie können die anderen Programmstandards nach Wunsch überschreiben.
Die Ausgabe des Analyzers wird auf der Konsole (Standardausgabe) ausgegeben. Beispiel unten (Für beste Ergebnisse leiten Sie die Standardausgabe in eine JSON-Datei um und überprüfen/nachbearbeiten Sie sie offline):
Linux: ./wsa -dir /opt/www
Windows: wsa.exe -dir C:\Windows\Inetput\wwwroot
### Mit STDOUT und vollständiger, codierter und komprimierter Web-Shell-Datei:
Linux: ./wsa -dir /opt/www -raw_contents=true > scan_results.json
Sobald der Analyzer fertig ist, gibt er die gesamten Scan-Metriken an STDOUT aus, wie im folgenden Beispiel gezeigt:
{"scanned":311,"matches":122,"noMatches":189,"directory":"/webshell-master/php","scanDuration":1.4757737378333333,"systemInfo":{"hostname":"Beast","envVars":[""],"username":"beastmode","userID":"501","realName":"The Beast","userHomeDir":"/Users/beastmode"}}