LSMS/scripts/search_ssh_leftover_process...

120 lines
3.3 KiB
Python
Executable File

#!/usr/bin/env python3
# written by sqall
# twitter: https://twitter.com/sqall01
# blog: https://h4des.org
# github: https://github.com/sqall01
#
# Licensed under the MIT License.
"""
Short summary:
Searches for processes that were started by an SSH session that is now disconnected.
Requirements:
None
Reference:
https://twitter.com/CraigHRowland/status/1579582776529281026
"""
import os
import re
import sys
from lib.util import output_error, output_finding
# Read configuration.
try:
from config.config import ALERTR_FIFO, FROM_ADDR, TO_ADDR
from config.search_ssh_leftover_processes import ACTIVATED
except:
ALERTR_FIFO = None
FROM_ADDR = None
TO_ADDR = None
ACTIVATED = True
def search_leftover_ssh_process():
# Decide where to output results.
print_output = False
if ALERTR_FIFO is None and FROM_ADDR is None and TO_ADDR is None:
print_output = True
if not ACTIVATED:
if print_output:
print("Module deactivated.")
return
# Search for SSH_CONNECTION and SSH_CLIENT
fd = os.popen("grep -l SSH_C /proc/*/environ 2> /dev/null")
ssh_processes = fd.read().strip()
fd.close()
for ssh_process in ssh_processes.split("\n"):
# Example output: /proc/996/environ
# noinspection RegExpRedundantEscape
matches = re.search(r'proc/(\d*)/environ', ssh_process, re.IGNORECASE)
if not matches:
continue
pid = matches.group(1)
try:
with open("/proc/" + str(pid) + "/status", "r") as fp:
status_data = fp.read()
except FileNotFoundError: # Process got terminated while searching
continue
ppid = None
name = None
for line in status_data.split("\n"):
if line.startswith("PPid:"):
line_split = line.split("\t")
try:
ppid = int(line_split[-1])
except Exception as e:
output_error(__file__, "PPid not parsable for pid %d\n\n%s\n\n%s" % (pid, status_data, str(e)))
break
elif line.startswith("Name:"):
line_split = line.split("\t")
name = line_split[-1]
if ppid is not None and name is not None:
break
if ppid is not None and name is not None:
if ppid == 1:
# Get executed file
exe_link = "/proc/" + str(pid) + "/exe"
fd = os.popen("ls -laR %s" % exe_link)
exe_raw = fd.read().strip()
fd.close()
matches = re.search(r'/proc/\d*/exe -> (.*)', exe_raw, re.IGNORECASE)
exe_file = exe_raw
if matches:
exe_file = matches.group(1)
message = "Leftover process of SSH session found.\n\n"
message += "Name: %s\n" % name
message += "Exe: %s\n" % exe_file
message += "Pid: %s\n" % pid
output_finding(__file__, message)
if __name__ == '__main__':
is_init_run = False
if len(sys.argv) == 2:
if sys.argv[1] == "--init":
is_init_run = True
# Script does not need to establish a state.
if not is_init_run:
search_leftover_ssh_process()