Como o Recon-NG implementa OSINT
Saudações, pessoal! No post anterior, vimos uma introdução aos conceitos de Open Source Intelligence, além de começarmos a cobrir o Recon-NG. Chegou a hora de irmos para a parte prática. Neste post, iniciaremos a coleta e organização de dados relativos ao nosso alvo. Vamos à leitura!
Laboratório Inicial
Gosto de usar o site do SANS para meus laboratórios e explicações, porque ele é uma referência para nós, profissionais de cybersecurity. Então, vamos começar o laboratório usando o SANS como nosso alvo. Criemos um workspace novo pra isso:
[recon-ng][default] > workspaces list +------------+ | Workspaces | +------------+ | default | +------------+ [recon-ng][default] > workspaces add sans [recon-ng][sans] >
Depois disso, vamos adicionar um domínio principal, incluindo o prefixo “www”. Para isso, usamos o comando “add”, seguido pela palavra-chave “domains” e pelo domínio correspondente. Isto adicionará um registro à tabela “domains” dentro do banco de dados do workspace “sans”. Se você desejar saber quais tabelas existem no banco antes de começar a mexer com elas, use o comando “show schema”.
O comando “show” será seu parceiro ao longo de sua jornada em torno da enumeração do alvo. Todos os dados coletados podem ser visualizados com ele. Não apenas isso, mas também toda sua atividade (os comandos digitados e módulos carregados), bem como o banner de startup da ferramenta, hosts descobertos, blocos de rede e muito mais. Lembre-se de que tudo é gravado no banco de dados e que os workspaces não compartilham suas bases.
recon-ng][sans] > show schema +---------------+ | domains | +---------------+ | domain | TEXT | | module | TEXT | +---------------+ +--------------------+ | companies | +--------------------+ | company | TEXT | | description | TEXT | | module | TEXT | +--------------------+ +-----------------+ | netblocks | +-----------------+ | netblock | TEXT | | module | TEXT | +-----------------+ . . . <saída suprimida> recon-ng][sans] > show domains [*] No data returned. recon-ng][sans] > add domains sans.org recon-ng][sans] > add domains www.sans.org recon-ng][sans] > show domains +-------------------------------------+ | rowid | domain | module | +-------------------------------------+ | 1 | sans.org | user_defined | | 2 | www.sans.org | user_defined | +-------------------------------------+ [*] 2 rows returned
A partir da saída acima do “show schema”, é possível ver que a tabela “domains” tem dois campos: o próprio domínio e um módulo. O valor deste último é automaticamente preenchido pela ferramenta. Portanto, não precisa se preocupar com ele. A tabela “companies”, por outro lado, tem um campo a mais: description. Se você digitar “help add”, perceberá que existe um caracter delimitador usado para separar os valores dos campos. Este caracter é o “˜” (til). Assim, para adicionar o nome da empresa, seguido por uma descrição, você digitaria (observe a posição do til):
[recon-ng][sans] > add companies SANS~The widely known SANS Institute [recon-ng][sans] > show companies +------------------------------------------------------------------+ | rowid | company | description | module | +------------------------------------------------------------------+ | 1 | SANS | The widely known SANS Institute | user_defined | +------------------------------------------------------------------+ [*] 1 rows returned
Como temos apenas o domínio da empresa, vamos iniciar nossa busca envolvendo algum módulo relacionado aos domínios. Não precisa memorizar os nomes dos módulos. Além disso, o Recon-NG completa automaticamente o comando sendo digitado quando se pressiona <TAB>, assim como funciona com o shell do Linux e algumas interfaces de linha de comando de roteadores. Você pode usar o comando “search” para procurar partes de nomes de módulos. Assim, vamos fazer uma busca rápida para ver quais são os módulos disponíveis:
recon-ng][sans] > search domains [*] Searching for 'domains'... Recon ----- recon/contacts-domains/migrate_contacts recon/domains-contacts/metacrawler recon/domains-contacts/pgp_search recon/domains-contacts/whois_pocs recon/domains-credentials/pwnedlist/account_creds recon/domains-credentials/pwnedlist/api_usage recon/domains-credentials/pwnedlist/domain_creds recon/domains-credentials/pwnedlist/domain_ispwned recon/domains-credentials/pwnedlist/leak_lookup recon/domains-credentials/pwnedlist/leaks_dump recon/domains-domains/brute_suffix recon/domains-hosts/bing_domain_api recon/domains-hosts/bing_domain_web recon/domains-hosts/brute_hosts recon/domains-hosts/builtwith recon/domains-hosts/certificate_transparency recon/domains-hosts/google_site_api recon/domains-hosts/google_site_web recon/domains-hosts/hackertarget recon/domains-hosts/mx_spf_ip recon/domains-hosts/netcraft recon/domains-hosts/shodan_hostname recon/domains-hosts/ssl_san recon/domains-hosts/threatcrowd recon/domains-vulnerabilities/ghdb recon/domains-vulnerabilities/punkspider recon/domains-vulnerabilities/xssed recon/domains-vulnerabilities/xssposed recon/hosts-domains/migrate_hosts
Assim, pelos resultados acima, todos os módulos estão localizados sob a categoria “Recon”. Ótimo, pois é nesta categoria que ficaremos focados neste artigo. Podemos iniciar com o módulo “pgp_search”, tentando encontrar algum contato. Qualquer informação relacionada ao módulo pode ser obtida através do comando “show info”:
[recon-ng][sans] > use recon/domains-contacts/pgp_search [recon-ng][sans][pgp_search] > show info Name: PGP Key Owner Lookup Path: modules/recon/domains-contacts/pgp_search.py Author: Robert Frost (@frosty_1313, frosty[at]unluckyfrosty.net) Description: Searches the MIT public PGP key server for email addresses of the given domain. Updates the 'contacts' table with the results. Options: Name Current Value Required Description ------ ------------- -------- ----------- SOURCE default yes source of input (see 'show info' for details) Source Options: default SELECT DISTINCT domain FROM domains WHERE domain IS NOT NULL <string> string representing a single input <path> path to a file containing a list of inputs query <sql> database query returning one column of inputs Comments: * Inspiration from theHarvester.py by Christan Martorella: cmarorella[at]edge-seecurity.com
Este módulo possui uma opção necessária (SOURCE). Observe que o valor está vazio. Não há problema, pois muitos módulos usam a tabela domains como entrada. Para executar o módulo, simplesmente digite o comando “run” e espere pelo prêmio. 🙂 Muito do conteúdo da saída foi suprimido, pois esta execução retornou mais de 160 contatos!
[recon-ng][sans][pgp_search] > run -------- SANS.ORG -------- [*] [contact] Mike Bean (mbean@sans.org) - PGP key association [*] [contact] Jeff Rivard (jrivard@sans.org) - PGP key association [*] [contact] Alex Peruyera (aperuyera@sans.org) - PGP key association [*] [contact] SANS Operations (sys-ops@sans.org) - PGP key association [*] [contact] Dan Shires (dshires@sans.org) - PGP key association . . . <saída suprimida> ------------ WWW.SANS.ORG ------------ [*] No results found. ------- SUMMARY ------- [*] 164 total (163 new) contacts found.
Outro módulo que recupera nomes de contatos e endereços de e-mail é o “whois_pocs”. PoCs significa Points Of Contact e são usados pelas bases de dados WHOIS ao redor do mundo para alertar pessoas responsáveis por domínios, quando é necessário relatar algum problema com os mesmos. Portanto, se você executá-lo, vai receber ainda mais contatos:
[recon-ng][sans][pgp_search] > use recon/domains-contacts/whois_pocs [recon-ng][sans][whois_pocs] > run -------- SANS.ORG -------- [*] URL: http://whois.arin.net/rest/pocs;domain=sans.org [*] URL: http://whois.arin.net/rest/poc/ABUSE3840-ARIN [*] [contact] <blank> Abuse (security@sans.org) - Whois contact [*] URL: http://whois.arin.net/rest/poc/MF974-ARIN [*] [contact] MATT FEARNOW (MATT@sans.org) - Whois contact [*] URL: http://whois.arin.net/rest/poc/DGO137-ARIN [*] [contact] David Goldsmith (dgoldsmith@sans.org) - Whois contact [*] URL: http://whois.arin.net/rest/poc/GOLDS13-ARIN [*] [contact] David Goldsmith (dgoldsmith@sans.org) - Whois contact [*] URL: http://whois.arin.net/rest/poc/NOC12468-ARIN [*] [contact] <blank> Network Operations Center (noc@sans.org) - Whois contact [*] URL: http://whois.arin.net/rest/poc/NOC13233-ARIN [*] [contact] <blank> Network Operations Center (it@sans.org) - Whois contact ------------ WWW.SANS.ORG ------------ [*] URL: http://whois.arin.net/rest/pocs;domain=www.sans.org [*] No contacts found. ------- SUMMARY ------- [*] 6 total (5 new) contacts found.
Observando a descrição do módulos anteriores, vemos que a tabela “contacts” é alimentada:
[recon-ng][sans][pgp_search] > show contacts +------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | rowid | first_name | middle_name | last_name | email | title | region | country | module | +------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | 1 | Mike | | Bean | mbean@sans.org | PGP key association | | | pgp_search | | 2 | Jeff | | Rivard | jrivard@sans.org | PGP key association | | | pgp_search | | 3 | Alex | | Peruyera | aperuyera@sans.org | PGP key association | | | pgp_search | | 4 | SANS | System | Operations | sys-ops@sans.org | PGP key association | | | pgp_search | | 5 | Dan | | Shires | dshires@sans.org | PGP key association | | | pgp_search | . . . <saída suprimida>
O formato de saída não fica muito fácil de visualizar, mesmo com um monitor grande, por conta dos tamanhos das colunas. Para ajudar, podemos usar um outro comando muito poderoso: “query”. Este comando recebe uma sintaxe SQL, interpreta e a executa. Vamos iniciar verificando o uso. Você verá que é possível exibir e também atualizar os conteúdos de tabelas. Pela saída anterior, a informação mais útil seria o primeiro nome, último nome e endereço de e-mail. Assim, com o comando “query”, obtemos:
[recon-ng][sans][pgp_search] > help query Queries the database Usage: query <sql> SQL examples: SELECT columns|* FROM table_name SELECT columns|* FROM table_name WHERE some_column=some_value DELETE FROM table_name WHERE some_column=some_value INSERT INTO table_name (column1, column2,...) VALUES (value1, value2,...) UPDATE table_name SET column1=value1, column2=value2,... WHERE some_column=some_value [recon-ng][sans][pgp_search] > [recon-ng][sans][pgp_search] > query select first_name, last_name, email from contacts +------------------------------------------------------------------------------------+ | first_name | last_name | email | +------------------------------------------------------------------------------------+ | Mike | Bean | mbean@sans.org | | Jeff | Rivard | jrivard@sans.org | | Alex | Peruyera | aperuyera@sans.org | | SANS | Operations | sys-ops@sans.org | | Dan | Shires | dshires@sans.org | . . . <saída suprimida>
O que nos dá uma saída muito mais digerível! A qualquer hora, você pode checar o sumário de seu progresso e atividades com o comando “show dashboard”:
[recon-ng][sans][whois_pocs] > show dashboard +------------------------------------------+ | Activity Summary | +------------------------------------------+ | Module | Runs | +------------------------------------------+ | recon/domains-contacts/pgp_search | 1 | | recon/domains-contacts/whois_pocs | 1 | +------------------------------------------+ +----------------------------+ | Results Summary | +----------------------------+ | Category | Quantity | +----------------------------+ | Domains | 2 | | Companies | 1 | | Netblocks | 0 | | Locations | 0 | | Vulnerabilities | 0 | | Ports | 0 | | Hosts | 0 | | Contacts | 168 | | Credentials | 0 | | Leaks | 0 | | Pushpins | 0 | | Profiles | 0 | | Repositories | 0 | +----------------------------+
É possível obter mais detalhes de contatos com um módulo que emprega a API do Bing. Entretanto, para usar tal API, você precisará fazer uma assinatura do Azure. Dentro do ambiente, você precisará fazer uso dos Cognitive Services. A Microsoft fornece um período gratuito de avaliação. Este módulo (recon/companies-contacts/bing_linkedin_cache) pesquisa o LinkedIn e recupera contatos e as URLs de seus perfis. Ambas as tabelas (“contacts” e “profiles”) são atualizadas. Assim, fiz uma assinatura gratuita e criei um novo Cognitive Services usando a API do Bing. Depois disso, obtive duas chaves e adicionei uma delas ao Recon-NG usando o comando “keys add bing_api <chave>”. Depois, carreguei o módulo e o executei:
[recon-ng][sans] > use recon/companies-contacts/bing_linkedin_cache [recon-ng][sans][bing_linkedin_cache]> run ---- SANS ---- [*] Searching Bing API for: site:"linkedin.com/in/" "SANS" [*] [contact] Paulo Sans (<blank>) - Undetermined [*] [profile] paulo-sans-915a26140 - LinkedIn (https://br.linkedin.com/in/paulo-sans-915a26140) [*] [contact] Flavia Sans (<blank>) - Undetermined [*] [profile] flavia-sans-5b9411154 - LinkedIn (https://br.linkedin.com/in/flavia-sans-5b9411154) [*] [contact] Eduardo Sans (<blank>) - Undetermined [*] [profile] eduardosans - LinkedIn (https://br.linkedin.com/in/eduardosans) [*] [contact] ALBERTO SANS (<blank>) - Undetermined [*] [profile] alberto-sans-sans-ab71b327 - LinkedIn (https://br.linkedin.com/in/alberto-sans-sans-ab71b327) [*] [contact] Daniel Sans (<blank>) - Undetermined [*] [profile] daniel-sans - LinkedIn (https://br.linkedin.com/in/daniel-sans) . . . <saída suprimida> ------- SUMMARY ------- [*] 84 total (84 new) profiles found. [*] 84 total (74 new) contacts found. [recon-ng][sans][bing_linkedin_cache]> query select username, url from profiles +--------------------------------------------------------------------------------------------------------------------+ | username | url | +--------------------------------------------------------------------------------------------------------------------+ | paulo-sans-915a26140 | https://br.linkedin.com/in/paulo-sans-915a26140 | | flavia-sans-5b9411154 | https://br.linkedin.com/in/flavia-sans-5b9411154 | | eduardosans | https://br.linkedin.com/in/eduardosans | | alberto-sans-sans-ab71b327 | https://br.linkedin.com/in/alberto-sans-sans-ab71b327 | | daniel-sans | https://br.linkedin.com/in/daniel-sans | . . . <saída suprimida>
O que você não consegue ver da saída anterior (porque omiti boa parte dela e não mostrei a tabela “contacts” inteira) é que o módulo Bing não conseguiu obter corretamente os e-mails das pessoas. Isso pode acontecer algumas vezes. Para ajudar-nos nestas ocasiões, existe um módulo especial chamado “mangle” (recon/contacts-contacts/mangle). Uma vez carregado, quando você especifica um domínio inicial (sans.org, em nosso caso), ele percorre toda a tabela “contacts” e constrói os endereços de e-mail faltantes usando um padrão (como primeiro nome e último nome) e o domínio fornecido. Você configura o domínio com “set domain <domínio>”.
Verifique sua tabela com o comando “show contacts”. Você verá que uma grande parte dos contatos está sem endereço de e-mail. Observe ainda que os endereços de e-mail já descobertos usam o formato “primeira inicial” + “último nome” + “@sans.org”. Assim, podemos deduzir que todos os outros e-mails seguem o mesmo padrão. Felizmente, o módulo mangle permite configurar o padrão a ser seguido, apresentando algumas opções, como “primeira inicial”, “nome do meio”, “última inicial”, e assim por diante. Este parâmetro precisa ser alterado dentro do módulo mangle. Vejamos:
[recon-ng][sans][bing_linkedin_cache] > use recon/contacts-contacts/mangle [recon-ng][sans][mangle] > show info Name: Contact Name Mangler Path: modules/recon/contacts-contacts/mangle.py Author: Tim Tomes (@LaNMaSteR53) Description: Applies a mangle pattern to all of the contacts stored in the database, creating email addresses or usernames for each harvested contact. Updates the 'contacts' table with the results. Options: Name Current Value Required Description ---------- ------------- -------- ----------- DOMAIN no target email domain MAX-LENGTH 30 yes maximum length of email address prefix or username OVERWRITE False yes overwrite existing email addresses PATTERN <fn>.<ln> yes pattern applied to mangle first and last name SOURCE default yes source of input (see 'show info' for details) SUBSTITUTE - yes character to substitute for invalid email address characters Source Options: default SELECT rowid, first_name, middle_name, last_name, email FROM contacts ORDER BY first_name <string> string representing a single input <path> path to a file containing a list of inputs query <sql> database query returning one column of inputs Comments: * Pattern options: <fi>,<fn>,<mi>,<mn>,<li>,<ln> * Example: <fi>.<ln> => j.doe@domain.com * Note: Omit the 'domain' option to create usernames [recon-ng][sans][mangle] > set domain sans.org [recon-ng][sans][mangle] > set pattern <fi><ln> [recon-ng][sans][mangle] > query select first_name, last_name, email from contacts <saída suprimida> | Ben | Allen | ballen@sans.org | | Ryan | Browne | rbrowne@sans.org | | | Abuse | security@sans.org | | MATT | FEARNOW | MATT@sans.org | | David | Goldsmith | dgoldsmith@sans.org | | | Network Operations Center | noc@sans.org | | | Network Operations Center | it@sans.org | | Beatriz | Melo | | | Bruno | Beinotti | | | Danilo | Cerqueira | | | Fabio | Mello | | | Juliana | Camargo | | <saída suprimida> [recon-ng][sans][mangle] > run [recon-ng][sans][mangle] > query select first_name, last_name, email from contacts <saída suprimida> | Ben | Allen | ballen@sans.org | | Ryan | Browne | rbrowne@sans.org | | | Abuse | security@sans.org | | MATT | FEARNOW | MATT@sans.org | | David | Goldsmith | dgoldsmith@sans.org | | | Network Operations Center | noc@sans.org | | | Network Operations Center | it@sans.org | | Beatriz | Melo | bmelo@sans.org | | Bruno | Beinotti | bbeinotti@sans.org | | Danilo | Cerqueira | dcerqueira@sans.org | | Fabio | Mello | fmello@sans.org | | Juliana | Camargo | jcamargo@sans.org |
No próximo post, iremos mais a fundo na análise, obtendo ainda mais dados do SANS e explorando mais recursos do Recon-NG. Até lá!
0 comentário