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 3

    Melhorando Script

    O nosso bruteforce de subdomínios irá fazer parte de uma ferramenta mais aprimorada mais pra frente, por isso podemos e devemos fazer melhorias.

    Vamos começar adicionando abaixo da entrada de domínio, dois dicionários, assim:

    
    cons = list()
    dom4 = dict()
    dom6 = dict()
    relDom = dict()
    
    

    E altere as funções dnsIPv4 e dnsIPv6 para que elas retornem o endereço. Veja como ficará o dnsIPv4 e faça o mesmo com o dnsIPv6:

    
    def dnsIPv4(subdom):
        try:
            dados = socket.getaddrinfo(subdom, None, socket.AF_INET)
            addr = dados[0][4][0]
            print(f"{subdom} - {addr}")
            
            return addr
        except socket.gaierror:
            return 0
    
    

    E altere a estrutura with open assim:

    
    with open("wordlist-dominios.txt") as wordlist:
        for w in wordlist.readlines():
            w = w.replace("\n", "")
            subdom = f"{w}.{dominio}"
    
            if subdom not in cons:
                addr4 = dnsIPv4(subdom)
                addr6 = dnsIPv6(subdom)
                cons.append(subdom)
    
    

    Para ele salvar os dicionários, deixe a estrutura assim:

    
    with open("wordlist-dominios.txt") as wordlist:
        for w in wordlist.readlines():
            w = w.replace("\n", "")
            subdom = f"{w}.{dominio}"
    
            if subdom not in cons:
                addr4 = dnsIPv4(subdom)
                addr6 = dnsIPv6(subdom)
    
                if addr4 != 0:
                    dom4[subdom] = addr4
    
                if addr6 != 0:
                    dom6[subdom] = addr6
                    
                cons.append(subdom)    
    
    

    E debaixo de tudo isso, fora de todas as identações, coloque isso pra ele colocar os dicionários em IPv4 e IPv6 dentro de um outro dicionário:

    
    relDom["ipv4"] = dom4
    relDom["ipv6"] = dom6
    
    print(relDom)
    
    

    Agora apague o print acima e coloque isso no lugar pra ele salvar como JSON:

    
    domJson = json.dumps(relDom) # Coloque "import json" acima do código
    
    with open(f"{dominio}-subdomains.json", "w") as arqJson:
        arqJson.write(domJson)
    
    

    No caso, salvaremos tudo num arquivo JSON só, que terá esse formato:

    
    {"ipv4": {
        "www.facebook.com": "157.240.222.35",
        "mobile.facebook.com": "157.240.222.16",
        "m.facebook.com": "157.240.222.35"},
    "ipv6": {
        "www.facebook.com": "2a03:2880:f148:82:face:b00c:0:25de",
        "mobile.facebook.com": "2a03:2880:f048:11:face:b00c:0:2",
        "m.facebook.com": "2a03:2880:f148:82:face:b00c:0:25de"}
    }
    
    

    Para ver um arquivo JSON, podemos usar um site como esse: https://jsonviewer.stack.hu/

    Mas futuramente faremos isso com o próprio Python.

    Subdomain Takeover

    Podemos também fazer ele retornar o CNAME, CNAME é um tipo de registro DNS que funciona como um alias: Ele aponta um nome de domínio para outro. Por exemplo, o domínio help.4d3358.com pode ter um CNAME apontando para um outro site de nome mais amigável. Isso significa que, ao resolver help.4d3358.com, o DNS retorna o endereço desse outro site mais amigável. Porém, isso não garante redirecionamento no navegador, apenas o apontamento de nome.

    Instale a biblioteca dnspython e vamos fazer esse programa:

    
    import dns.resolver
    
    dominio = str(input("Digite o domínio: "))
    
    resp = dns.resolver.resolve(dominio, "CNAME")
    
    print(resp)
    
    

    Ele dará um erro caso o domínio não tenha nenhuma resposta. Para filtrar, fazemos assim:

    
    import dns.resolver
    
    dominio = str(input("Digite o domínio: "))
    
    try:
        resp = dns.resolver.resolve(dominio, "CNAME")
        print(resp[0].target)
    except dns.resolver.NoAnswer:
        print("Não encontrado o CNAME!")
    
    

    Caso passemos um outro subdomínio no mesmo domínio, ele dará erro. Também podemos filtrar ele:

    
    import dns.resolver
    
    dominio = str(input("Digite o domínio: "))
    
    try:
        resp = dns.resolver.resolve(dominio, "CNAME")
        print(resp[0].target)
    except dns.resolver.NoAnswer:
        print("Não encontrado o CNAME!")
    except dns.resolver.NXDOMAIN:
        print("Não encontrado o subdomínio!")
    
    

    Podemos também usar o bruteforce de subdomínios para isso, deixando dessa forma, nesse caso passe só o domínio:

    
    import dns.resolver
    
    dominio = str(input("Digite o domínio: "))
    
    with open("wordlist-dominios.txt") as wordlist:
        for w in wordlist.readlines():
            w = w.replace("\n", "")
            subdom = f"{w}.{dominio}"
    
            try:
                resp = dns.resolver.resolve(subdom, "CNAME")
                cname = resp[0].target
                print(f"{subdom} tem um alias {cname}")
            except dns.resolver.NoAnswer:
                pass
            except dns.resolver.NXDOMAIN:
                pass
    
    

    PS: Não é porque tem um alias que o domínio exatamente tenha uma vulnerabilidade.

    Ao fazer essas análises, pode ser que o próprio servidor bloqueie ele, então nesse caso, podemos fazer um filtro nele também:

    
    with open("wordlist-dominios.txt") as wordlist:
        for w in wordlist.readlines():
            w = w.replace("\n", "")
            subdom = f"{w}.{dominio}"
    
            while True:
                try:
                    resp = dns.resolver.resolve(subdom, "CNAME")
                    cname = resp[0].target
                    print(f"{subdom} tem um alias {cname}")
                    
                    break
                except dns.resolver.NoAnswer:
                    break
                except dns.resolver.NXDOMAIN:
                    break
                except dns.resolver.LifetimeTimeout:
                    print("Caiu no Timeout CNAME...")
                    time.sleep(2) # Adicione "import time" logo acima, aumente ou diminua conforme a necessidade
    
    

    Aprimorando nosso Script DNS

    Vamos usar o JSON para salvar os resultados das nossas análises. No começo do script, chame o JSON e crie um dicionário, assim:

    
    import dns.resolver
    import time
    import json
    
    dominio = str(input("Digite o domínio: "))
    cnameDic = dict()
    
    

    E no try, faça assim:

    
    resp = dns.resolver.resolve(subdom, "CNAME")
    cname = resp[0].target
    cnameDic[subdom] = str(cname)
    print(f"{subdom} tem um alias {cname}")
    
    break
    
    

    E no final do código, fora de qualquer identação, coloque isso:

    
    cnameJson = json.dumps(cnameDic)
    
    with open(f"{dominio}-cname.json", "w") as arqJson:
        arqJson.write(cnameJson)
        
    print(f"Arquivo JSON {dominio}-cname.json criado!")
    
    

    Agora, vamos organizar tudo num arquivo só que unirá os dois programas, volte no arquivo de subdomínios e vamos unir os dois. Primeiramente, crie uma classe assim:

    
    import socket
    import json
    
    class DnsScan:
        def subdominios(self, dominio, listaPl):
            cons = list()
            dom4 = dict()
            dom6 = dict()
            relDom = dict()
    
            with open(listaPl) as wordlist:
                for w in wordlist.readlines():
                    w = w.replace("\n", "")
                    subdom = f"{w}.{dominio}"
    
                    if subdom not in cons:
                        addr4 = self.dnsIPv4(subdom)
                        addr6 = self.dnsIPv6(subdom)
    
                        if addr4 != 0:
                            dom4[subdom] = addr4
    
                        if addr6 != 0:
                            dom6[subdom] = addr6
    
                        cons.append(subdom)
    
            relDom["ipv4"] = dom4
            relDom["ipv6"] = dom6
    
            domJson = json.dumps(relDom)
    
            with open(f"{dominio}-subdomains.json", "w") as arqJson:
                arqJson.write(domJson)
    
            print(f"Arquivo JSON {dominio}-subdomains.json criado!")
    
        def dnsIPv4(self, subdom):
            try:
                dados = socket.getaddrinfo(subdom, None, socket.AF_INET)
                addr = dados[0][4][0]
                print(f"{subdom} - {addr}")
    
                return addr
            except socket.gaierror:
                return 0
    
        def dnsIPv6(self, subdom):
            try:
                dados = socket.getaddrinfo(subdom, None, socket.AF_INET6)
                addr = dados[0][4][0]
                print(f"{subdom} - {addr}")
    
                return addr
            except socket.gaierror:
                return 0
    
    

    No arquivo principal (como dnsfoda.py), fazemos assim:

    
    from DnsScan import DnsScan
    import sys
    
    dominio = sys.argv[1]
    wordlist = sys.argv[2]
    
    dns = DnsScan()
    
    dns.subdominios(dominio, wordlist)
    
    

    E rode pelo terminal digitando python3 dnsfoda.py nomedosite.com wordlist.txt.

    Para unir as funcionalidades dos dois programas, coloque esse método na classe DnsScan:

    
    # Não esqueça de importar "dns.resolver" e "time"
    def verifCName(self, dominio, listaPl):
        cNameDic = dict()
    
        with open(listaPl) as wordlist:
            for w in wordlist.readlines():
                w = w.replace("\n", "")
                subdom = f"{w}.{dominio}"
    
                while True:
                    try:
                        resp = dns.resolver.resolve(subdom, "CNAME")
                        cName = resp[0].target
                        cNameDic[subdom] = str(cName)
                        print(f"{subdom} tem um alias {cName}")
    
                        break
                    except dns.resolver.NoAnswer:
                        break
                    except dns.resolver.NXDOMAIN:
                        break
                    except dns.resolver.LifetimeTimeout:
                        print("Caiu no Timeout CNAME...")
                        time.sleep(3)
    
        cNameJson = json.dumps(cNameDic)
    
        with open(f"{dominio}-cname.json", "w") as arqJson:
            arqJson.write(cNameJson)
    
        print(f"Arquivo JSON {dominio}-cname.json criado!")
    
    

    E altere o dnsfoda.py assim:

    
    from DnsScan import DnsScan
    import sys
    
    dominio = sys.argv[1]
    wordlist = sys.argv[2]
    
    dns = DnsScan()
    
    # dns.subdominios(dominio, wordlist)
    dns.verifCName(dominio, wordlist)
    
    

    Pra finalizar, deixe ele assim:

    
    from DnsScan import DnsScan
    import sys
    
    dominio = sys.argv[1]
    wordlist = sys.argv[2]
    
    dns = DnsScan()
    
    print("Iniciando bruteforce de subdomínios!")
    dns.subdominios(dominio, wordlist)
    print("Iniciando bruteforce de CNAME!")
    dns.verifCName(dominio, wordlist)
    
    

    PS: Podemos criar condições também para escolher apenas um dos scans.