Mapeamento de Aplicativos da Web de Código Aberto

A análise de aplicativos da Web é absolutamente essencial para um invasor ou um testador de penetração. A maior superfície de ataques na maioria das redes modernas são os aplicativos da Web que, portanto, também são o caminho mais comum para obter acesso. Há várias excelentes ferramentas de aplicativo da Web que foram escritas em Python, incluindo w3af, sqlmap e outras. Embora as ferramentas disponíveis estejam suficientemente maduras para que não precisemos reinventar a roda, em algum momento e em algum cenário de ataque específico, será necessário criar alguma ferramenta diferente. O Python possui bibliotecas bastante eficientes para construirmos qualquer tipo de ferramenta para interação com a Web.

Nos Posts anteriores abordei como escrever ferramentas de rede com a biblioteca de sockets, agora vou mostrar como criar uma ferramenta para interagir com serviços da web usando a biblioteca urllib2, “a biblioteca de sockets da web”

urllib2 – A biblioteca de sockets da web

Vamos dar uma olhada em fazer uma solicitação GET bem simples a um site:

import urllib2
body = urllib2.urlopen("http://sitealvo.com.br")    #(1)
print body.read()    #(2)

Este é o exemplo mais simples de como fazer uma solicitação GET para um site. Lembre-se de que estamos apenas buscando a página bruta no site e que nenhum JavaScript ou qualquer outra coisa será executada no lado cliente. Simplesmente passamos uma URL para a função urlopen #(1) e ela retorna um objeto semelhante a um arquivo que nos permite ler de volta #(2) o corpo do que o servidor da web remoto retorna. Na maioria dos casos, no entanto, você desejará um controle mais refinado sobre como fazer essas solicitações, incluindo a possibilidade de definir cabeçalhos específicos, manipular cookies e criar solicitações POST. urllib2 contém uma classe Request que fornece esse nível de controle. Abaixo está um exemplo de como criar a mesma solicitação GET usando a classe Request e definindo um cabeçalho HTTP User-Agent personalizado:

import urllib2
url = "http://www.sitealvo.com.br"
headers = {}    #(1)
headers['User-Agent'] = "Googlebot"

request  = urllib2.Request(url,headers=headers)    #(2)
response = urllib2.urlopen(request)    #(3)

print response.read()
response.close()

A construção de um objeto Request é um pouco diferente do nosso exemplo anterior. Para criar cabeçalhos personalizados, defina um dicionário de cabeçalhos #(1), que permite definir a chave de cabeçalho e o valor que você deseja usar. Nesse caso, faremos com que nosso script em Python pareça ser o Googlebot. Em seguida, criamos nosso objeto Request e passamos o url e o dicionário de cabeçalhos #(2) e, em seguida, passamos o objeto Request para a chamada de função urlopen #(3). Isso retorna um objeto semelhante a um arquivo normal que podemos usar para ler os dados do site remoto. Agora, temos os meios fundamentais para conversar com serviços da Web e sites da Web, por isso vamos criar uma ferramenta útil para qualquer ataque de aplicativo da Web ou teste de penetração.

Mapeamento de Aplicativos da Web de Código Aberto

Os Sistemas de Gerenciamento de Conteúdo (CMS) e as plataformas de blogs como Joomla, WordPress e Drupal, simplificam a construção de um blog ou site e são relativamente comuns em um ambiente de hospedagem compartilhada ou até mesmo em uma rede corporativa. Todos os sistemas têm seus próprios desafios em termos de instalação, configuração e gerenciamento de patches, e esses conjuntos de CMS não são exceção. Quando um administrador de sistema sobrecarregado de trabalho ou um infeliz desenvolvedor de Web não segue todos os procedimentos de segurança e instalação, pode ser uma escolha fácil para um invasor obter acesso ao servidor da Web.

Primeiro é preciso identificar o CMS usado pelo alvo. Existem alguns serviços online que fazem isso facilmente, eis alguns:

Builtwith (Mais Popular e eficiente)

W3Techs (Popular e muito eficiente)

cms-detect

Depois, baixar e extrair o CMS. No Linux, onde estou trabalhando, é moleza. Baixar o .tar.gz com o navegador e:

cd /root/Downloads
tar -zxvf drupal-8.6.1.tar.gz

O exemplo que ilustra o resultado usei o WordPress como entrada no script que chamei de cockshot.py

/root/Downloads/wordpress-4.9.8/wordpress

Como podemos fazer o download de qualquer aplicativo da Web de código aberto e determinar localmente sua estrutura de arquivos e diretórios, podemos criar um mecanismo de varredura com finalidade específica que possa procurar todos os arquivos que podem ser acessados no destino remoto. Isso pode arrancar arquivos de instalação remanescentes, diretórios que deveriam estar protegidos por arquivos .htaccess e outros itens que podem permitir a um invasor obter um “ponto de apoio” para iniciar o trabalho. Este projeto também apresenta o uso de objetos Python Queue, que nos permitem criar uma grande pilha de itens thread-safe e ter vários itens de seleção de threads para processamento. Isso permitirá que o nosso scanner (cockshot.py) funcione bem rápido.

O cockshot.py a que tenho me referido consiste no seguinte código para Python 2.7:

import Queue
import threading
import os
import urllib2
import urllib

threads = 10
target = raw_input("Digite a URL do alvo:")    #(1)
directory = raw_input("Digite o diretorio do CMS:")
filters = [".jpg",".gif","png",".css"]

os.chdir(directory)

user_agent = 'Mozilla/5.0 (Windows NT 6.1; Win64; x64)'
values = {'name': 'Horacio Mala',
          'location': 'Nordeste',
          'language': 'Python'}
headers = {'User-Agent': user_agent}
data = urllib.urlencode(values)
web_paths = Queue.Queue()    #(2)

for r,d,f in os.walk("."):    #(3)
    for files in f:
        remote_path = "%s/%s" % (r,files)
        if remote_path.startswith("."):
            remote_path = remote_path[1:]
        if os.path.splitext(files)[1] not in filters:
            web_paths.put(remote_path)
def test_remote():
    while not web_paths.empty():    #(4)
        path = web_paths.get()
        url = "%s%s" % (target, path)

        request = urllib2.Request(url, data, headers)

        try:
            response = urllib2.urlopen(request)
            content  = response.read()
            print "[%d] => [%s]" % (response.code,path)    #(5)
            response.close()
        except urllib2.HTTPError as error:    #(6)
            #print "Failed %s" % error.code
            pass

for i in range(threads):    #(7)
    print "Spawning thread: %d" % i
    t = threading.Thread(target=test_remote)
    t.start()

Começamos definindo o site de destino remoto #(1) e o diretório local para o qual fizemos download e extraímos o CMS. Também criamos uma lista simples de extensões de arquivo que não temos interesses. Essa lista pode ser diferente dependendo do aplicativo de destino. A variável web_paths #(2) é nosso objeto Queue, onde armazenaremos os arquivos que tentaremos localizar no servidor remoto. Em seguida, usamos a função os.walk #(3) para percorrer todos os arquivos e diretórios no diretório local de aplicativos da web. À medida que percorremos os arquivos e diretórios, estamos construindo o caminho completo para os arquivos de destino e testando-os em nossa lista de filtros para garantir que apenas procuremos os tipos de arquivos desejados. Para cada arquivo válido que encontramos localmente, nós o adicionamos à nossa fila web_paths.

Olhando para a parte inferior do script #(7), estamos criando vários threads (como definido no topo do arquivo) onde cada um será chamará a função test_remote. A função test_remote opera em um loop que continuará sendo executado até que a fila web_paths esteja vazia. Em cada iteração do loop, pegamos um caminho da Fila #(4), o adicionamos ao caminho base do site de destino e tentamos recuperá-lo. Se obtivermos êxito na recuperação do arquivo, exibiremos o código de status HTTP e o caminho completo para o arquivo #(5). Se o arquivo não for encontrado ou estiver protegido por um arquivo .htaccess, isso fará com que o urllib2 lance um erro, o qual nós manipulamos #(6) para que o loop possa continuar sendo executado.

Resultado

Para fins de demonstração neste Post, usei a minha Kali VM, mas você pode usar o Windows e qualquer CMS de código aberto. Ao executar o cockshot.py, veremos o resultado como segue:

ipda-ws-cockshot.png

Como pode-se ver,  obtivemos alguns resultados válidos, incluindo alguns arquivos .txt e .XML. É claro que podemos criar inteligência adicional no script para retornar apenas arquivos nos quais temos interesse, como aqueles com a palavra install neles.

Diretórios de força bruta e locais dos arquivos

O exemplo pressupõe muito conhecimento sobre o seu alvo. No entanto, em muitos casos em que você está atacando um aplicativo da Web personalizado ou um grande sistema de comércio eletrônico, você não estará ciente de todos os arquivos acessíveis no servidor da web. Geralmente, você implantará um spider, como o incluído no Burp Suite, para rastrear o site de destino, a fim de descobrir o máximo possível do aplicativo da web. No entanto, em muitos casos, há arquivos de configuração, arquivos de sobras de desenvolvimento, scripts de depuração e outras migalhas de segurança que podem fornecer informações confidenciais ou expor funcionalidades que o desenvolvedor do software não pretendia. A única maneira de descobrir esse conteúdo é usar uma ferramenta de força bruta para procurar nomes de arquivos e diretórios comuns. Mas isto é um assunto para outro post.

Anúncios

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair /  Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair /  Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair /  Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair /  Alterar )

Conectando a %s