Last active
October 23, 2023 10:15
-
-
Save HorlogeSkynet/054e363ade6093e24dd97ea19debff9e to your computer and use it in GitHub Desktop.
A simple SSH hook for OpenSSH and Discord
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
""" | |
@author : Samuel FORESTIER | |
@date : Created on 26/10/2017 | |
@version : 1.2.1 | |
@url : https://samuel.forestier.app/blog/security/a-ssh-monitoring-platform-with-discord | |
""" | |
# Packages required : | |
# * python3 | |
# * python3-requests | |
# * dnsutils | |
import signal | |
import requests | |
from os import getenv | |
from subprocess import check_output, DEVNULL, \ | |
TimeoutExpired, CalledProcessError | |
# Discord Web-hook information go here | |
WEBHOOK_ID = 'YOUR_WEBHOOK_ID' | |
WEBHOOK_TOKEN = 'YOUR_WEBHOOK_TOKEN' | |
# ____________________________________ | |
# Free Mobile SMS API credentials go here | |
SEND_SMS_ON_FAIL = False | |
FREE_USERNAME = 'YOUR_FREE_USERNAME' | |
FREE_PASSWORD = 'YOUR_FREE_PASSWORD' | |
# _______________________________________ | |
if __name__ == '__main__': | |
# Before anything else, we set signal handlers... | |
# ... to keep the attacker from stopping this script with its keyboard | |
signal.signal(signal.SIGINT, signal.SIG_IGN) # Disable CTRL + C (^C) | |
signal.signal(signal.SIGTSTP, signal.SIG_IGN) # Disable CTRL + Z (^Z) | |
signal.signal(signal.SIGQUIT, signal.SIG_IGN) # Disable CTRL + \ (^\) | |
# Here we get the IP address of the inner connection | |
remote_ip = getenv('SSH_CONNECTION', 'Unknown').split(' ')[0] | |
# Here we (try to) do a reverse DNS request on the address IP | |
try: | |
reverse = check_output(['dig', '-x', remote_ip, '+short'], | |
stderr=DEVNULL, | |
timeout=1 | |
).decode().split('\n')[0].replace('*', '\*') | |
# If the reverse DNS did not bring any result... | |
reverse = reverse or remote_ip | |
except (FileNotFoundError, TimeoutExpired, CalledProcessError): | |
# If `dig` is not available, or the DNS query was too long... | |
reverse = remote_ip | |
# Which session has been opened ? | |
whoami = check_output(['whoami']).decode().rstrip().replace('*', '\*') | |
# Which server is accessed ? | |
hostname = check_output(['hostname']).decode().rstrip().replace('*', '\*') | |
# Execute the query ! | |
try: | |
requests.post( | |
'https://discordapp.com/api/webhooks/{0}/{1}'.format( | |
WEBHOOK_ID, | |
WEBHOOK_TOKEN | |
), | |
json={ | |
'content': 'The session **{0}** has just been opened on' | |
' **{1}** by **{2}** !' | |
.format(whoami, hostname, reverse) | |
}, | |
headers={ | |
'content-type': 'application/json' | |
}, | |
timeout=2 | |
).raise_for_status() | |
except (requests.exceptions.HTTPError, requests.exceptions.Timeout): | |
# The request couldn't be posted as well. Are we sending a SMS now ? | |
if SEND_SMS_ON_FAIL: | |
try: | |
requests.post( | |
'https://smsapi.free-mobile.fr/sendmsg', | |
params={ | |
'user': FREE_USERNAME, | |
'pass': FREE_PASSWORD, | |
'msg': 'The session {0} has just been opened on {1}' | |
' by {2} !'.format(whoami, hostname, reverse) | |
}, | |
timeout=3 | |
) | |
except requests.exceptions.Timeout: | |
# In this case, it's complicated to inform the sys-admin :'( | |
pass |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment