|
|
 | |  |  | Etendre les fonctionnalités de nmap et réaliser un scan au niveau applicatif |  |
par Julien Raeis et Jean-Baptiste Aviat (02/02/10)
============================================================================
Etendre les fonctionnalités de nmap et réaliser un scan au niveau applicatif
============================================================================
This article is available in english at nmap-script.html.en.
.
--[ 1. Introduction ]---------------------------------------------------
Nmap intègre, depuis la version 4.21, un moteur de script appelé NSE
pour "Nmap Scripting Engine" et basé sur le langage LUA
(http://nmap.org/nse/). Cette brève montre qu'il est ainsi possible, en
fonction des ports ouverts détectés par nmap, d'exécuter des scripts pour aller
encore plus loin dans la découverte d'informations.
--[ 2. Intégration des scripts ]----------------------------------------
Sous Linux, les scripts sont stockés par défaut dans le répertoire
/usr/share/nmap/scripts/, et indexés dans le fichier script.db, qui peut être
mis à jour par la commande "nmap --script-updatedb". Les scripts sont triés
par catégorie. Chaque script déclare lui-même les catégories auxquelles il
appartient au moyen de la ligne suivante :
-- Extrait du fichier rpcinfo.nse
categories = {"default","safe","discovery"}
Le moteur de scripts est activé en passant l'option "-sC" à nmap, lançant
ceux marqués "intrusive" et "safe". Il est recommandé, dans le cadre d'un
réseau de production, de désactiver les scripts "intrusive", ceux-ci pouvant
aller jusqu'à tenter des injections SQL automatiquement. Pour activer
d'autres catégories, il suffit d'appeler nmap avec l'option "--script"
comme suit :
Pour les scripts "sans danger" :
$ sudo nmap --script safe 127.0.0.1
ou pour l'ensemble des scripts disponibles (attention, dangereux !)
$ sudo nmap --script all 127.0.0.1
Un script individuel peut également être appelé :
$ sudo nmap --script nom_du_script.nse 127.0.0.1
D'une manière générale, il est raisonnable de privilégier les scripts
marqués "safe" pour minimiser les risques de crash des applications cibles.
--[ 3. Scripts livrés par défaut ]--------------------------------------
Par défaut, nmap 5.20 propose quatre-vingts scripts analysant notamment les
bannières des serveurs Apache et SSH, interrogeant les portmappers pour
obtenir la liste des services RPC ou encore réalisant des requêtes Whois
pour la découverte d'informations. Le script "smb-os-discovery.nse"
identifie la version d'un système Windows en se basant sur sa pile
NetBIOS/SMB :
$ sudo nmap -sU -sS --script smb-os-discovery.nse -p U:137,T:139 192.168.111.112 -PN
Starting Nmap 5.21 ( http://nmap.org ) at 2010-01-28 12:00 CET
NSE: Script Scanning completed.
Nmap scan report for 192.168.111.112
Host is up (0.00088s latency).
PORT STATE SERVICE
139/tcp open netbios-ssn
137/udp open netbios-ns
Host script results:
| smb-os-discovery:
| OS: Windows Server 2003 R2 3790 Service Pack 2 (Windows Server 2003 R2 5.2)
| Name: WORKGROUP\MSSQL2005
|_ System time: 2010-01-28 12:00:08 UTC+1
Nmap done: 1 IP address (1 host up) scanned in 0.42 seconds
--[ 4. Création de scripts personnalisés ]------------------------------
Il est facilement envisageable de créer des plugins personnalisés, en
utilisant le langage LUA (http://www.lua.org/) ainsi que les bibliothèques
fournies par nmap (nselibs).
Par exemple, le code suivant effectue une requête sur un serveur SIP afin de
découvrir les méthodes que celui-ci propose :
-- -------------- Script NSE SIPOptions -------------- --
id = "SIPOptions"
description = "Attempts to extract SIP Options on SIP service"
author = "Jean-Baptiste Aviat <Jean-Baptiste.Aviat@hsc.fr>"
license = "See nmaps COPYING for licence"
categories = {"discovery", "safe"}
require "shortport"
portrule = shortport.portnumber(5060, "udp", {"open", "open|filtered"})
action = function(host, port)
local status, s, methods, socket, request
socket = nmap.new_socket()
socket:set_timeout(5000)
local catch = function()
socket:close()
end
local try = nmap.new_try(catch)
try(socket:connect(host.ip, port.number, "udp"))
request = "INFO sip:test@hsc.fr SIP/2.0"
request = request .. "Via: SIP/2.0/TCP hsc.fr:5060\r\n"
request = request .. "From: <sip:test@hsc.fr>;tag=d3f423d\r\n"
request = request .. "To: <sip:test@hsc.fr>;tag=8942\r\n"
request = request .. "Call-ID: 312352\r\n"
request = request .. "CSeq: 5 INFO\r\n"
request = request .. "Content-Length: 0\r\n\r\n"
socket:send(request)
while true do
status, s = socket:receive_lines(1)
methods = string.match(s, "Allow: *([ A-Z,]+)")
if not status or string.len(methods)> 0 then
break
end
end
socket:close()
-- inform nmap the UDP port is opened
nmap.set_port_state(host, port, "open")
return methods
end
-- ------------------------------------------------------
--[ 5. Exemples d'utilisation ]-----------------------------------------
Une session de nmap accompagnée de ce script fournit la sortie suivante (ici,
un serveur Asterisk) :
$ sudo nmap --script=./SIPOptions.nse localhost -sU -p 5060
Starting Nmap 5.21 ( http://nmap.org ) at 2010-01-28 13:45 CET
Interesting ports on localhost (127.0.0.1):
PORT STATE SERVICE
5060/udp open sip
|_ SIPOptions: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY
Nmap done: 1 IP address (1 host up) scanned in 2.108 seconds
Et ici, sur le softphone Ekiga :
$ sudo nmap --script=./SIPOptions.nse localhost -sU -p 5060
Starting Nmap 5.21 ( http://nmap.org ) at 2010-01-28 13:47 CET
Interesting ports on dhcp2.hsc.fr (192.70.106.122):
PORT STATE SERVICE
5060/udp open unknown
|_ SIPOptions: INVITE,ACK,OPTIONS,BYE,CANCEL,NOTIFY,REFER,MESSAGE
--[ 6. Références ]-----------------------------------------------------
- Nmap : http://nmap.org/
- NSE : http://nmap.org/nse/
- SIP / INFO : http://www.ietf.org/rfc/rfc2976.txt
- LUA : http://www.lua.org/
|