Escrevendo um Portscan em Python 3
Entenda na prática o funcionamento de um portscan TCP.
Mas o que é um Portscan?
Para entender o que é um scanner de portas é necessário ter claro o conceito de portas.
Uma porta (em redes) se trata de uma estrutura lógica de dados, onde através dela os dados trafegam. As portas são identificadas através de sua numeração (de 1 até 65535, no caso de ser TCP) e a maior parte dos serviços tem uma porta específica na qual ele fica “escutando”, ou seja, trabalhando nos dados que entram e saem.
Um scanner de portas é um programa que de forma automatizada sai testando essas portas em busca dos serviços que estão rodando lá.
Qual a vantagem de saber qual serviço está rodando em determinada porta?
Supondo que você está na fase de reconhecimento em um pentest, você roda um portscan no alvo e descobre que a porta 21 (ftp) está aberta, fazendo uma busca mais profunda você descobre que esse ftp está rodando uma versão antiga com várias falhas graves.
Então, é claro, a partir daí existe uma gama de possibilidades, você pode, por exemplo, sair em busca de exploits para essa falha ou escrever o seu próprio, mas para não sair do assunto não irei me aprofundar nas possibilidades.
O interessante é que com Python programar um port scanner fácil demais, a linguagem é uma mão na roda tanto para os profissionais de segurança, quanto para o estudante na hora de entender como que o nmap funciona por trás dos panos.
Let’s Code!
Depois de uma breve (bem breve) introdução, você já deve estar pronto para por a mão no teclado.
O primeiro a se fazer é importar a biblioteca socket (nativa do Python), que dá funcionalidades específicas para a linguagem que permite fazer requisições web de maneira fácil
import socketPara o código se tornar dinâmico, é bom permitir o input do usuário para o IP/Domínio que ele deseja testar e colocar isso dentro da variável ‘alvo’
import socketalvo = input('Digite o IP/Dominio: ')
Vamos instanciar essa lib socket e usar o método com o mesmo nome, armazenando tudo isso na variável ‘client’. E em seguida setar um timeout de 0.05 segundos para a conexão ser realizada, isso é mais que o suficiente para nosso script testar se uma porta está aberta ou não
import socketalvo = input('Digite o IP/Dominio: ')client = socket.socket()
client.settimeout(0.05)
O método ‘connect_ex()’ recebe uma tupla com dois valores (alvo e porta) e retorna um número referente à conexão
Se ele conseguir se conectar: Ele retorna 0
Se ele não conseguir: Pode retornar qualquer outro número
import socketalvo = input('Digite o IP/Dominio: ')client = socket.socket()
client.settimeout(0.05)client.connect_ex((alvo, <porta>))
# (Ainda falta setarmos qual vai ser a porta)
Vamos criar uma condicional, caso o retorno do connect_ex() seja ‘0’ (ou seja, caso a porta esteja aberta) o programa deve printar o número da porta
import socketalvo = input('Digite o IP/Dominio: ')client = socket.socket()
client.settimeout(0.05)if client.connect_ex((alvo, <porta>)) == 0:
print('Porta Aberta ==>', porta)
Agora a parte legal, vamos por tudo isso dentro de um loop que irá se repetir 65535 vezes!
O range() irá nos ajudar nisso, ele recebe dois parâmetros cujo o primeiro é o primeiro número da sequência e o segundo é o último, por exemplo:
for numero in range(1, 3):
print(numero)
# 1
# 2
# 3A estrutura for in irá atribuir o valor do range para a variável passada, ou seja, essa variável irá ter o valor 1, depois 2, até o valor 65535 e essa mesma variável será passada como parâmetro ‘porta’ para o connect_ex.
De modo que para o alvo passado pelo usuário, o connect_ex vai testar suas 65535 portas
import socketalvo = input('Digite o IP/Dominio: ')for porta in range(1, 65535):
client = socket.socket()
client.settimeout(0.05) if client.connect_ex((alvo, porta)) == 0:
print('Porta Aberta ==>', porta)
Com isso temos o script pronto! Se quiser, pode ir aprimorando o código, colocando toda a estrutura do client dentro de uma função e chamar essa função dentro do loop, colocar condicionais para o número da porta (se a porta for 80 printe ‘apache’, se for 21 printe ‘ftp’).
Esse é o barato de programar sua própria ferramenta, você sabe exatamente como ela se comporta e pode deixa-la da melhor maneira que atenda sua necessidade!
# Import da lib socket para conexões
import socket# O alvo será digitado pelo usuário
alvo = input('Digite o IP/Dominio: ')# Loop de 65535 vezes (quantidade de portas TCP)
for porta in range(1, 65535):
# Setando e configurando o cliente
client = socket.socket()
client.settimeout(0.05) # Se a porta estiver aberta, jogue ela na tela
if client.connect_ex((alvo, porta)) == 0:
print('Porta Aberta ==>', porta)
