Aprenda Python Pentest

  • Página Inicial
  • Contato!
  • Tudo sobre Python Pentest Parte 1!
  • Tudo sobre Python Pentest Parte 2!
  • Tudo sobre Python Pentest Parte 3!
  • Tudo sobre Python Pentest Parte 4!
  • Tudo sobre Python Pentest Parte 5!
  • Tudo sobre Python Pentest Parte 6!
  • Tudo sobre Python Pentest Parte 7!
  • Tudo sobre Python Pentest Parte 8!
  • Tudo sobre Python Pentest Parte 9!
  • Tudo sobre Python Pentest Parte 10!
  • Tudo sobre Python Pentest Parte 11!
  • Tudo sobre Python Pentest Parte 12!
  • Tudo sobre Python Pentest Parte 13!
  • Tudo sobre Python Pentest Parte 4

    Criando um Whois

    O Whois permite que a gente faça consultas sobre um domínio, com informações como o dono do domínio, números de documentos e outras informações confidenciais. Podemos escanear as chamadas do Whois num sniffer como o Wireshark. Podemos também criar nosso próprio Whois com o Python.

    PS: Não é todo servidor Whois que tem as informações sobre determinados domínios.

    Esse site aqui, dá as informações sobre qual servidor Whois tem determinado servidor: https://www.iana.org/whois

    Vamos supor que colocamos um domínio no servidor acima, e ele mostra que o Whois que ele está é o whois.verisign-grs.com. Nós abrimos o Netcat digitando nc -v whois.verisign-grs.com 43, e enquanto ele roda, colocamos o site que queremos (como o globo.com). Ele retornará o servidor Whois dele, que pode ser algo como whois.1api.net, aí rodamos o Netcat de novo com nc -v whois.1api.net 43 e passar o domínio novamente. Podemos passar o próprio IANA no Netcat, também na porta 43, digitando nc -v whois.iana.org 43.

    Tudo que teremos que fazer, é uma ferramenta que automatiza isso. Crie um novo arquivo Python, e coloque esse código:

    
    import socket
    
    dominio = str(input("Digite o domínio: "))
    dominio += "\r\n"
    
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    
    sock.connect(("whois.iana.org", 43))
    sock.send(dominio.encode())
    
    print(sock.recv(1024).decode())
    
    

    Para pegar só o domínio do Whois que ele retorna, faça assim no print:

    
    print(sock.recv(1024).decode().split("refer:        ")[1].split("\n")[0])
    
    

    Deixe o código assim, para entender como ele funciona melhor:

    
    import socket
    
    dominio = str(input("Digite o domínio: "))
    dominio += "\r\n"
    
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    
    sock.connect(("whois.iana.org", 43))
    sock.send(dominio.encode())
    
    who1 = sock.recv(1024).decode().split("refer:        ")[1].split("\n")[0]
    
    print(who1)
    
    sock.close()
    
    

    Como a gente vai ter que ficar repetindo partes do código tentando vários domínios retornados pelo Whois até achar o que tem o domínio que queremos, é melhor usarmos funções pra isso, veja como fica:

    
    import socket
    
    def abrirSocket(who):
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.connect((who, 43))
    
        return sock
    
    dominio = str(input("Digite o domínio: "))
    dominio += "\r\n"
    
    sock = abrirSocket("whois.iana.org")
    sock.send(dominio.encode())
    
    who1 = sock.recv(1024).decode().split("refer:        ")[1].split("\n")[0]
    
    print(who1)
    
    sock.close()
    
    sock = abrirSocket(who1)
    sock.send(dominio.encode())
    
    who2 = sock.recv(1024).decode().split("Registrar WHOIS Server: ")[1].split("\r")[0] # Atenção, é "r", não "n"
    
    print(who2)
    
    sock.close()
    
    sock = abrirSocket(who2)
    sock.send(dominio.encode())
    
    print(sock.recv(4096).decode())
    
    

    O problema, é que mesmo aumentando o buffer do último print, ele pode cortar a informação. Poderíamos dividir em dois ou mais prints, ou usar um while dessa forma, no lugar do último print:

    
    while True:
        data = sock.recv(1024)
        
        if data:
            print(data.decode())
        else:
            break
    
    

    PS: Retire todos os prints que são usados pro debug, e deixe o último while assim:

    
    resp = ""
    
    while True:
        data = sock.recv(1024)
    
        if data:
            resp += data.decode()
        else:
            break
            
    print(resp)
    
    

    Código completo abaixo, com mais algumas correções:

    
    import socket
    
    def abrirSocket(who, site):
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.connect((who, 43))
        sock.send(site.encode())
    
        return sock
    
    dominio = str(input("Digite o domínio: "))
    dominio += "\r\n"
    
    sock = abrirSocket("whois.iana.org", dominio)
    
    who1 = sock.recv(1024).decode().split("refer:        ")[1].split("\n")[0]
    
    sock.close()
    
    sock = abrirSocket(who1, dominio)
    
    who2 = sock.recv(1024).decode().split("Registrar WHOIS Server: ")[1].split("\r")[0] # Atenção, é "r", não "n"
    
    sock.close()
    
    sock = abrirSocket(who2, dominio)
    
    resp = ""
    
    while True:
        data = sock.recv(1024)
    
        if data:
            resp += data.decode()
        else:
            break
    
    print(resp)
    
    

    Adicionando Whois na Nossa Ferramenta

    No lugar do último print, vamos colocar isso pra ele salvar num arquivo:

    
    dominio = dominio.strip()
    
    with open(f"{dominio}-whois.txt", "w") as arqWhois:
        arqWhois.write(resp)
    
    print(f"Arquivo Whois {dominio}.whois criado!")
    
    

    Podemos colocar em métodos numa classe, pode ser até a classe DnsScan mesmo:

    
    def abrirSocket(self, who, site):
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.connect((who, 43))
        sock.send(site.encode())
    
        return sock
    
    def whois(self, dominio):
        dominio += "\r\n"
    
        sock = self.abrirSocket("whois.iana.org", dominio)
    
        who1 = sock.recv(1024).decode().split("refer:        ")[1].split("\n")[0]
    
        sock.close()
    
        sock = self.abrirSocket(who1, dominio)
    
        who2 = sock.recv(1024).decode().split("Registrar WHOIS Server: ")[1].split("\r")[0] # Atenção, é "r", não "n"
    
        sock.close()
    
        sock = self.abrirSocket(who2, dominio)
    
        resp = ""
    
        while True:
            data = sock.recv(1024)
    
            if data:
                resp += data.decode()
            else:
                break
    
        dominio = dominio.strip()
    
        with open(f"{dominio}-whois.txt", "w") as arqWhois:
            arqWhois.write(resp)
    
        print(f"Arquivo Whois {dominio}.whois criado!")
    
    

    E no programa principal (dnsfoda.py), fazemos assim:

    
    from DnsScan import DnsScan
    import sys
    
    dominio = sys.argv[1]
    wordlist = sys.argv[2]
    
    dns = DnsScan()
    
    print(f"Consultando Whois {dominio}")
    dns.whois(dominio)
    print(f"Consulta Whois finalizada!")
    
    print("Iniciando bruteforce de subdomínios!")
    dns.subdominios(dominio, wordlist)
    
    print("Iniciando bruteforce de CNAME!")
    dns.verifCName(dominio, wordlist)
    
    print("Scan DNS finalizado!")
    
    

    Criando Menu e Parsing de Informações

    Podemos fazer com que o nosso programa crie pasta automaticamente com os scans (por exemplo, ao escanear globo.com, ele cria a pasta com esses arquivos dentro).

    Crie essa classe, pra começar:

    
    import os
    
    class Menu:
        def __init__(self): # Construtor
            if not os.path.isdir("scans"):
                os.mkdir("scans") # Cria pasta scans
    
    

    E no dnsfoda.py, podemos comentar tudo e deixar apenas isso:

    
    from Menu import Menu
    
    men = Menu()
    
    

    E caso queiramos que ele crie uma pasta com o nome do domínio dentro dessa pasta scan, podemos fazer assim:

    
    import os
    
    class Menu:
        def __init__(self, dominio): # Construtor
            if not os.path.isdir("scans"):
                os.mkdir("scans") # Cria pasta scans
    
            if not os.path.isdir(f"scans/{dominio}"):
                os.mkdir(f"scans/{dominio}")
    
    

    E no dnsfoda.py:

    
    from Menu import Menu
    
    men = Menu("globo.com")
    
    

    Daí, deixe a classe Menu assim:

    
    class Menu:
        def __init__(self): # Construtor
            if not os.path.isdir("scans"):
                os.mkdir("scans") # Cria pasta scans
    
    

    E aí, nesse caso, no dnsfoda.py apenas passamos Menu(), sem argumento.

    E aí, na classe DnsScan, alteramos as linhas do with open assim, como nessa:

    
    if not os.path.isdir(f"scans/{dominio}"): # Importe os
        os.mkdir(f"scans/{dominio}")
    
    with open(f"scans/{dominio}/subdomains.json", "w") as arqJson:
        arqJson.write(domJson)
    
    

    Daí, faça o mesmo com todas as ocorrências do tipo.

    E no programa principal:

    
    from DnsScan import DnsScan
    import sys
    from Menu import Menu
    
    men = Menu()
    dns = DnsScan()
    
    dominio = sys.argv[1]
    wordlist = sys.argv[2]
    
    print(f"Consultando Whois {dominio}")
    dns.whois(dominio)
    print(f"Consulta Whois finalizada!")
    
    print("Iniciando bruteforce de subdomínios!")
    dns.subdominios(dominio, wordlist)
    
    print("Iniciando bruteforce de CNAME!")
    dns.verifCName(dominio, wordlist)
    
    print("Scan DNS finalizado!")
    
    

    Na classe Menu, coloque esse método, para listar os diretórios:

    
    def exibirMenu(self):
        print(os.listdir("scans"))
    
    

    E no dnsfoda.py, chame ele assim (comente o restante do código, exceto as importações, por enquanto):

    
    men = Menu()
    men.exibirMenu()
    
    

    Agora descomente tudo pra criar tudo que precisamos.

    Deixe a função exibirMenu assim:

    
    def exibirMenu(self):
        scans = os.listdir("scans")
        id = 0
    
        for s in scans:
            print(f"{id} - {s}")
            id += 1
    
        sel = int(input("Selecione o ID: "))
        pasta = scans[sel]
    
        print(pasta)
    
    

    E depois, deixe ela assim pra completar o código por ora:

    
    def exibirMenu(self):
        scans = os.listdir("scans")
        id = 0
    
        for s in scans:
            print(f"{id} - {s}")
            id += 1
    
        sel = int(input("Selecione o ID: "))
        pasta = scans[sel]
    
        with open(f"scans/{pasta}/cname.json") as arqCname:
            cName = arqCname.read()
    
        print(cName)
    
    

    Mude as últimas linhas para isso:

    
    with open(f"scans/{pasta}/cname.json") as arqCname:
        cName = json.loads(arqCname.read()) # Importe json
    
    for c in cName:
        print(f"{c} alias para {cName[c]}")
    
    

    E depois pra isso, pra abrir todos os arquivos:

    
    with open(f"scans/{pasta}/cname.json") as arqCname:
        cName = json.loads(arqCname.read())
    
    with open(f"scans/{pasta}/subdomains.json") as arqSubs:
        subdom = json.loads(arqSubs.read())
        subIPv4 = subdom["ipv4"]
        subIPv6 = subdom["ipv6"]
        
    with open(f"scans/{pasta}/whois.txt") as arqWhois:
        whois = arqWhois.read()
    
    

    Daí, dentro da função, fora dos with open, podemos, por exemplo, exibir a quantidade de domínios IPv4 e IPv6, assim:

    
    print(f"Subdomínios IPv4: {len(subIPv4)}")
    print(f"Subdomínios IPv6: {len(subIPv6)}")
    
    

    E depois completamos tudo assim, no lugar desses dois prints:

    
    print(f"Subdomínios IPv4: {len(subIPv4)}")
    print(f"Subdomínios IPv6: {len(subIPv6)}")
    print(f"CNames: {len(cName)}")
    print("Escolha IPv4, IPv6, CName, Whois ou Sair!")
    
    while True:
        sel = str(input("Digite qual você quer exibir: "))
    
        if sel.lower() == "ipv4":
            for s in subIPv4:
                print(f"{s} -> {subIPv4[s]}")
        elif sel.lower() == "ipv6":
            for s in subIPv6:
                print(f"{s} -> {subIPv6[s]}")
        elif sel.lower() == "cname":
            for c in cName:
                print(f"{c} -> {cName[c]}")
        elif sel.lower() == "whois":
            print(whois)
        elif sel.lower() == "sair":
            break
        else:
            print("Comando não encontrado! Escolha IPv4, IPv6, CName, Whois ou Sair!")
    
    

    E pra finalizar, deixe o dnsfoda.py assim:

    
    from DnsScan import DnsScan
    import sys
    from Menu import Menu
    
    men = Menu()
    dns = DnsScan()
    
    if len(sys.argv) == 1:
        men.exibirMenu()
        exit()
    
    dominio = sys.argv[1]
    wordlist = sys.argv[2]
    
    print(f"Consultando Whois {dominio}")
    dns.whois(dominio)
    print(f"Consulta Whois finalizada!")
    
    print("Iniciando bruteforce de subdomínios!")
    dns.subdominios(dominio, wordlist)
    
    print("Iniciando bruteforce de CNAME!")
    dns.verifCName(dominio, wordlist)
    
    print("Scan DNS finalizado!")