Creando un notificador en Telegram con Bash

Vay3t
5 min readNov 21, 2020

¿En que consistirá el notificador?

Crearemos una herramienta la cual enviará un mensaje a un bot de Telegram creado y configurado por nosotros, de esta forma nos notificará ante algún evento que nosotros hallamos programado.

Se creará una herramienta en dos modalidades, como función para usarlo en ~/.bashrc y como herramienta de línea de comandos que estará ubicado en /usr/bin/.

Creando y configurando el bot con BotFather

Antes que nada necesitamos buscar el bot BotFather que nos ayudará a crear y administrar nuestros bots dándonos un token para poder usarlos.

  • En el bot se pueden usar las siguientes opciones:

Para añadir nuestro bot tenemos que usar el comando /newbot, luego colocarle un título y un nombre de usuario para poder identificarlo entre todos los usuarios y bots existentes. Luego de eso nos dará el link para acceder al chat del bot y un API token para trabajar e interactuar con él.

Programando el bot

Ya creado el bot, accedemos a su chat desde el link entregado luego de configurarlo y damos a /start.

Para hacer funcionar la herramienta es necesario saber nuestro id de chat (id de usuario de Telegram) que sirve para poder identificar qué usuario está interactuando con el bot. Para eso enviamos un mensaje de prueba al bot.

A continuación debemos obtener id del chat, con el siguiente link:

Este es un ejemplo de cómo obtener el dato necesario usando curl:

El campo id es nuestro identificador de chat, que será necesario para que nos lleguen las notificaciones a nuestra cuenta.

  • Este trozo de código tiene que ser añadido al final del archivo ~/.bashrc:

Para poder hacer válidos los cambios en el ~/.bashrc es necesario usar el comando source.

Luego se ejecuta desde la terminal usando el nombre de la función pusher. Tenemos tres formas de ejecutar:

  • STDIN. $ echo test text | pusher
  • Input por argumentos. $ pusher test text
  • Sin argumentos. $ pusher

Casos de uso

Es importante tener en cuenta para qué usaremos esta herramienta y las limitaciones que tendremos. Acomodé el script para que pueda ser usado como herramienta, independiente del ~/.bashrc, para casos particulares en los cuales no se pueda usar el recurso desde ahí, por ejemplo cuando ejecutamos una tarea programada en el crontab o usamos xargs, parallel o cuando ejecutamos dentro de un script en Bash:

> notify.sh

Herramienta que se usa en línea de comandos para notificar por Telegram.

Luego damos permiso de ejecución al script y lo movemos a /usr/bin/notify.sh:

Ejemplos

  • Bug bounty y pentesting para poder identificar si un ataque fue efectivo o no usando un if con los estados de salida de Bash ($?) y enviando la salida del comando al bot. En caso de querer realizar un comando de una línea es posible usar el operador booleano and (&&) y or (||).
Ejemplo para notificar cada dominio existente en cada mensaje.
Ejemplo para notificar todos los dominios existentes en un solo mensaje.
Ejemplo para notificar cuando se encuentren credenciales de autenticación básica.
  • Crontab, útil para tener un seguimiento de las tareas programadas que se estén llevando a cabo.

Al ejecutar crontab -e se despliega una pantalla donde uno puede programar tareas para que se ejecuten cada cierto tiempo o a una cierta hora. Un ejemplo para aplicar el notificador es el siguiente:

Ejemplo con tarea en crontab revisando un portal cada una hora.
  • Control de logs, en algunas ocasiones es necesario saber qué pasa por nuestro servidor para eso diseñamos un script que envía los resultados al bot en tiempo real.

> hotreader.sh

Script que envía notificaciones con las líneas añadidas de un archivo en tiempo real.

Modo de uso:

Leer logs DNS:

Herramienta que notifica las consultas DNS realizadas al servidor.

Conclusión

Esta herramienta que creamos prueba la versatilidad y utilidad de un lenguaje como Bash, que en conjunto con una herramienta como BotFather, puede utilizarse para todo tipo de tareas y en varias áreas. El notificador se puede usar para monitorear todo tipo de tareas, por ejemplo, tales como A, B y C. Lo único que se requiere para expandir los límites de la herramienta es tiempo y creatividad.

Bash le pone.

Bonus Track

Telegram Hot reader en Python:

#!/usr/bin/python3

import os.path
import sys
import urllib.request
import urllib.parse

# sudo pip3 install pyinotify
import pyinotify


# Usage
# python3 notifier.py <TextFile>

global lines

file_watcher = os.path.realpath(sys.argv[1])

def count_lines(file_name):
with open(file_name) as f:
count = len(f.readlines())
return count

def tail_n(file_name, n):
with open(file_name) as f:
lines = f.readlines()
return lines[-n:]

def list2string(list):
return "".join(list)

def sender(msj):
if msj == "":
msj = "[HotReader]"

token = "<TOKEN_BOT>"
chat_id = "<CHAT_ID>"

url = f"https://api.telegram.org/bot{token}/sendMessage"

values = {
"chat_id": chat_id,
"text": "[HotReader] " + msj
}

data = urllib.parse.urlencode(values)
data = data.encode('ascii')
req = urllib.request.Request(url, data)
urllib.request.urlopen(req)


# Example: monitors transient files.
#
# Run this code, then run transient_file.sh in another shell.


class ProcessTransientFile(pyinotify.ProcessEvent):

def process_IN_MODIFY(self, event):
global lines
# We have explicitely registered for this kind of event.
#print('\t', event.pathname, ' -> written')
lines_now = count_lines(file_watcher)
modified = tail_n(file_watcher, lines_now - lines)
print(list2string(modified))
lines = lines_now
sender(list2string(modified))


def process_default(self, event):
# Implicitely IN_CREATE and IN_DELETE are watched too. You can
# ignore them and provide an empty process_default or you can
# process them, either with process_default or their dedicated
# method (process_IN_CREATE, process_IN_DELETE) which would
# override process_default.
print('default: ', event.maskname)


lines = count_lines(file_watcher)

wm = pyinotify.WatchManager()
notifier = pyinotify.Notifier(wm)
# In this case you must give the class object (ProcessTransientFile)
# as last parameter not a class instance.
wm.watch_transient_file(file_watcher, pyinotify.IN_MODIFY, ProcessTransientFile)
notifier.loop()

Thanks Daniel Barrientos & elborikua.

--

--