sábado, 20 de junho de 2015

Nmap Scripting Engine (NSE) - Escrevendo o meu primeiro script



                           
Introdução


O Nmap Scripting Engine (NSE) é um dos recursos mais poderosos e flexíveis do Nmap. Ele permite aos usuários escrever (e partilhar) scripts simples para automatizar uma ampla variedade de tarefas de rede. Esses scripts são executados em paralelo com a velocidade e eficiência que se espera do Nmap. Os usuários podem contar com a crescente e diversificada base de dados de scripts distribuídos com o Nmap, ou escrever o seu próprio para atender às necessidades personalizadas, os scripts Nmap Scripting Engine são implementados usando linguagem de programação Lua, Nmap API e um número de realmente poderosas Bibliotecas NSE.
LUA: Lua Tutorials - www.dev-hq.net   NMAP API: Nmap API   NSEDOC: nsedoc (nse)


Os scripts NSE são (pack) em diferentes categorias:
auth, broadcast, brute, default, discovery, dos, exploit, external, fuzzer, intrusive, malware, safe,vuln
configuando o nosso script NSE dentro de uma destas categorias permite-nos chama-lo a ele e todos
os scripts dentro dessa mesma categoria usando a 'flag' (--script <categoria> <target>). o seguinte
exemplo "irá correr o nosso script e todos que se encontrarem dentro da categoria 'discovery'"
exemplo: nmap -sS -Pn -p 80 --script discovery <target>


Os scripts NSE são divididos em 4 secções:
O 'HEAD' contém meta-dados que descreve a funcionalidade do modulo, autor, impacto, categoria e outros dados descritivos.
As 'DEPENDENCIES' (bibliotecas lua necessarias) ao uso da API de programação do nmap
A 'RULE SECTION' define as condições necessárias para o script executar. Esta secção deve conter pelo menos uma função desta lista: portrule, hostrule, prerule, postrule. Para os fins deste tutorial (e a maioria dos scripts), vou concentrar-se no portrule que pode executar verificações sobre ambas as propriedades de host e porta antes de correr o script. No script abaixo, portrule se aproveita da API do nmap para verificar se há alguma porta http aberta para executar os commands da secção 'the action section'.
A 'ACTION SECTION' define a lógica do script, Na tradição de K&R (kernighan & ritchie) eu vou simplesmente dar a saída "Olá, mundo!" para qualquer porta aberta http usando a API 'return' para fazer o output.
           


                            

hello.nse

Vamos começar com um script que simplesmente irá imprimir "hello world" para todas as portas HTTP encontradas abertas.
                             Abra um editor de texto e escreva o seguinte trecho em 'hello.nse' em seu diretório home.
  1. ------------------------------ The Head Section ------------------------------
  2. description = [[
  3. Author: r00t-3xp10it
  4. INURLBR AULA - escrevendo o meu primeiro script NSE para o nmap
  5. Some Syntax examples:
  6. nmap --script-help hello.nse
  7. nmap -sS -Pn -80 --script hello.nse <target>
  8. ]]
  9. author = "r00t-3xp10it"
  10. categories = {"discovery", "safe"}
  11. ------------------------------ Dependencies ------------------------------
  12. local http = require "http"
  13. local shortport = require "shortport"
  14. ------------------------------ The Rule Section ------------------------------
  15. portrule = shortport.http
  16. ------------------------------ The Action Section ------------------------------
  17. action = function(host, port)
  18.     return "Hello world!"
  19. end

Descrição: na secção 'head' definimos a categoria como 'discovery and safe', para correr este script e todos contidos na categoria 'discovery' basta executarmos 'nmap -sV -p 80,8080 --script discovery <target>', na secção 'Dependencies' chamamos as bibliotecas 'http & shortport', na secção 'the rule section' vamos nos servir da biblioteca 'shortport' para verificar se o <target> está a correr alguma porta com o protocol 'http' abertas, para podermos executar a secção 'the action section' a 'funtion(host, port)' vai executar o command "hello world!" (display no terminal), P.S. a portrule 'shortport.http' verifica todos os protocolos http based, like: http, https, ipp, http-alt, https-alt, vnc-http, oem-agent, soap, http-proxy, (descrição da biblioteca 'shortport.lua')...
shortport.lua: nmap.org/nmap/nselib/shortport.lua

hello.nse output:
exporte o script para a base de dados do nmap ('/nmap/scripts/' folder)
sudo cp hello.nse /usr/share/nmap/scripts/hello.nse
actualize a base de dados do NSE
sudo nmap --script-updatedb
visualizar a descrição do modulo
sudo nmap --script-help hello.nse
corra o script
sudo nmap -sV -Pn -p 80,443,445,8080 --script hello.nse <target>

file-checker.nse

Vamos construir um Script NSE rápido para verificar se o /path/arquivo/pasta selecionado existe no alvo webserver verificando os codigos de retorno da API do google. "o comportamento padrão será procurar o arquivo robots.txt se não for introduzido um argumento (@args) para procurar um file/path diferente", os '@argumentos' são lançados pela 'flag' --script-args <nome do argumento>=  neste caso vai servir para pedir ao utilizador para entrar um nome diferente do valor default (/robots.txt) a procurar no target, vamos construir o proximo script em 4 secções 'head, dependencies, the rules section, the action section' para mais facil compreenção:


---'THE HEAD SECTION'---
  1. description = [[
  2. Author: r00t-3xp10it
  3. Quick NSE script to check if the selected file/path/folder exists
  4. on target webserver by checking google API return codes.
  5. 'default behavior its to search for robots.txt file'
  6. Some Syntax examples:
  7. nmap -sS -Pn -80 --script file-checker.nse <target>
  8. nmap -sS -Pn -80 --script file-checker.nse --script-args file=/privacy/ <target>
  9. nmap -sS -sV -iR 40 -80 --open --script file-checker.nse --script-args file=/robots.txt
  10. ]]
  11. ---
  12. -- @usage
  13. -- nmap --script-help file-checker.nse
  14. -- nmap -sS -Pn -p 80 --script file-checker.nse <target>
  15. -- nmap -sS -Pn -p 80 --script file-checker.nse --script-args file=/robots.txt <target>
  16. -- nmap -sS -Pn -p 80 --script file-checker.nse --script-args file=/privacy/ 113.38.34.72
  17. -- @output
  18. -- PORT   STATE SERVICE
  19. -- 80/tcp open  http
  20. -- | file-checker: /robots.txt
  21. -- |             : STRING FOUND...
  22. -- |_            : returned 200 OK
  23. -- @args file-checker.file the file/path name to search. Default: /robots.txt
  24. ---
  25. author = "r00t-3xp10it"
  26. license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
  27. categories = {"discovery", "safe"}



---'DEPENDENCIES'---
  1. -- Dependencies (lua libraries)
  2. local shortport = require "shortport"
  3. local stdnse = require ('stdnse')
  4. local http = require "http"



---'THE RULES SECTION'---
  1. -- Port rule will only execute if port 80/tcp http is open
  2. portrule = shortport.port_or_service({80}, "http", "tcp", "open")
  3. -- Seach for string stored in variable @args.file or use default
  4. local file = stdnse.get_script_args(SCRIPT_NAME..".file") or "/robots.txt"
Descrição: a biblioteca 'shortport' vai se servir da função 'port_or_service' para só executar a secção 'the action section' se todos os valores retornarem correctos (port 80 tcp http open), a biblioteca 'stdnse.get_script_args' vai ler o que foi inserido no @argumento (e procurar por essa string) ou então vai procurar pelo valor default (/robots.txt) se não for utilizada a 'flag' '--script-args file=' 
'shortport.port_or_service': nsedoc/lib/shortport.html#port_or_service
'stdnse.get_script_args': nsedoc/lib/stdnse.html#get_script_args



---'THE ACTION SECTION'---
  1. action = function(host, port)
  2. local response = http.get(host, port, file)
  3. -- Check google API return codes to determine if file exists
  4. if (response.status == 200 ) then
  5. return file.."\n            : STRING FOUND...\n            : returned 200 OK\n"
  6. elseif (response.status == 400 ) then
  7. return file.."\n            : BadRequest...\n            : returned 400 BadRequest\n"
  8. elseif (response.status == 302 ) then
  9. return file.."\n            : Redirected...\n            : returned 302 Redirected\n"
  10. elseif (response.status == 401 ) then
  11. return file.."\n            : Unauthorized...\n            : returned 401 Unauthorized\n"
  12. elseif (response.status == 404 ) then
  13. return file.."\n            : STRING NOT FOUND...\n            : returned 404 NOT FOUND\n"
  14. elseif (response.status == 403 ) then
  15. return file.."\n            : Forbidden...\n            : returned 403 Forbidden\n"
  16. elseif (response.status == 503 ) then
  17. return file.."\n            : Service_unavailable...\n            : returned 503 Service_unavailable\n"
  18. else
  19. return file.."\n            : UNDEFINED ERROR...\n            : returned "..response.status.."\n"
  20. end
  21. end
Descrição: a função 'action = function(host, port)' vai executar os commands no <target>, na função seguinte a biblioteca 'http.get' retorna um recurso com um pedido GET, a API NSE  'response.status' vai verificar o codigo de retorno da API do google para determinar se o file existe, e vamos nos servir da API 'return' vai fazer o display do output...
'http.get': nmap.org/nsedoc/lib/http.html#get

file-checker.nse output:

download file-checker.nse: file-checker.nse
exporte o script para a base de dados do nmap ('/nmap/scripts/' folder)
sudo cp file-checker.nse /usr/share/nmap/scripts/file-checker.nse
actualize a base de dados do NSE
sudo nmap --script-updatedb
visualizar a descriçao do modulo
sudo nmap --script-help file-checker.nse
corra o script
sudo nmap -sV -Pn -p 80,443,445,8080 --script file-checker.nse <target>
sudo nmap -sV -Pn -p 80,443,445,8080 --script file-checker.nse --script-args file=/etc/passwd <target>    

ms15-034.nse

Detecta a vulnerabilidade MS15-034 (HTTP.sys) em servidores Microsoft IIS. e explora a condição denial-of-service usando argumentos de script (--script-args D0S=exploit) ou podemos verificar (escanear) ainda mais usando outro argumento (--script-args uri =/wellcome.png), o comportamento padrão 'default' será verificar pela existencia da vulnerabilidade, e só se for introduzido o @argumento D0S (--script-args D0S=exploit) é que será explorado o denial-of-service.
versões afetadas são o Windows 7,8,8.1, Windows Server 2008 R2, 2012 e 2012R2.
An analysis of ms15-034: an-analysis-of-ms15-034



1º - download ms15-034.nse: ms15-034.nse
 2º - exporte o script para a base de dados do nmap ('/nmap/scripts/' folder)
sudo cp ms15-034.nse /usr/share/nmap/scripts/ms15-034.nse
3º - actualize a base de dados do NSE
sudo nmap --script-updatedb
4º - visualizar a descriçao do modulo
sudo nmap --script-help ms15-034.nse
5º - corra o script
sudo nmap -sV -Pn -p 80 --script ms15-034.nse <target>
sudo nmap -sV -Pn -p 80,443,445,8080 --script ms15-034.nse --script-args D0S=exploit <target>



How To Display outputs:


usando return
  1. -- writting output to table (using return)
  2. if (response.status == 200) then
  3. return file.." FOUND..."
  4.   elseif (response.status == 404) then
  5.   return file.." NOT FOUND..."
  6. else
  7.   return file.." undefined"..response.status
  8.   end
  9. end



usando table.insert
  1. --writting output to table (using 'table.insert')
  2. if (response.status == 200) then
  3.   table.insert(response, "  STRING FOUND: "..file)
  4.   table.insert(response, "  returned 200 OK")
  5.   elseif (response.status == 404) then
  6.   table.insert(response, "  STRING NOT FOUND: "..file)
  7.   table.insert(response, "  returned 404 NOT FOUND")
  8. else
  9.   table.insert(response, "  STRING : "..file)
  10.   table.insert(response, "  returned "..response.status)
  11. end

  12. --writting response output to table
  13. return stdnse.format_output(true, response)
  14. end


usando stdnse.output_table()

  1. -- writting output to table using stdnse.output_table()
  2. -- THE RULES SECTION --
  3. local file = stdnse.get_script_args(SCRIPT_NAME..".file") or "/robots.txt"
  4. local output = stdnse.output_table()  -- fazendo table em 'the rules section'
  5. -- THE ACTION SECTION --
  6. if (response.status == 200) then
  7.   output.found = {}
  8.   output.found[#output.found + 1] = file
  9.   output.found[#output.found + 1] = "/privacy/"
  10.   output.found[#output.found + 1] = "/news/"
  11.   return output
  12. elseif (response.status == 404) then
  13.   output.found = {}
  14.   output.found[#output.found + 1] = file
  15.   output.found[#output.found + 1] = "/privacy/"
  16.   output.found[#output.found + 1] = "/news/"
  17.   return output
  18. else
  19.   output.found = {}
  20.   output.found[#output.found + 1] = file
  21.   output.found[#output.found + 1] = "/privacy/"
  22.   output.found[#output.found + 1] = "/news/"
  23.   return output
  24. end
  25. return output
  26. end
                        

Nenhum comentário:

Postar um comentário

............