{"uuid": "31dc2511-a3da-41e3-8d6d-39d5c67b6243", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2012-5627", "type": "seen", "source": "https://gist.github.com/GustavoLopreto/2028a93a87ebc86d6cb797b2b5907f4d", "content": "#!/usr/bin/env python3\n\"\"\"\nCYMAG Nmap Analyzer v3.0\nEquipe CYMAG | SENAI Seguranca Cibernetica 2026\nUso: python3 cymag_analyzer.py scan.xml -o relatorio.txt --csv achados.csv\n\"\"\"\n\nimport xml.etree.ElementTree as ET\nimport argparse, csv, sys\nfrom datetime import datetime\n\nPORTAS_CRITICAS = {\n    445:  {\"s\": \"SMB\",          \"r\": \"CRITICO\", \"cve\": \"CWE-300 / CVE-2017-0144\", \"d\": \"SMB exposto - vetor primario de ransomware (EternalBlue/WannaCry)\"},\n    3389: {\"s\": \"RDP\",          \"r\": \"ALTO\",    \"cve\": \"CVE-2019-0708\",           \"d\": \"RDP exposto - BlueKeep, brute force facilitado sem NLA\"},\n    389:  {\"s\": \"LDAP\",         \"r\": \"ALTO\",    \"cve\": \"CWE-862\",                 \"d\": \"LDAP - bind anonimo pode expor estrutura do Active Directory\"},\n    88:   {\"s\": \"Kerberos\",     \"r\": \"ALTO\",    \"cve\": \"CWE-287\",                 \"d\": \"Kerberos - AS-REP Roasting e Kerberoasting possiveis\"},\n    1880: {\"s\": \"Node-RED\",     \"r\": \"CRITICO\", \"cve\": \"CWE-306\",                 \"d\": \"Node-RED sem autenticacao padrao - painel IoT acessivel livremente\"},\n    1883: {\"s\": \"MQTT\",         \"r\": \"CRITICO\", \"cve\": \"CWE-306\",                 \"d\": \"MQTT Broker sem autenticacao e sem TLS - mensagens IoT expostas\"},\n    3307: {\"s\": \"MySQL\",        \"r\": \"CRITICO\", \"cve\": \"CVE-2012-5627\",           \"d\": \"MySQL 5.5.62 - EOL desde 2018, sem patches, multiplas CVEs abertas\"},\n    80:   {\"s\": \"HTTP\",         \"r\": \"MEDIO\",   \"cve\": \"CWE-319\",                 \"d\": \"HTTP sem TLS - dados trafegam em texto claro\"},\n    22:   {\"s\": \"SSH\",          \"r\": \"BAIXO\",   \"cve\": \"N/A\",                     \"d\": \"SSH exposto - versao recente, verificar configuracao de acesso\"},\n    5985: {\"s\": \"WinRM\",        \"r\": \"ALTO\",    \"cve\": \"CWE-284\",                 \"d\": \"WinRM - gerenciamento remoto Windows exposto\"},\n    135:  {\"s\": \"RPC\",          \"r\": \"MEDIO\",   \"cve\": \"CWE-284\",                 \"d\": \"RPC Endpoint Mapper - enumeracao de servicos Windows possivel\"},\n    139:  {\"s\": \"NetBIOS\",      \"r\": \"MEDIO\",   \"cve\": \"CWE-200\",                 \"d\": \"NetBIOS - LLMNR poisoning, vazamento de informacoes de rede\"},\n    5040: {\"s\": \"Desconhecido\", \"r\": \"MEDIO\",   \"cve\": \"N/A\",                     \"d\": \"Servico nao identificado na porta 5040 - investigar\"},\n}\n\nORDEM = [\"CRITICO\", \"ALTO\", \"MEDIO\", \"BAIXO\"]\n\ndef parse_nmap(arquivo):\n    try:\n        tree = ET.parse(arquivo)\n    except FileNotFoundError:\n        print(f\"[ERRO] Arquivo nao encontrado: {arquivo}\")\n        sys.exit(1)\n    except ET.ParseError as e:\n        print(f\"[ERRO] XML invalido: {e}\")\n        sys.exit(1)\n    root = tree.getroot()\n    alertas = []\n    for host in root.findall(\"host\"):\n        addr_el = host.find(\"address[@addrtype='ipv4']\")\n        if addr_el is None:\n            continue\n        ip = addr_el.get(\"addr\", \"N/A\")\n        hostname_el = host.find(\".//hostname\")\n        hostname = hostname_el.get(\"name\", \"\") if hostname_el is not None else \"\"\n        for port in host.findall(\".//port\"):\n            estado = port.find(\"state\")\n            if estado is None or estado.get(\"state\") != \"open\":\n                continue\n            portid = int(port.get(\"portid\", 0))\n            proto = port.get(\"protocol\", \"tcp\")\n            svc = port.find(\"service\")\n            nome_svc = svc.get(\"name\", \"?\") if svc is not None else \"?\"\n            produto   = svc.get(\"product\", \"\") if svc is not None else \"\"\n            versao    = svc.get(\"version\", \"\") if svc is not None else \"\"\n            ver_completa = f\"{produto} {versao}\".strip()\n            if portid in PORTAS_CRITICAS:\n                info = PORTAS_CRITICAS[portid]\n                alertas.append({\n                    \"ip\": ip, \"hostname\": hostname, \"porta\": portid,\n                    \"proto\": proto, \"servico\": nome_svc, \"versao\": ver_completa,\n                    \"risco\": info[\"r\"], \"cve\": info[\"cve\"], \"descricao\": info[\"d\"],\n                })\n    return sorted(alertas, key=lambda x: (ORDEM.index(x[\"risco\"]), x[\"ip\"], x[\"porta\"]))\n\ndef gerar_relatorio(alertas, arquivo_saida=None):\n    agora = datetime.now().strftime(\"%d/%m/%Y %H:%M\")\n    L = []\n    L.append(\"=\" * 70)\n    L.append(\"  CYMAG -- RELATORIO DE PORTAS CRITICAS\")\n    L.append(f\"  Gerado em: {agora}\")\n    L.append(\"  Equipe CYMAG | SENAI Seguranca Cibernetica 2026\")\n    L.append(\"  Rede analisada: 10.10.100.0/24\")\n    L.append(\"=\" * 70)\n    risco_atual = None\n    for a in alertas:\n        if a[\"risco\"] != risco_atual:\n            risco_atual = a[\"risco\"]\n            L.append(f\"\\n{'\u2500' * 70}\")\n            L.append(f\"  [ {risco_atual} ]\")\n            L.append(f\"{'\u2500' * 70}\")\n        host = a[\"ip\"] + (f\" ({a['hostname']})\" if a[\"hostname\"] else \"\")\n        L.append(f\"\\n  Host    : {host}\")\n        L.append(f\"  Porta   : {a['porta']}/{a['proto']}  ({a['servico']} {a['versao']})\".rstrip())\n        L.append(f\"  CVE/CWE : {a['cve']}\")\n        L.append(f\"  Risco   : {a['descricao']}\")\n    contagem = {r: sum(1 for a in alertas if a[\"risco\"] == r) for r in ORDEM}\n    L.append(f\"\\n{'=' * 70}\")\n    L.append(f\"  RESUMO  -- Total de alertas: {len(alertas)}\")\n    for r in ORDEM:\n        if contagem[r]:\n            L.append(f\"    {r:&lt;10}: {contagem[r]} alerta(s)\")\n    L.append(\"=\" * 70)\n    texto = \"\\n\".join(L)\n    if arquivo_saida:\n        with open(arquivo_saida, \"w\", encoding=\"utf-8\") as f:\n            f.write(texto)\n        print(f\"[OK] Relatorio salvo em: {arquivo_saida}\")\n    else:\n        print(texto)\n    return texto\n\ndef gerar_csv(alertas, arquivo_csv):\n    campos = [\"ip\",\"hostname\",\"porta\",\"proto\",\"servico\",\"versao\",\"risco\",\"cve\",\"descricao\"]\n    with open(arquivo_csv, \"w\", newline=\"\", encoding=\"utf-8\") as f:\n        w = csv.DictWriter(f, fieldnames=campos)\n        w.writeheader()\n        w.writerows(alertas)\n    print(f\"[OK] CSV salvo em: {arquivo_csv}\")\n\ndef main():\n    parser = argparse.ArgumentParser(description=\"CYMAG Nmap Analyzer\")\n    parser.add_argument(\"xml\", help=\"Arquivo XML do Nmap\")\n    parser.add_argument(\"-o\", \"--output\", help=\"Salvar relatorio em .txt\")\n    parser.add_argument(\"--csv\", help=\"Exportar para CSV\")\n    parser.add_argument(\"--only-critical\", action=\"store_true\", help=\"Mostrar so CRITICO e ALTO\")\n    args = parser.parse_args()\n    alertas = parse_nmap(args.xml)\n    if args.only_critical:\n        alertas = [a for a in alertas if a[\"risco\"] in (\"CRITICO\", \"ALTO\")]\n    if not alertas:\n        print(\"[INFO] Nenhuma porta critica encontrada.\")\n        sys.exit(0)\n    gerar_relatorio(alertas, args.output)\n    if args.csv:\n        gerar_csv(alertas, args.csv)\n\nif __name__ == \"__main__\":\n    main()", "creation_timestamp": "2026-06-08T02:37:18.000000Z"}