Como Analisar Resultados de Varredura Nmap em Formato XML

NmapBeginner
Pratique Agora

Introdução

No campo da Cibersegurança, compreender e analisar os resultados de varreduras de rede é crucial para manter uma infraestrutura segura. Nmap (Network Mapper) é uma das ferramentas mais amplamente utilizadas para descoberta de rede e auditoria de segurança. Este tutorial irá guiá-lo através do processo de interpretação dos resultados de varreduras Nmap em formato XML, equipando-o com as habilidades necessárias para aproveitar esta poderosa ferramenta para suas necessidades de Cibersegurança.

Ao final deste laboratório, você saberá como executar varreduras Nmap com saída XML, entender a estrutura dos dados XML, extrair informações valiosas usando ferramentas de linha de comando e scripts Python, e identificar potenciais preocupações de segurança a partir dos resultados da varredura.

Este é um Lab Guiado, que fornece instruções passo a passo para ajudá-lo a aprender e praticar. Siga as instruções cuidadosamente para completar cada etapa e ganhar experiência prática. Dados históricos mostram que este é um laboratório de nível intermediário com uma taxa de conclusão de 74%. Recebeu uma taxa de avaliações positivas de 96% dos estudantes.

Instalando o Nmap e Executando uma Varredura XML Básica

O que é Nmap?

Nmap (Network Mapper) é um utilitário de código aberto e gratuito para descoberta de rede e auditoria de segurança. Profissionais de segurança em todo o mundo o utilizam para identificar quais dispositivos estão rodando em suas redes, descobrir hosts disponíveis e os serviços que eles oferecem, encontrar portas abertas e detectar vulnerabilidades de segurança.

Instalando o Nmap

Vamos começar instalando o Nmap em nosso sistema. Abra uma janela de terminal e insira os seguintes comandos:

sudo apt update
sudo apt install nmap -y

Após a conclusão da instalação, verifique se o Nmap foi instalado corretamente, verificando sua versão:

nmap --version

Você deve ver uma saída semelhante a esta:

Nmap version 7.80 ( https://nmap.org )
Platform: x86_64-pc-linux-gnu
Compiled with: liblua-5.3.3 openssl-1.1.1f libssh2-1.8.0 libz-1.2.11 libpcre-8.39 nmap-libpcap-1.9.1 nmap-libdnet-1.12 ipv6
Compiled without:
Available nsock engines: epoll poll select

Executando uma Varredura Nmap Básica com Saída XML

O Nmap pode salvar seus resultados de varredura em formato XML, o que fornece uma maneira estruturada de analisar os dados programaticamente. Vamos executar uma varredura básica de nossa máquina local e salvar os resultados em formato XML:

sudo nmap -A -T4 -oX ~/project/localhost_scan.xml localhost

Este comando executa:

  • -A: Habilita a detecção de SO (Sistema Operacional), detecção de versão, varredura de script e traceroute
  • -T4: Define o modelo de tempo para "agressivo"
  • -oX: Especifica que a saída deve ser em formato XML
  • localhost: O alvo a ser varrido (nossa própria máquina)

A varredura pode levar um ou dois minutos para ser concluída. Quando terminar, você verá um resumo dos resultados da varredura no terminal.

Visualizando os Resultados da Varredura XML

Vamos examinar o arquivo XML que acabamos de criar:

cat ~/project/localhost_scan.xml

A saída será um documento XML estruturado contendo informações detalhadas sobre a varredura. Pode parecer complicado no início, mas aprenderemos como interpretá-lo nos próximos passos.

Vamos também verificar a estrutura básica do arquivo XML usando o comando head:

head -n 20 ~/project/localhost_scan.xml

Isso mostra as primeiras 20 linhas do arquivo XML, dando-nos um vislumbre de sua estrutura.

Examinando a Estrutura da Saída XML

Compreendendo o Formato XML do Nmap

A saída XML do Nmap segue uma estrutura hierárquica que organiza as informações da varredura de maneira lógica. Vamos explorar os principais elementos dessa estrutura:

  1. <nmaprun>: O elemento raiz que contém todas as informações da varredura
  2. <scaninfo>: Detalhes sobre o tipo e os parâmetros da varredura
  3. <host>: Informações sobre cada host varrido
    • <status>: Se o host está ativo ou inativo
    • <address>: Endereços IP e MAC
    • <hostnames>: Nomes DNS
    • <ports>: Detalhes sobre as portas varridas
      • <port>: Informações sobre uma porta específica
        • <state>: Se a porta está aberta, fechada ou filtrada
        • <service>: Informações do serviço, se disponíveis
    • <os>: Resultados da detecção do sistema operacional
    • <times>: Informações de tempo sobre a varredura

Usando Ferramentas de Linha de Comando para Extrair Informações

Arquivos XML podem ser difíceis de ler em sua forma bruta. Vamos usar algumas ferramentas de linha de comando para extrair informações específicas dos nossos resultados de varredura.

Primeiro, vamos contar quantas portas abertas foram encontradas usando grep e wc:

grep -c "state=\"open\"" ~/project/localhost_scan.xml

Este comando procura por instâncias de state="open" no arquivo XML e as conta.

Em seguida, vamos identificar as portas abertas e seus serviços usando grep com a opção -A para mostrar as linhas após a correspondência:

grep -A 3 "state=\"open\"" ~/project/localhost_scan.xml

Isso mostrará cada instância de uma porta aberta junto com as 3 linhas que a seguem, que normalmente incluem informações do serviço.

Também podemos usar xmllint para formatar o arquivo XML para melhor legibilidade. Vamos instalá-lo primeiro:

sudo apt install libxml2-utils -y

Agora, vamos formatar o arquivo XML:

xmllint --format ~/project/localhost_scan.xml > ~/project/formatted_scan.xml

Vamos dar uma olhada no arquivo formatado:

head -n 50 ~/project/formatted_scan.xml

Isso exibe as primeiras 50 linhas do arquivo XML formatado, que deve ser muito mais fácil de ler.

Finalmente, vamos extrair informações específicas sobre o status do host usando xmllint com XPath:

xmllint --xpath "//host/status/@state" ~/project/localhost_scan.xml

Este comando usa XPath para extrair o atributo state de todos os elementos status sob os elementos host.

Analisando XML do Nmap com Python

Introdução à Análise XML com Python

Python fornece bibliotecas poderosas para analisar arquivos XML. Nesta etapa, criaremos um script Python simples para analisar nossos resultados de varredura do Nmap e exibi-los em um formato mais legível.

Criando um Analisador XML Básico

Vamos criar um script Python que usa o módulo xml.etree.ElementTree para analisar o arquivo XML do Nmap. Este módulo está incluído na biblioteca padrão do Python, então não precisamos instalar nada adicional.

Crie um novo arquivo chamado parse_nmap.py no diretório do projeto:

nano ~/project/parse_nmap.py

Copie e cole o seguinte código no editor:

#!/usr/bin/env python3
import xml.etree.ElementTree as ET
import sys

def parse_nmap_xml(xml_file):
    try:
        ## Parse the XML file
        tree = ET.parse(xml_file)
        root = tree.getroot()

        ## Print scan information
        print("Nmap Scan Report")
        print("=" * 50)
        print(f"Scan started at: {root.get('startstr')}")
        print(f"Nmap version: {root.get('version')}")
        print(f"Nmap command: {root.get('args')}")
        print("=" * 50)

        ## Process each host in the scan
        for host in root.findall('host'):
            ## Get host addresses
            for addr in host.findall('address'):
                if addr.get('addrtype') == 'ipv4':
                    ip_address = addr.get('addr')
                    print(f"\nHost: {ip_address}")

            ## Get hostname if available
            hostnames = host.find('hostnames')
            if hostnames is not None:
                for hostname in hostnames.findall('hostname'):
                    print(f"Hostname: {hostname.get('name')}")

            ## Get host status
            status = host.find('status')
            if status is not None:
                print(f"Status: {status.get('state')}")

            ## Process ports
            ports = host.find('ports')
            if ports is not None:
                print("\nOpen Ports:")
                print("-" * 50)
                print(f"{'PORT':<10}{'STATE':<10}{'SERVICE':<15}{'VERSION'}")
                print("-" * 50)

                for port in ports.findall('port'):
                    port_id = port.get('portid')
                    protocol = port.get('protocol')

                    ## Get port state
                    state = port.find('state')
                    port_state = state.get('state') if state is not None else "unknown"

                    ## Skip closed ports
                    if port_state != "open":
                        continue

                    ## Get service information
                    service = port.find('service')
                    if service is not None:
                        service_name = service.get('name', '')
                        service_product = service.get('product', '')
                        service_version = service.get('version', '')
                        service_info = f"{service_product} {service_version}".strip()
                    else:
                        service_name = ""
                        service_info = ""

                    print(f"{port_id}/{protocol:<5} {port_state:<10}{service_name:<15}{service_info}")

            ## Get OS detection information
            os = host.find('os')
            if os is not None:
                print("\nOS Detection:")
                for osmatch in os.findall('osmatch'):
                    print(f"OS: {osmatch.get('name')} (Accuracy: {osmatch.get('accuracy')}%)")

    except ET.ParseError as e:
        print(f"Error parsing XML file: {e}")
        return False
    except Exception as e:
        print(f"Error: {e}")
        return False

    return True

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print(f"Usage: {sys.argv[0]} <nmap_xml_file>")
        sys.exit(1)

    xml_file = sys.argv[1]
    if not parse_nmap_xml(xml_file):
        sys.exit(1)

Salve o arquivo pressionando Ctrl+O, depois Enter e saia do nano com Ctrl+X.

Agora, torne o script executável:

chmod +x ~/project/parse_nmap.py

Executando o Analisador

Vamos executar nosso script Python no arquivo XML do Nmap que criamos anteriormente:

python ~/project/parse_nmap.py ~/project/localhost_scan.xml

Você deve ver uma saída bem formatada dos resultados da varredura, incluindo:

  • Informações básicas da varredura
  • Detalhes do host
  • Portas e serviços abertos
  • Resultados da detecção do sistema operacional, se disponíveis

Esta saída formatada é muito mais fácil de ler do que o arquivo XML bruto e destaca as informações mais importantes da varredura.

Compreendendo o Código do Analisador

Vamos revisar o que nosso script Python faz:

  1. Ele usa xml.etree.ElementTree para analisar o arquivo XML
  2. Ele extrai informações gerais da varredura do elemento raiz
  3. Para cada host encontrado na varredura:
    • Ele extrai endereços IP e nomes de host
    • Ele determina se o host está ativo ou inativo
    • Ele lista todas as portas abertas, incluindo número da porta, protocolo, nome do serviço e versão
    • Ele extrai informações de detecção do SO, se disponíveis

Essa abordagem estruturada nos permite focar nas informações mais relevantes, ignorando a complexidade do XML.

Extraindo Informações Relevantes para Segurança

Insights de Segurança das Varreduras do Nmap

Agora que podemos analisar dados XML do Nmap, vamos estender nosso script para extrair informações relevantes para segurança. Isso inclui:

  1. Identificar portas abertas potencialmente arriscadas
  2. Detectar versões de serviço desatualizadas
  3. Resumir preocupações de segurança

Vamos criar uma versão aprimorada do nosso analisador que se concentra na análise de segurança.

Criando um Script de Análise de Segurança

Crie um novo arquivo chamado security_analysis.py:

nano ~/project/security_analysis.py

Copie e cole o seguinte código:

#!/usr/bin/env python3
import xml.etree.ElementTree as ET
import sys
import datetime

## Define potentially risky ports
HIGH_RISK_PORTS = {
    '21': 'FTP - File Transfer Protocol (often unencrypted)',
    '23': 'Telnet - Unencrypted remote access',
    '25': 'SMTP - Email transfer (may allow relay)',
    '445': 'SMB - Windows file sharing (potential target for worms)',
    '3389': 'RDP - Remote Desktop Protocol (target for brute force)',
    '1433': 'MSSQL - Microsoft SQL Server',
    '3306': 'MySQL - Database access',
    '5432': 'PostgreSQL - Database access'
}

## Services with known security issues
OUTDATED_SERVICES = {
    'ssh': [
        {'version': '1', 'reason': 'SSHv1 has known vulnerabilities'},
        {'version': 'OpenSSH 7', 'reason': 'Older OpenSSH versions have multiple CVEs'}
    ],
    'http': [
        {'version': 'Apache httpd 2.2', 'reason': 'Apache 2.2.x is end-of-life'},
        {'version': 'Apache httpd 2.4.1', 'reason': 'Apache versions before 2.4.30 have known vulnerabilities'},
        {'version': 'nginx 1.14', 'reason': 'Older nginx versions have security issues'}
    ]
}

def analyze_security(xml_file):
    try:
        ## Parse the XML file
        tree = ET.parse(xml_file)
        root = tree.getroot()

        ## Prepare the report
        report = []
        report.append("NMAP SECURITY ANALYSIS REPORT")
        report.append("=" * 50)
        report.append(f"Report generated on: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
        report.append(f"Scan started at: {root.get('startstr')}")
        report.append(f"Scan command: {root.get('args')}")
        report.append("=" * 50)

        ## Track security findings
        high_risk_services = []
        potentially_outdated = []
        exposed_services = []

        ## Process each host in the scan
        for host in root.findall('host'):
            ## Get host addresses
            ip_address = None
            for addr in host.findall('address'):
                if addr.get('addrtype') == 'ipv4':
                    ip_address = addr.get('addr')

            hostname = "Unknown"
            hostnames = host.find('hostnames')
            if hostnames is not None:
                hostname_elem = hostnames.find('hostname')
                if hostname_elem is not None:
                    hostname = hostname_elem.get('name')

            report.append(f"\nHOST: {ip_address} ({hostname})")
            report.append("-" * 50)

            ## Process ports
            ports = host.find('ports')
            if ports is None:
                report.append("No port information available")
                continue

            open_ports = 0
            for port in ports.findall('port'):
                port_id = port.get('portid')
                protocol = port.get('protocol')

                ## Get port state
                state = port.find('state')
                if state is None or state.get('state') != "open":
                    continue

                open_ports += 1

                ## Get service information
                service = port.find('service')
                if service is None:
                    service_name = "unknown"
                    service_product = ""
                    service_version = ""
                else:
                    service_name = service.get('name', 'unknown')
                    service_product = service.get('product', '')
                    service_version = service.get('version', '')

                service_full = f"{service_product} {service_version}".strip()

                ## Check if this is a high-risk port
                if port_id in HIGH_RISK_PORTS:
                    high_risk_services.append(f"{ip_address}:{port_id} ({service_name}) - {HIGH_RISK_PORTS[port_id]}")

                ## Check for outdated services
                if service_name in OUTDATED_SERVICES:
                    for outdated in OUTDATED_SERVICES[service_name]:
                        if outdated['version'] in service_full:
                            potentially_outdated.append(f"{ip_address}:{port_id} - {service_name} {service_full} - {outdated['reason']}")

                ## Track all exposed services
                exposed_services.append(f"{ip_address}:{port_id}/{protocol} - {service_name} {service_full}")

            report.append(f"Open ports: {open_ports}")

        ## Add security findings to report
        report.append("\nSECURITY FINDINGS")
        report.append("=" * 50)

        ## High-risk services
        report.append("\nHIGH-RISK SERVICES")
        report.append("-" * 50)
        if high_risk_services:
            for service in high_risk_services:
                report.append(service)
        else:
            report.append("No high-risk services detected")

        ## Potentially outdated services
        report.append("\nPOTENTIALLY OUTDATED SERVICES")
        report.append("-" * 50)
        if potentially_outdated:
            for service in potentially_outdated:
                report.append(service)
        else:
            report.append("No potentially outdated services detected")

        ## Exposed services inventory
        report.append("\nEXPOSED SERVICES INVENTORY")
        report.append("-" * 50)
        if exposed_services:
            for service in exposed_services:
                report.append(service)
        else:
            report.append("No exposed services detected")

        ## Write the report to a file
        report_file = "security_report.txt"
        with open(report_file, 'w') as f:
            f.write('\n'.join(report))

        print(f"Security analysis complete. Report saved to {report_file}")

        ## Display a summary
        print("\nSummary:")
        print(f"- High-risk services: {len(high_risk_services)}")
        print(f"- Potentially outdated services: {len(potentially_outdated)}")
        print(f"- Total exposed services: {len(exposed_services)}")

    except ET.ParseError as e:
        print(f"Error parsing XML file: {e}")
        return False
    except Exception as e:
        print(f"Error: {e}")
        return False

    return True

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print(f"Usage: {sys.argv[0]} <nmap_xml_file>")
        sys.exit(1)

    xml_file = sys.argv[1]
    if not analyze_security(xml_file):
        sys.exit(1)

Salve o arquivo pressionando Ctrl+O, depois Enter e saia do nano com Ctrl+X.

Torne o script executável:

chmod +x ~/project/security_analysis.py

Executando a Análise de Segurança

Vamos executar nosso script de análise de segurança no arquivo XML do Nmap:

cd ~/project
./security_analysis.py localhost_scan.xml

O script analisará os resultados da varredura e gerará um relatório de segurança focado em potenciais vulnerabilidades, salvando-o em um arquivo chamado security_report.txt.

Vamos olhar o conteúdo do relatório:

cat ~/project/security_report.txt

Compreendendo a Análise de Segurança

O script de análise de segurança executa várias funções importantes:

  1. Identificação de Portas de Alto Risco: Ele identifica portas comumente exploradas, como FTP (21), Telnet (23) e RDP (3389), que são alvos frequentes de invasores.

  2. Detecção de Serviços Desatualizados: Ele verifica versões mais antigas de serviços como SSH, Apache e nginx que podem ter vulnerabilidades de segurança conhecidas.

  3. Inventário de Serviços Expostos: Ele cria um inventário completo de todas as portas e serviços abertos, o que é valioso para auditoria de segurança.

  4. Categorização de Risco: Ele organiza as descobertas por nível de risco para ajudar a priorizar as melhorias de segurança.

Este tipo de análise é crucial para que os profissionais de segurança identifiquem potenciais vulnerabilidades em uma rede antes que os invasores possam explorá-las.

Estendendo a Análise

Em um cenário do mundo real, você pode querer estender esta análise:

  1. Adicionando mais portas de alto risco à lista de detecção
  2. Atualizando as definições de serviço desatualizadas com as informações de vulnerabilidade mais recentes
  3. Integrando com bancos de dados de vulnerabilidades para verificar CVEs (Common Vulnerabilities and Exposures) conhecidas
  4. Adicionando recomendações para a correção de problemas detectados

A capacidade de analisar programaticamente dados XML do Nmap é uma habilidade poderosa para profissionais de segurança cibernética, pois permite a avaliação automatizada de vulnerabilidades e a integração com sistemas maiores de monitoramento de segurança.

Resumo

Parabéns por concluir este laboratório sobre a análise de resultados de varredura do Nmap em formato XML. Você aprendeu várias habilidades importantes:

  1. Instalação e Execução do Nmap: Você aprendeu como instalar o Nmap e executar varreduras com saída XML, fornecendo uma base para reconhecimento de rede.

  2. Compreensão da Estrutura XML: Você explorou a estrutura dos arquivos XML do Nmap e usou ferramentas de linha de comando para extrair informações específicas, dando a você a capacidade de analisar rapidamente os resultados da varredura.

  3. Análise de XML com Python: Você criou um script Python para analisar e exibir os resultados da varredura do Nmap em um formato legível, demonstrando como trabalhar programaticamente com dados estruturados.

  4. Análise de Segurança: Você estendeu suas habilidades em Python para analisar os resultados da varredura em busca de preocupações de segurança, identificando serviços potencialmente arriscados e gerando um relatório de segurança abrangente.

Essas habilidades são essenciais para profissionais de segurança cibernética que precisam realizar avaliações de rede, varreduras de vulnerabilidade e auditorias de segurança. A capacidade de automatizar a análise dos resultados do Nmap permite um monitoramento de segurança mais eficiente e completo.

Você pode aprimorar ainda mais essas habilidades:

  • Explorando técnicas de varredura do Nmap mais avançadas
  • Integrando os resultados da varredura com outras ferramentas de segurança
  • Criando algoritmos de análise mais sofisticados
  • Desenvolvendo ferramentas de visualização para dados de varredura

Lembre-se de que a varredura de rede só deve ser realizada em redes que você possui ou para as quais tem permissão explícita para varrer, pois a varredura não autorizada pode ser ilegal e antiética.