Nmap NSE Hacking, Teil 2: Derivatives Plugin eines Portscan

Nmap NSE Hacking, Teil 2

Derivatives Plugin eines Portscan

Marc Ruef
von Marc Ruef
Lesezeit: 10 Minuten

Im ersten Teil dieser Serie haben wir das Automatisieren von nmap mittels NSE-Skripten vorgestellt. Dabei haben wir kurz die Idee, das Konzept und die Möglichkeiten umrissen. Zusätzlich haben wir die grundlegende Struktur eines mit NSE implementierten Tests illustriert.

Im zweiten Teil wollen wir nun ein simples Skript schreiben. Dieses stützt sich in erster Linie auf den regulären Resultaten eines Portscans mit nmap ab. Wir bezeichnen ein solches Plugin als derivativ, da es eine Ableitung von grundlegenden Resultaten durchführt und damit keine eigenen Zugriffe über das Netzwerk umsetzen wird.

NSE-Skripte werden bei einer nmap-Installation standardmässig im Verzeichnis scripts abgelegt. Dort finden sich sodann auch die Standardskripte der jeweiligen Distribution. Zum Beispiel werden einige Skripte für die Auswertung von FTP-Server mitgeliefert:

Ein NSE-Skript benutzt in der Regel die Dateierweiterung nse. Neue Skripte können in dieser Art ebenfalls ins script-Verzeichnis abgelegt werden. Oder sie können in einem Unterverzeichnis oder an anderer Stelle gespeichert werden. Ein Miteinbeziehen bei einem Script-Scan erfordert in diesem Fall die zusätzliche Angabe des jeweiligen Standorts.

Der Aufbau eines NSE-Skripts gestaltet sich immer gleich: Im Kopf einer NSE-Datei finden sich einige deskriptive Felder, die grundlegende Informationen zum Plugin bereitstellen: Im Feld description wird beispielsweise eine Beschreibung des Tests festgehalten, in categories findet eine Zuweisung der Kategorien statt (siehe Teil 1), in dependencies werden Abhängigkeiten von anderen Skripten definiert, in author wird der Autor spezifiziert und in license die Lizenzbestimmungen festgehalten. Eine minimale Angabe gestaltet sich beispielsweise wie folgt:

description = [[ Dieses minimale Skript identifiziert Webdienste ]]

author = “Marc Ruef” license = “(c) 2010 by scip AG” categories = {“default”, “safe”}

In der rule-Sektion wird nun definiert, unter welchen Bedingungen das Skript ausgeführt wird. Hierbei kann entweder eine portrule (für Tests von Ports) oder eine hostrule (für Tests von Hosts) verwendet werden. Eine Ableitung von einem Portscan fokussiert sich in erster Linie auf die portrule (das Prinzip der hostrule werden wir später besprechen). Innerhalb von ihr wird vordefiniert, bei welchem Zustand eines Zielports eine Weiterverarbeitung des Skripts initiiert und damit schlussendlich die Schwachstelle gemeldet werden soll.

Eine portrule kann unterschiedlich implementiert werden. Die einfachste und von vielen bevorzugte Methode besteht unter Zuhilfenahme der Library shortport und der entsprechenden Methoden. Nachfolgend wird zuerst die Library mittels require inkludiert und danach die Methode port_or_service() auf das Objekt shortport angewendet. Die genannte Methode erwartet drei verschiedene Argumente, wobei diese jeweils als Table (in anderen Programmiersprachen wird dieser Datentyp Array genannt) übergeben werden müssen. Das erste Argument definiert die Portnummern, das zweite die Protokollnamen und das dritte das Transportprotokoll. Es scheint offensichtlich, dass in diesem Beispiel eine portrule für Web-Dienste umgesetzt wird.

require “shortport”

portrule = shortport.port_or_service({80, 443}, {“http”, “https”}, {“tcp”})

In einem weiteren Schritt kann nun in action die Weiterverarbeitung – in der NSE-Dokumentation als Mechanism bezeichnet – spezifiziert werden. Diese Funktion, sie kann als Main-Funktion verstanden werden, wird dann ausgeführt, wenn portrule gleich true ist. Also dann, wenn ein Webserver auf dem Zielport vermutet (anhand der Portnummern) oder identifiziert (anhand der Protokollnamen) wird. In diesem Fall geben wir nur ganz allgemein mittels return eine Zeichenkette zurück, die explizit darüber informiert, dass ein Webserver gefunden wurde und mit port.number geben wir die entsprechende Portnummer an.

action = function(host, port)
   return "Webserver gefunden auf Port " .. port.number
end

Es wird nun mit dem Schalter --script="scripts\labs\http-detection_simple.nse" dieses einzelne Skript ausgeführt. Und wie zu sehen ist, wird als Detail des offenen Ports zusätzlich die explizite Ausgabe ausgewiesen:

C:\Dokumente und Einstellungen\maru>nmap -sS -sV —script=“scripts\labs\http-detection_simple.nse” www.scip.ch -p 80

Starting Nmap 5.21 ( http://nmap.org ) at 2010-03-24 12:37 Westeuropõische Normalzeit NSE: Script Scanning completed. Nmap scan report for www.scip.ch (192.168.0.10) Host is up (0.0020s latency). rDNS record for 192.168.0.10: www.scip.ch PORT STATE SERVICE VERSION 80/tcp open http Apache httpd |_http-detection_simple: Webserver gefunden auf Port 80

Service detection performed. Please report any incorrect results at http://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned in 7.59 seconds

Dies war alles relativ simpel und erfüllt zugegebenermassen zur Standardausgabe von nmap keinen zusätzlichen Zweck. Sodann soll die Funktion erweitert werden, um ein Mehr an Informationen bereitstellen zu können. So wird mit common_http_ports eine Table angelegt, in der die Standardports für Webserver abgelegt sind. Indem nun diese Table mittels einer for-Schleife durchlaufen wird, kann nun explizit ermittelt werden, ob der angenbotene Webserver auf einem Standardport horcht oder nicht. Der Zustand dessen wird als String (Yes|No) in der lokalen Variable common_port_found abgelegt. Zum Schluss wird in der lokalen Variable output das Resultat generiert und zurückgeliefert.

action = function(host, port)
      local common_http_ports = {80, 443}
      local common_port_found = “Nein”

for i=1, #common_http_ports, 1 do if port.number == common_http_ports[i] then common_port_found = “Ja” break end end local output = “Webserver gefunden:\n” output = output .. “Port:\t\t” .. port.number .. “\n” output = output .. “Standard:\t” .. common_port_found .. “\n” return output end

Es lassen sich in einem weiteren Schritt zusätzliche eigene Funktionen definieren. Diese sind wie bei anderen funktionalen Programmiersprachen über das Schlüsselwort function definiert, können aus anderen Subroutinen aufgerufen und ihre Rückgabewerte weiterverarbeitet werden. Dedizierte Prozeduren lassen sich ebenfalls in externe Dateien ablegen. Möchte man diese mittels require einbinden, sieht nmap das Verzeichnis nselib vor. In diesem finden sich verschiedene Standard-Bibliotheken, die den Umgang mit nmap-Scans erleichtern.

Wird ein Skript-Ausgeführt, das einen Syntaxfehler aufweist, wird die Ausführung dessen abgebrochen. Die durch den Lua-Interpreter ausgegebene Fehlermeldung wird ersichtlich, wenn nmap mit dem Debugging-Schalter -d ausgeführt wurde. In der Standardbilbiothek nmap wird mit den Methoden verbosity() und debugging() die Möglichkeit geboten, die Aktivierung von Verbose- und Debugging-Parametern zu erkennen und auf diese einzugehen. Vor allem, aber nicht nur, lohnt sich bei der Entwicklung von NSE-Skripten auf diese Möglichkeit sowie auf print_debug() zurückzugreifen, um je nachdem interne Details der Verarbeitung anzeigen zu lassen.

Im dritten Teil werden wir die Entwicklung dieses NSE-Skripts vorantreiben. Dabei werden wir die Möglichkeiten der Version Detection von nmap ausschöpfen, um anhand der ermittelten Fingerprints komplexere Ableitungen umzusetzen. Mitunter werden wir Pattern-Matching und reguläre Ausdrücke miteinbeziehen, um verwundbare Versionen erkennen und dokumentieren zu können.

Über den Autor

Marc Ruef

Marc Ruef ist seit Ende der 1990er Jahre im Cybersecurity-Bereich aktiv. Er hat vor allem im deutschsprachigen Raum aufgrund der Vielzahl durch ihn veröffentlichten Fachpublikationen und Bücher – dazu gehört besonders Die Kunst des Penetration Testing – Bekanntheit erlangt. Er ist Dozent an verschiedenen Hochschulen, darunter ETH, HWZ, HSLU und IKF. (ORCID 0000-0002-1328-6357)

Links

Sie wollen mehr als einen simplen Security Test mit Nessus und Nmap?

Unsere Spezialisten kontaktieren Sie gern!

×
Cyber Threat Intelligence

Cyber Threat Intelligence

Marc Ruef

3D Printing

3D Printing

Marc Ruef

Contact Tracing App DP3T

Contact Tracing App DP3T

Marc Ruef

Sie wollen mehr?

Weitere Artikel im Archiv

Sie brauchen Unterstützung bei einem solchen Projekt?

Unsere Spezialisten kontaktieren Sie gern!

Sie wollen mehr?

Weitere Artikel im Archiv