Todas as bibliotecas KATYUSHASEC · DOCUMENTAÇÃO TÉCNICA

OpenSec

Biblioteca Python para análise de redes, reconhecimento de serviços, recolha de informação web e cifragem de ficheiros.

Python 3.8+ Versão 0.1.0 Referência da API
01 · INSTALAÇÃO

Instalar a OpenSec

A versão publicada no repositório do projeto é a 0.1.0. O comando abaixo utiliza o índice Python configurado para a KatyushaSec.

Terminal
python -m pip install --no-deps --index-url https://packages.katyushasec.net/simple/ opensec==0.1.0
Importante: este comando pressupõe que o pacote e o índice estejam acessíveis no servidor. O gestor MIWA ainda não está disponibilizado neste servidor; por isso, não é apresentado aqui como método de instalação disponível.

Dependência de cifragem

O módulo MelisaCry importa a biblioteca cryptography. Instala-a separadamente:

python -m pip install cryptography

O parâmetro --no-deps impede a instalação automática de dependências. Se outros módulos da biblioteca vierem a exigir dependências adicionais, estas terão de ser instaladas separadamente.

02 · PRIMEIROS PASSOS

Importar os módulos

from OpenSec import Net, WebSec, MelisaCry

print(WebSec.resolve("example.com"))
print(Net.ports("192.168.1.10"))

Os nomes importados são os exportados pelo pacote. As operações de rede devem ser executadas apenas em equipamentos e redes sobre os quais tens autorização.

03 · REFERÊNCIA DA API

Como ler as assinaturas

Um parâmetro com valor atribuído, como timeout=10, tem esse valor por omissão. Parâmetros sem valor predefinido são obrigatórios, salvo indicação contrária.

Os métodos iniciados por _ são auxiliares internos. Não devem ser considerados parte estável da API pública.

MÓDULO A

Net — análise de redes

Disponibiliza funções de descoberta de hosts, consulta de endereços MAC, verificação de portas TCP, identificação aproximada de sistemas operativos, recolha de banners e monitorização de tráfego.

Descoberta de hosts

Net.list_me()

Devolve uma lista com o endereço IP local e os hosts descobertos na rede.

Parâmetros: nenhum.

Retorno: list de endereços IP em formato textual.

from OpenSec import Net

hosts = Net.list_me()
for ip in hosts:
    print(ip)

Net.list_me_mac()

Obtém um mapeamento de endereços IP para endereços MAC conhecidos.

Parâmetros: nenhum.

Retorno: dict no formato {IP: MAC}. O IP local pode ter o valor None.

from OpenSec import Net

for ip, mac in Net.list_me_mac().items():
    print(ip, mac)

Net.me

Propriedade que devolve o IP local guardado pela instância interna de rede.

Parâmetros: nenhum.

Retorno: endereço IP como str.

ip_local = Net.me
print(ip_local)

Portas TCP e identificação de serviços

Net.ports(ip, port_range=None, timeout=1.0)

Verifica a acessibilidade de portas TCP e tenta identificar o serviço através de um banner ou de uma tabela de serviços.

ParâmetroTipoDescrição
ipstr, lista, tuplo ou conjuntoEndereço do alvo autorizado. Pode ser uma coleção de alvos.
port_rangeNone, int ou intervalo de dois elementosNone usa as portas comuns; um inteiro testa uma porta; um tuplo/lista com início e fim inclui ambos os limites.
timeoutfloatTempo limite de cada tentativa TCP, em segundos. Por omissão: 1.0.

Retorno: dicionário ordenado de portas acessíveis para serviços identificados. Com vários alvos, devolve um dicionário por alvo e omite resultados vazios.

# Portas comuns
resultado = Net.ports("192.168.1.10")

# Uma porta
ssh = Net.ports("192.168.1.10", port_range=22)

# Intervalo inclusivo: 20 a 25
servicos = Net.ports("192.168.1.10", port_range=(20, 25))

# Vários alvos autorizados
rede = Net.ports(["192.168.1.10", "192.168.1.20"], timeout=1.5)

A ausência de uma porta no resultado não prova que o serviço não existe: firewalls, filtros, timeout e condições de rede podem influenciar a resposta.

Net.list_SO(ip)

Estima o sistema operativo com base no TTL e em sinais encontrados nos serviços acessíveis. Não é uma identificação definitiva.

Parâmetro: ip — endereço IP ou coleção de endereços.

Retorno individual: dicionário com so, confianca e detalhes. Para uma coleção, devolve um mapeamento de alvo para resultado.

info = Net.list_SO("192.168.1.10")
print(info["so"])
print(info["confianca"])
print(info["detalhes"])

A percentagem representa uma heurística implementada no código, não uma probabilidade estatística validada.

Net.ports_version(ip, port_range=None, timeout=1.0)

Verifica portas TCP acessíveis e tenta extrair a identificação e a versão de serviços através de banners.

ipEndereço IP ou coleção de alvos autorizados.
port_rangePortas comuns por omissão, uma porta inteira ou intervalo inclusivo em tuplo/lista.
timeoutTempo limite TCP em segundos; por omissão, 1.0.

Retorno: dicionário de portas, cada uma com servico, versao e banner. A versão pode ser None se não for detetada.

versoes = Net.ports_version(
    "192.168.1.10",
    port_range=(20, 100),
    timeout=1.5
)

for porta, dados in versoes.items():
    print(porta, dados["servico"], dados["versao"])

Monitorização de tráfego

Net.static(clear_screen=False, sample_time=1.0)

Captura uma amostra de tráfego, converte os pacotes em linhas e apresenta o histórico guardado no terminal.

clear_screenbool. Se True, limpa o terminal antes de apresentar os dados. Por omissão: False.
sample_timefloat. Duração da amostra em segundos. Por omissão: 1.0.

Retorno: lista de linhas geradas para a amostra atual. A tabela apresentada no terminal utiliza o histórico interno, limitado a 500 linhas.

from OpenSec import Net

linhas = Net.static(sample_time=2.0)
print("Linhas desta amostra:", len(linhas))

A implementação apresentada utiliza a interface wlan0. Se essa interface não existir, a captura pode falhar. São também necessários Scapy ou tcpdump, conforme o caminho utilizado, e permissões adequadas.

Net.static_full(interval=1.0)

Repete a captura e a apresentação do tráfego continuamente até o utilizador interromper o processo.

Parâmetro: interval — intervalo de amostragem em segundos; por omissão, 1.0.

Retorno: não foi definido um valor de retorno útil; o método mantém o ciclo ativo e trata KeyboardInterrupt.

Net.static_full(interval=1.0)
# Para parar: Ctrl+C
MÓDULO B

WebSec — análise web e OSINT

Reúne métodos para consultar informações HTTP/TLS, DNS, WHOIS, conteúdo HTML, JavaScript, CSS, ligações, imagens, e-mails, contactos e verificações indicativas de XSS/CSRF.

Informação HTTP e TLS

WebSec.get_info(url, timeout=10)

Recolhe informações gerais sobre o URL, DNS, resposta HTTP, cabeçalhos, título da página, TLS (quando HTTPS) e um resumo WHOIS.

urlURL HTTP/HTTPS; se não tiver esquema, o código acrescenta HTTPS.
timeoutTempo limite do pedido HTTP em segundos; por omissão, 10.

Retorno: dicionário com campos como host, ips, status, headers, titulo, tls e whois_resumo. Os campos disponíveis dependem do resultado da ligação.

info = WebSec.get_info("https://example.com", timeout=10)
print(info.get("status"))
print(info.get("ips"))
print(info.get("tls"))

WebSec.tls_info(host, port=443)

Estabelece uma ligação TLS e lê informações do certificado apresentado pelo servidor.

Parâmetros: host — nome de domínio ou host; port — porta TLS, por omissão 443.

Retorno: dicionário com emissor, sujeito, validade e dias restantes; em caso de falha, devolve um dicionário com erro.

certificado = WebSec.tls_info("example.com")
print(certificado)

DNS, reverso e WHOIS

WebSec.resolve(domain)

Resolve o domínio para os endereços IP encontrados pelo resolvedor do sistema.

Parâmetro: domain — nome do domínio.

Retorno: lista de endereços IP; lista vazia se a resolução falhar.

ips = WebSec.resolve("example.com")
print(ips)

WebSec.reverse(ip)

Tenta obter o nome de host associado a um endereço IP através de DNS reverso.

Parâmetro: ip — endereço IP.

Retorno: nome do host (str) ou None quando não é encontrado.

hostname = WebSec.reverse("8.8.8.8")
print(hostname)

WebSec.whois(domain)

Consulta o servidor WHOIS selecionado a partir do TLD e tenta converter linhas no formato chave/valor para um dicionário.

Parâmetro: domain — domínio a consultar.

Retorno: dicionário com campos encontrados e o texto original em _raw; em caso de falha, devolve erro.

dados = WebSec.whois("example.com")
print(dados)

A disponibilidade e o formato das respostas dependem do servidor WHOIS e do TLD. Nem todos os campos estarão presentes.

WebSec.trace(url_or_ip, max_hops=15)

Executa um rastreio de rota UDP com TTL progressivo.

url_or_ipURL, nome de domínio ou endereço IP de destino.
max_hopsNúmero máximo de saltos; por omissão, 15.

Retorno: lista de dicionários com hop e ip. O valor "*" representa um salto sem resposta recebida dentro do timeout.

rota = WebSec.trace("example.com", max_hops=15)
for salto in rota:
    print(salto["hop"], salto["ip"])

O código utiliza sockets UDP IPv4 e um timeout de dois segundos por salto. Firewalls e routers podem impedir respostas.

Extração de conteúdo web

WebSec.get_html(url, timeout=10)

Obtém o HTML da página, até ao limite de leitura definido no código.

Parâmetros: url — endereço HTTP/HTTPS; timeout — timeout em segundos, por omissão 10.

Retorno: dicionário com URL original/final, estado HTTP e html; em caso de sucesso inclui tamanho.

pagina = WebSec.get_html("https://example.com")
print(pagina.get("status"))
print(pagina.get("html"))

WebSec.get_js(url, timeout=10)

Extrai blocos JavaScript inline e referências a scripts externos presentes no HTML.

Parâmetros: url e timeout (segundos, por omissão 10).

Retorno: dicionário com js_inline e js_externos, além dos metadados da resposta.

scripts = WebSec.get_js("https://example.com")
print(scripts.get("js_inline"))
print(scripts.get("js_externos"))

As referências externas são extraídas do HTML, mas o método não descarrega o conteúdo desses ficheiros.

WebSec.get_css(url, timeout=10)

Extrai blocos CSS inline e referências a folhas de estilo externas.

Parâmetros: url e timeout (segundos, por omissão 10).

Retorno: dicionário com css_inline e css_externos, além dos metadados da resposta.

estilos = WebSec.get_css("https://example.com")
print(estilos.get("css_inline"))
print(estilos.get("css_externos"))

WebSec.get_links(url, timeout=10, internos=True, externos=True, unicos=True)

Extrai ligações HTML e classifica-as como internas ou externas em relação ao domínio da página.

urlURL da página a analisar.
timeoutTimeout HTTP em segundos; por omissão 10.
internosSe True, inclui as ligações internas no resultado; por omissão, True.
externosSe True, inclui as ligações externas; por omissão, True.
unicosSe True, remove URLs duplicados; por omissão, True.

Retorno: dicionário com links.internos, links.externos e links.outros_recursos (formulários e iframes).

links = WebSec.get_links(
    "https://example.com",
    internos=True,
    externos=False,
    unicos=True
)
print(links.get("links"))

WebSec.get_img(url, timeout=10)

Procura referências a imagens em etiquetas img, srcset, CSS inline e elementos input type="image".

Parâmetros: url e timeout em segundos, por omissão 10.

Retorno: objeto ImageSet, iterável e com os métodos urls() e save().

imagens = WebSec.get_img("https://example.com")

for imagem in imagens:
    print(imagem)

print(imagens.urls())

Método associado: ImageSet.urls() devolve uma lista de URLs. ImageSet.save(pasta=".", timeout=15) descarrega as imagens para a pasta indicada.

pastaDiretório de destino; por omissão, ".".
timeoutTimeout por imagem, em segundos; por omissão, 15.

Retorno de save(): dicionário com salvos, erros e pasta. O código limita cada leitura de imagem a 20 MB.

resultado = imagens.save(pasta="./imagens", timeout=15)
print(resultado["salvos"])
print(resultado["erros"])

E-mails e contactos

WebSec.get_email(url, timeout=10, whois=True, profundidade=0)

Procura e-mails no HTML da página e em páginas comuns de contacto. Opcionalmente consulta WHOIS e procura endereços ofuscados.

urlURL ou domínio de destino.
timeoutTimeout de cada pedido em segundos; por omissão 10.
whoisSe True, tenta obter e-mails através do WHOIS; por omissão, True.
profundidadeControla a procura adicional por ligações relacionadas com contacto. Por omissão, 0.

Retorno: dicionário com dominio, emails, fontes e total.

resultado = WebSec.get_email(
    "https://example.com",
    timeout=10,
    whois=True,
    profundidade=0
)
print(resultado["emails"])
print(resultado["fontes"])

WebSec.get_ctt(url, timeout=10)

Extrai potenciais contactos e ligações sociais do HTML de uma página.

Parâmetros: url e timeout em segundos, por omissão 10.

Retorno: dicionário com url, emails, telefones, redes_sociais, possiveis_nomes e enderecos. Se a obtenção da página falhar, devolve os dados de erro disponíveis.

contactos = WebSec.get_ctt("https://example.com")
print(contactos.get("emails"))
print(contactos.get("telefones"))
print(contactos.get("redes_sociais"))

Os resultados são extraídos por padrões textuais e podem incluir falsos positivos ou omitir dados presentes em conteúdo dinâmico.

Verificações XSS e CSRF

WebSec.test_xss(url, payloads=None, timeout=10)

Identifica parâmetros em URLs e formulários, envia cargas de teste e regista possíveis reflexões na resposta. É uma verificação preliminar, não uma confirmação automática de vulnerabilidade explorável.

urlURL de uma aplicação autorizada a testar.
payloadsLista de cargas de teste. None utiliza os padrões definidos pela biblioteca.
timeoutTimeout HTTP em segundos; por omissão 10.

Retorno: objeto XssResult, com to_dict() para obter o dicionário e js(payload) para executar uma verificação com uma carga personalizada.

resultado = WebSec.test_xss(
    "https://staging.example.com/search?q=test",
    timeout=10
)

dados = resultado.to_dict()
print(dados["parametros_testados"])
print(dados["refletidos"])
print(dados["possiveis_xss"])

Para uma carga personalizada:

personalizado = resultado.js("<script>alert(1)</script>")
print(personalizado.to_dict())

O código não executa JavaScript no navegador: procura reflexões na resposta HTTP. A ausência de reflexão não prova que a aplicação está segura, e uma reflexão não prova, por si só, XSS explorável.

WebSec.test_crf(url, payloads=None, timeout=10)

Analisa formulários HTML à procura de campos cujos nomes pareçam indicar um token CSRF e regista se as cargas enviadas aparecem nas respostas.

urlURL de uma aplicação autorizada a testar.
payloadsLista de cargas personalizadas; None usa os padrões internos.
timeoutTimeout HTTP em segundos; por omissão 10.

Retorno: objeto de resultado com to_dict() e js(payload). O dicionário contém formularios, formularios_sem_token e testes.

resultado = WebSec.test_crf(
    "https://staging.example.com/form",
    timeout=10
)
dados = resultado.to_dict()
print(dados["formularios"])
print(dados["formularios_sem_token"])
print(dados["testes"])

Nota: o nome real do método no código é test_crf, não test_csrf. A deteção por nomes de campos não substitui a validação do mecanismo CSRF do servidor. Não executar estes testes em sistemas de terceiros sem autorização.

MÓDULO C

MelisaCry — cifragem de ficheiros

O módulo permite escolher um motor de cifragem, criar ou carregar uma chave e cifrar/decifrar ficheiros individuais ou diretórios. Requer o pacote externo cryptography.

MelisaCry.use(engine)

Define o motor de cifragem usado pelas operações seguintes.

Parâmetro: engine — "Fernet" ou "AES". A comparação não distingue maiúsculas de minúsculas.

Retorno: a própria classe MelisaCry, permitindo encadeamento. Um nome inválido gera ValueError.

from OpenSec import MelisaCry

MelisaCry.use("Fernet")
# ou
MelisaCry.use("AES")

Fernet usa a implementação fornecida por cryptography. O modo AES usa AES-256-GCM com nonce de 12 bytes. A escolha deve ser mantida consistente entre cifragem e decifragem.

MelisaCry.key(caminho="chave.txt")

Carrega uma chave existente do ficheiro indicado ou cria uma nova quando o ficheiro não existe ou está vazio.

Parâmetro: caminho — caminho do ficheiro da chave; por omissão, "chave.txt".

Retorno: objeto Key derivado de str, contendo a chave e a referência ao caminho usado.

chave = MelisaCry.key("./segredos/chave.txt")
print("Chave carregada/criada")

Protege a chave: não a publiques, não a envies em mensagens e não a guardes no mesmo local dos ficheiros cifrados sem uma estratégia de proteção. Perder a chave pode tornar os dados irrecuperáveis.

MelisaCry.crypt(caminho)

Prepara uma operação de cifragem para um ficheiro ou diretório.

Parâmetro: caminho — caminho existente para um ficheiro ou diretório.

Retorno: objeto de operação que disponibiliza by_key(chave).

chave = MelisaCry.key("./chave.txt")
resultado = MelisaCry.crypt("./documento.txt").by_key(chave)
print(resultado)

Após cifrar com sucesso, o ficheiro original é removido e o resultado recebe a extensão .melisa. Em diretórios, o código percorre os ficheiros recursivamente.

MelisaCry.decrypt(caminho)

Prepara uma operação de decifragem para um ficheiro cifrado ou diretório que contenha ficheiros com extensão .melisa.

Parâmetro: caminho — caminho do ficheiro ou diretório.

Retorno: objeto de operação que disponibiliza by_key(chave).

chave = MelisaCry.key("./chave.txt")
resultado = MelisaCry.decrypt("./documento.txt.melisa").by_key(chave)
print(resultado)

Na decifragem bem-sucedida, é criado o ficheiro sem a extensão .melisa e o ficheiro cifrado é mantido. A chave deve corresponder à utilizada na cifragem.

by_key(chave) — método da operação

Executa a operação preparada por crypt() ou decrypt().

Parâmetro: chave — objeto devolvido por MelisaCry.key(), string da chave válida ou caminho para um ficheiro que contenha a chave.

Retorno: dicionário com engine, operacao, alvo, arquivos_ok, erros, pulados e total.

# Cifrar
chave = MelisaCry.key("./chave.txt")
cifrar = MelisaCry.crypt("./ficheiros").by_key(chave)

# Decifrar
decifrar = MelisaCry.decrypt("./ficheiros").by_key(chave)

print(cifrar["total"])
print(cifrar["erros"])
print(decifrar["arquivos_ok"])

O código ignora ficheiros já cifrados durante a cifragem e ficheiros sem extensão .melisa durante a decifragem. Os ficheiros de chave identificados pela implementação são ignorados. Faz sempre uma cópia de segurança antes de testar.

04 · USO RESPONSÁVEL

Segurança, permissões e limitações

  • Utiliza as funções de análise apenas em redes, sistemas e aplicações para os quais tens autorização.
  • Resultados de deteção de SO, banners, e-mails, contactos e testes web são indicativos e podem conter falsos positivos.
  • A captura de tráfego pode exigir privilégios elevados e ferramentas externas instaladas.
  • A monitorização apresentada depende da interface wlan0; adapta a implementação à interface real do sistema.
  • A cifragem remove o original após o sucesso. Mantém cópias de segurança e protege a chave antes de trabalhar com dados importantes.
  • Não introduzas credenciais, chaves privadas ou dados pessoais nos exemplos públicos.
Esta documentação descreve o comportamento indicado pelo código disponibilizado. Os resultados reais dependem do sistema operativo, permissões, dependências, rede e resposta do alvo.
Voltar às bibliotecas