
Ferramenta passiva auto-hospedada de monitoramento contínuo de subdomínios.
Ferramenta de monitoramento de subdomínios rápida e fácil de usar para gerenciamento contínuo da superfície de ataque.

Por que optar pelo sub.Monitor? Este programa oferece configuração fácil devido ao uso de SQLite para armazenar todos os domínios identificados (eliminando a necessidade de gerenciamento prévio de banco de dados). Além disso, possui alta personalização, onde os usuários precisam adicionar apenas algumas linhas de código ao script usando suas ferramentas escolhidas. Em contraste com outras soluções existentes que dependem de bancos de dados como MySQL ou MongoDB, a inicialização do script pode se tornar uma tarefa tediosa.
Opções do sub.Monitor:
options:
--add ADD Domain to scan
--out-scope OUT_SCOPE
File with out-of-scope domains
--file FILE File with known subdomains
-D DOMAIN, --domain DOMAIN
Domain to scan
-H HOURS, --hours HOURS
Hours between scans
--dump Dump all subdomains for a specific domain
--list List all root domains in the database
-df DF File with domains to scan
--inscope Dump only in-scope domains
--notinscope Dump only out-of-scope domains
--dumpall Dump all subdomains with their details
--info Show discovery date for subdomains
-help, -? Show this help message and exit
Você precisa escrever os caminhos dos arquivos de configuração (api) no arquivo config.ini.
pip3 install -r requirements.txtVocê pode facilmente implementar suas próprias ferramentas no script, basta modificar as linhas de código:
def run_tool(tool, domain, output_file):
print(f'[{datetime.datetime.now()}] - Running {tool} on {domain}')
if tool == 'assetfinder':
assetfinder_binary = config.get('Binary paths', 'assetfinder')
cmd = f'echo {domain} | {assetfinder_binary} -subs-only | grep -E "{domain}$" |grep -v "*" | grep -v "@"'
elif tool == 'subfinder':
subfinder_binary = config.get('Binary paths', 'subfinder')
subfinder_api = config.get('Api', 'subfinder_api')
cmd = f'{subfinder_binary} -d {domain} -silent -pc {subfinder_api} -all'
elif tool == 'amass':
amass_binary = config.get('Binary paths', 'amass')
amass_api = config.get('Api', 'amass_api')
cmd = f'{amass_binary} enum -passive -norecursive -noalts -d {domain} -config {amass_api}'
elif tool == 'my-custom-tool':
my-custom-tool-binary = config.get('Binary paths', 'my-custom-tool-binary-or-script')
cmd = f'{my-custom-tool-binary} -d {domain}'
É importante notar que, se você adicionar qualquer ferramenta personalizada, a última saída deve ser os resultados do domínio para que o sub.Monitor os salve no banco de dados. Por exemplo, a forma de usá-la seria:
cmd = f'bash customtool.sh {domain}''
...
cat customtool.sh
mycustomtool -d $1 > /tmp/$1.txt &>/dev/null; cat /tmp/$1.txt | unfurl domains | anew; rm -r /tmp/$1.txt
Adicione também o nome da sua ferramenta aqui:
for tool in ['subfinder', 'amass', 'assetfinder', 'my-custom-tool-name']:
run_tool(tool, domain, output_file)
Finalmente, claro, você precisa adicionar a ferramenta no arquivo sub.monitor-config.ini para que o script Python possa obter o binário desse arquivo de configuração.
A única coisa necessária é que, uma vez que o comando termine, ele deve mostrar na saída todos os domínios descobertos para que a ferramenta possa salvá-los no arquivo de logs e no banco de dados.
Primeiramente, o sub.Monitor precisa de uma lista de domínios já escaneados:
➜ cat ibm_sorted_subdomains.txt
test1.ibm.com
test2.ibm.com
test3.ibm.com
subtest.testX.ibm.com
...
Agora, o arquivo contendo os subdomínios pode ser passado para o sub.Monitor com o seguinte comando:
python3 monitor.py --add ibm.com --file ibm_sorted_subdomains.txt
_ ___ ___ _ _
| | | \/ | (_) |
___ _ _| |__ | . . | ___ _ __ _| |_ ___ _ __
/ __| | | | '_ \| |\/| |/ _ \| '_ \| | __/ _ \| '__|
\__ \ |_| | |_) | | | | (_) | | | | | || (_) | |
|___/\__,_|_.__/\_| |_/\___/|_| |_|_|\__\___/|_|
github.com/e1abrador/sub.Monitor
[2023-06-06 18:16:26.002521] - 538 subdomains were added to the local database.
Também existe a possibilidade de adicionar uma flag de fora do escopo. Por exemplo, suponha que um programa Bug Bounty tenha a seguinte política:
*.ibm.com - in scope
super-admin.ibm.com - out of scope
*.super-admin.ibm.com - out of scope
É possível criar um arquivo com esses itens:
cat outscope.txt
super-admin.ibm.com
*.super-admin.ibm.com
Agora, você pode adicionar manualmente todos os seus domínios descobertos ao banco de dados (filtrando aqueles que estão no escopo):
python3 monitor.py --add ibm.com --file ibm_sorted_subdomains.txt --out-scope outscope.txt
_ ___ ___ _ _
| | | \/ | (_) |
___ _ _| |__ | . . | ___ _ __ _| |_ ___ _ __
/ __| | | | '_ \| |\/| |/ _ \| '_ \| | __/ _ \| '__|
\__ \ |_| | |_) | | | | (_) | | | | | || (_) | |
|___/\__,_|_.__/\_| |_/\___/|_| |_|_|\__\___/|_|
github.com/e1abrador/sub.Monitor
[2023-06-06 18:16:26.002521] - 538 subdomains were added to the local database.
Isso adicionará todos os seus subdomínios ao banco de dados, mas marcará todos os que estão fora do escopo com a flag [Out of scope] (veremos como filtrar domínios no escopo do banco de dados na seção de exportação de domínios).
Para confirmar que o domínio foi adicionado ao banco de dados, execute:
python3 monitor.py --list
_ ___ ___ _ _
| | | \/ | (_) |
___ _ _| |__ | . . | ___ _ __ _| |_ ___ _ __
/ __| | | | '_ \| |\/| |/ _ \| '_ \| | __/ _ \| '__|
\__ \ |_| | |_) | | | | (_) | | | | | || (_) | |
|___/\__,_|_.__/\_| |_/\___/|_| |_|_|\__\___/|_|
github.com/e1abrador/sub.Monitor
ibm.com [9 subdomains added manually] [2 subdomains discovered] [11 total unique in database]
Uma vez carregado corretamente, o processo de monitoramento pode começar. É recomendado usar TMUX em uma VPS e deixá-lo rodando por um longo período. Com o seguinte comando, o script executará as ferramentas de enumeração de subdomínios e comparará os novos resultados com os antigos. Se algum novo subdomínio for encontrado, o sub.Monitor primeiro o adicionará ao banco de dados local (para não notificar mais sobre aquela descoberta) e depois notificará o usuário via Slack/Telegram/Discord.
python3 monitor.py -D ibm.com -H 12 --out-scope outscope.txt
Se algum subdomínio for encontrado, o sub.Monitor exibirá a seguinte mensagem na saída:
➜ python3 monitor.py -D ibm.com -H 8 # To filter the subdomains that are in the current scope from the out-scope ones, you can use:
# python3 monitor.py -D ibm.com -H 8 --out-scope outscope.txt
_ ___ ___ _ _
| | | \/ | (_) |
___ _ _| |__ | . . | ___ _ __ _| |_ ___ _ __
/ __| | | | '_ \| |\/| |/ _ \| '_ \| | __/ _ \| '__|
\__ \ |_| | |_) | | | | (_) | | | | | || (_) | |
|___/\__,_|_.__/\_| |_/\___/|_| |_|_|\__\___/|_|
github.com/e1abrador/sub.Monitor
[2023-06-06 18:07:25.191169] - New subdomain xxxx.ibm.com discovered
[2023-06-06 18:07:25.353156] - New subdomain xyxyxyxyxyx.ibm.com discovered
[2023-06-06 18:07:25.641082] - New subdomain x1.xxxx.ibm.com discovered
Também é possível monitorar mais de um domínio, com o seguinte comando:
python3 monitor.py -df root-domains.txt -H 8
python3 monitor.py -df roots.txt -H 8 --out-scope outscope.txt
Após essas mensagens serem reportadas, ao mesmo tempo o usuário receberá as notificações no Telegram

Como gerencio as notificações? Encontrei uma maneira bastante fácil (e fácil de gerenciar) de ver todos os domínios recém-descobertos com o Discord. Consegui isso (desfocado, pois todos são programas privados):

A ideia é primeiro criar uma categoria referente ao nome do programa:
Yahoo
--- yahoo.com
--- yahoo.net
--- etc ...
IBM
--- ibm.com
--- whateverdomain.com
--- etc ...
É assim que meu arquivo de configuração do notify se parece:

Recomendo fazer isso para cada domínio (pode ser bastante tedioso configurar isso, mas é uma ótima maneira de gerenciar os resultados). O script monitor.py enviará os resultados para o webhook fornecido com base no ID (que deve ser o mesmo nome do domínio a ser escaneado).
Digamos que o script esteja rodando há 2 meses e você queira obter todos os resultados (subdomínios antigos e recém-descobertos). Com o sub.Monitor, é possível usando a flag --dump:
python3 monitor.py -D ibm.com --dump
_ ___ ___ _ _
| | | \/ | (_) |
___ _ _| |__ | . . | ___ _ __ _| |_ ___ _ __
/ __| | | | '_ \| |\/| |/ _ \| '_ \| | __/ _ \| '__|
\__ \ |_| | |_) | | | | (_) | | | | | || (_) | |
|___/\__,_|_.__/\_| |_/\___/|_| |_|_|\__\___/|_|
github.com/e1abrador/sub.Monitor
Subdomains for ibm.com:
subdomain1.ibm.com
subdomain2.ibm.com
...
Você também pode usar o seguinte comando para ver o dia em que o domínio foi descoberto:
python3 monitor.py -D ibm.com --dump --info
_ ___ ___ _ _
| | | \/ | (_) |
___ _ _| |__ | . . | ___ _ __ _| |_ ___ _ __
/ __| | | | '_ \| |\/| |/ _ \| '_ \| | __/ _ \| '__|
\__ \ |_| | |_) | | | | (_) | | | | | || (_) | |
|___/\__,_|_.__/\_| |_/\___/|_| |_|_|\__\___/|_|
github.com/e1abrador/sub.Monitor
Subdomains for ibm.com:
test.ibm.com [discovered on 06/08/2023]
test2.ibm.com [discovered on 08/08/2023] [Out of scope]
Como é altamente provável que alguns domínios sejam marcados como fora do escopo usando o comando python3 monitor.py -d ibm.com --dump --info, para mostrar apenas os domínios no escopo, é possível usar a flag --inscope:
python3 monitor.py -D ibm.com --dump --info --inscope
_ ___ ___ _ _
| | | \/ | (_) |
___ _ _| |__ | . . | ___ _ __ _| |_ ___ _ __
/ __| | | | '_ \| |\/| |/ _ \| '_ \| | __/ _ \| '__|
\__ \ |_| | |_) | | | | (_) | | | | | || (_) | |
|___/\__,_|_.__/\_| |_/\___/|_| |_|_|\__\___/|_|
github.com/e1abrador/sub.Monitor
Subdomains for ibm.com:
test.ibm.com [discovered on 06/08/2023]
test3.ibm.com [discovered on 08/08/2023]
Agradecimentos a:
Se você tiver alguma ideia de nova funcionalidade, abra um PR em https://github.com/e1abrador/sub.Monitor/pulls.
Boa sorte e boas caçadas! Se você realmente ama a ferramenta (ou qualquer outra), ou se elas ajudaram você a encontrar uma recompensa incrível, considere COMPRAR-ME UM CAFÉ! ☕ (Eu poderia usar a cafeína!)
⚪ e1abrador
Twitter: https://twitter.com/e1abrador