
Herramienta de monitoreo continuo pasivo de subdominios autoalojada.
Herramienta de monitoreo de subdominios rápida y fácil de usar para la gestión continua de la superficie de ataque.

¿Por qué optar por sub.Monitor? Este programa ofrece una configuración sencilla gracias a su uso de SQLite para almacenar todos los dominios identificados (eliminando la necesidad de una gestión previa de la base de datos). Además, presume de una alta personalización, ya que los usuarios solo necesitan añadir unas pocas líneas de código al script usando sus herramientas elegidas. En contraste con otras soluciones existentes que dependen de bases de datos como MySQL o MongoDB, inicializar el script puede convertirse en una tarea tediosa.
sub.Monitor banderas:
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
Debes escribir las rutas de los archivos de configuración (api) en el archivo config.ini.
pip3 install -r requirements.txtPuedes implementar fácilmente tus propias herramientas en el script, solo modifica las líneas 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}'
Es importante tener en cuenta que si agregas una herramienta personalizada, la última salida debe ser los dominios resultantes para que sub.Monitor los guarde en la base de datos; por ejemplo, la forma de usarlo sería:
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
También añade el nombre de tu herramienta aquí:
for tool in ['subfinder', 'amass', 'assetfinder', 'my-custom-tool-name']:
run_tool(tool, domain, output_file)
Finalmente, por supuesto, debes agregar la herramienta en el archivo sub.monitor-config.ini para que el script de Python pueda obtener el binario desde ese archivo de configuración.
Lo único necesario es que una vez que el comando haya terminado, debe mostrar en la salida todos los dominios descubiertos para que la herramienta pueda guardarlos en el archivo de logs y dentro de la base de datos.
En primer lugar, sub.Monitor necesita una lista de dominios ya escaneados:
➜ cat ibm_sorted_subdomains.txt
test1.ibm.com
test2.ibm.com
test3.ibm.com
subtest.testX.ibm.com
...
Ahora, el archivo que contiene los subdominios se puede pasar a sub.Monitor con el siguiente 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.
También existe la posibilidad de añadir una bandera de fuera de alcance; por ejemplo, supongamos que un programa Bug Bounty tiene la siguiente política:
*.ibm.com - in scope
super-admin.ibm.com - out of scope
*.super-admin.ibm.com - out of scope
Es posible crear un archivo con esto:
cat outscope.txt
super-admin.ibm.com
*.super-admin.ibm.com
Ahora, puedes añadir manualmente todos los dominios descubiertos a la base de datos (filtrando los que están dentro del alcance):
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.
Esto añadirá todos tus subdominios a la base de datos, pero marcará todos los que están fuera de alcance con la bandera [Fuera de alcance] (veremos cómo filtrar los dominios dentro del alcance de la base de datos en la sección de volcado de dominios).
Para confirmar que el dominio ha sido añadido a la base de datos, ejecuta:
python3 monitor.py --list
_ ___ ___ _ _
| | | \/ | (_) |
___ _ _| |__ | . . | ___ _ __ _| |_ ___ _ __
/ __| | | | '_ \| |\/| |/ _ \| '_ \| | __/ _ \| '__|
\__ \ |_| | |_) | | | | (_) | | | | | || (_) | |
|___/\__,_|_.__/\_| |_/\___/|_| |_|_|\__\___/|_|
github.com/e1abrador/sub.Monitor
ibm.com [9 subdomains added manually] [2 subdomains discovered] [11 total unique in database]
Una vez que se ha cargado correctamente, el proceso de monitoreo puede comenzar. Se recomienda usar TMUX en una VPS y dejarlo ejecutándose durante mucho tiempo. Con el siguiente comando, el script ejecutará las herramientas de enumeración de subdominios y comparará los nuevos resultados con los antiguos. Si se encuentra algún subdominio nuevo, sub.Monitor lo añadirá primero a la base de datos local (para que no notifique más sobre ese descubrimiento) y luego notificará al usuario a través de Slack/Telegram/Discord.
python3 monitor.py -D ibm.com -H 12 --out-scope outscope.txt
Si se encuentra algún subdominio, sub.Monitor mostrará el siguiente mensaje en la salida:
➜ 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
También es posible monitorear más de 1 dominio, con el siguiente comando:
python3 monitor.py -df root-domains.txt -H 8
python3 monitor.py -df roots.txt -H 8 --out-scope outscope.txt
Después de que esos mensajes se reporten, al mismo tiempo el usuario recibirá las notificaciones en Telegram

¿Cómo gestiono las notificaciones? Encontré una forma bastante fácil (y fácil de gestionar) de ver todos los dominios recién descubiertos con Discord. Obtuve esto (difuminado ya que todos son programas privados):

La idea es primero crear una categoría con respecto al nombre del programa:
Yahoo
--- yahoo.com
--- yahoo.net
--- etc ...
IBM
--- ibm.com
--- whateverdomain.com
--- etc ...
Así es como se ve mi archivo de configuración de notify:

Recomiendo hacer esto para cada dominio (puede ser bastante tedioso configurarlo, pero es una excelente manera de gestionar los resultados). El script monitor.py enviará los resultados al webhook dado basado en el ID (que debe ser el mismo que el nombre del dominio a escanear).
Supongamos que el script ha estado ejecutándose durante 2 meses y quieres obtener todos los resultados (subdominios antiguos y recién descubiertos). Con sub.Monitor es posible usando la bandera --dump:
python3 monitor.py -D ibm.com --dump
_ ___ ___ _ _
| | | \/ | (_) |
___ _ _| |__ | . . | ___ _ __ _| |_ ___ _ __
/ __| | | | '_ \| |\/| |/ _ \| '_ \| | __/ _ \| '__|
\__ \ |_| | |_) | | | | (_) | | | | | || (_) | |
|___/\__,_|_.__/\_| |_/\___/|_| |_|_|\__\___/|_|
github.com/e1abrador/sub.Monitor
Subdomains for ibm.com:
subdomain1.ibm.com
subdomain2.ibm.com
...
También puedes usar el siguiente comando para ver el día en que se descubrió el dominio:
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 es muy probable que algunos dominios estén marcados como fuera de alcance usando el comando python3 monitor.py -d ibm.com --dump --info, para mostrar solo los dominios dentro del alcance es posible usar la bandera --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]
Gracias a:
Si tienes alguna idea de alguna nueva funcionalidad, abre un PR en https://github.com/e1abrador/sub.Monitor/pulls.
¡Buena suerte y buena cacería! Si realmente te encanta la herramienta (o cualquier otra), o te ayudó a encontrar un gran bounty, ¡considera COMPRARME UN CAFÉ! ☕ (¡Podría usar la cafeína!)
⚪ e1abrador
Twitter: https://twitter.com/e1abrador