Seguro que si sóis unos paranóicos como yo siempre os rondará por la cabeza la idea de que alguno de vuestros servidores pueda estar comprometido sin tan siquiera saberlo, en este artÃculo explicaré como programar un sencillo parseador de logs mediante Python, de este modo cuando se produzca un acceso SSH seremos informados vÃa Telegram.
Para mejorar la seguridad del servicio SSH primero denegaremos el acceso como root al servidor y deshabilitaremos el acceso por password:
PermitRootLogin no
PubkeyAuthentication yes
PasswordAuthentication no
ChallengeResponseAuthentication no
UsePAM yes
Reiniciamos el servicio:
Nuestro script de parseo necesitará algunas dependencias, instalamos Python y Pip:
Instalamos las dependencias mediante Pip:
El parseador tendrá el siguiente código:
#!/usr/local/bin/python
import time
import os
import re
import requests
import socket
print('')
print('---------------------------------')
print('| Auth Log Parser v0.1b by kr0m |')
print('---------------------------------')
def sendMessage(msg):
apiKey = "API_KEY"
userId = "USER_ID"
data = {"chat_id":userId,"text":msg}
url = "https://api.telegram.org/bot{}/sendMessage".format(apiKey)
r = requests.post(url,json=data)
logfile = open("/var/log/auth.log","r")
logfile.seek(0, os.SEEK_END)
while True:
logline = logfile.readline()
if not logline:
time.sleep(0.1)
continue
else:
#print('- LogLine: %s' % logline)
m = re.search(".*Accepted (.*) for (.*) from (.*) port.*", logline)
if m:
print('>> SSH LogIN -> User: %s - IP: %s - AuthType: %s' % (m.group(2), m.group(3), m.group(1)))
hostname = socket.gethostname()
message = 'SSH LogIN: '+hostname+'\n User: '+m.group(2)+'\n IP: '+m.group(3)+'\n AuthType: '+m.group(1)
sendMessage(message)
continue
m = re.search(".*Disconnected from user (.*) (.*) port.*", logline)
if m:
print('>> SSH LogOut -> User: %s - IP: %s' % (m.group(1), m.group(2)))
hostname = socket.gethostname()
message = 'SSH LogOut: '+hostname+'\n User: '+m.group(1)+'\n IP: '+m.group(2)
sendMessage(message)
continue
Asignamos los permisos necesarios:
Demonizamos el script mediante un script de RC:
#! /bin/sh
#
# $FreeBSD$
#
# PROVIDE: sshAccess
# REQUIRE: DAEMON
# KEYWORD: shutdown
. /etc/rc.subr
name="sshAccess"
rcvar="${name}_enable"
extra_commands="status"
start_cmd="${name}_start"
stop_cmd="${name}_stop"
status_cmd="${name}_status"
sshAccess_start(){
echo "Starting service: ${name}"
/usr/sbin/daemon -S -p /var/run/${name}.pid -T sshAccess -u root /root/.scripts/sshAccess.py
}
sshAccess_stop(){
if [ -f /var/run/${name}.pid ]; then
echo "Stopping service: ${name}"
kill -s INT $(cat /var/run/${name}.pid)
sleep 3
else
echo "It appears ${name} is not running."
fi
}
sshAccess_status(){
if [ -f /var/run/${name}.pid ]; then
echo "${name} running with PID: $(cat /var/run/${name}.pid)"
else
echo "It appears ${name} is not running."
fi
}
load_rc_config ${name}
run_rc_command "$1"
Asignamos los permisos y propietario/grupo necesarios al script RC:
chown root:wheel /usr/local/etc/rc.d/sshAccess
Habilitamos el servicio y lo arrancamos:
service sshAccess start
Cuando alguien acceda nuestro servidor recibiremos una notificación como esta:
Cuando haga logout también:
Si no hemos sido nosotros algo huele muy mal, seguramente nuestro servidor haya sido comprometido.