LSMS/scripts/monitor_passwd.py

119 lines
3 KiB
Python
Raw Normal View History

2021-12-27 13:52:26 +01:00
#!/usr/bin/env python3
# written by sqall
# twitter: https://twitter.com/sqall01
# blog: https://h4des.org
# github: https://github.com/sqall01
#
2021-12-30 20:48:17 +01:00
# Licensed under the MIT License.
2021-12-27 13:52:26 +01:00
"""
Short summary:
Monitor /etc/passwd for changes to detect malicious attempts to hijack/change users.
Requirements:
None
"""
import os
from typing import Dict
2022-01-05 20:16:57 +01:00
from lib.state import load_state, store_state
from lib.util import output_error, output_finding
2021-12-27 13:52:26 +01:00
2022-01-05 20:16:57 +01:00
# Read configuration.
2021-12-27 13:52:26 +01:00
try:
from config.config import ALERTR_FIFO, FROM_ADDR, TO_ADDR, STATE_DIR
from config.monitor_passwd import ACTIVATED
STATE_DIR = os.path.join(os.path.dirname(__file__), STATE_DIR, os.path.basename(__file__))
except:
ALERTR_FIFO = None
FROM_ADDR = None
TO_ADDR = None
ACTIVATED = True
STATE_DIR = os.path.join("/tmp", os.path.basename(__file__))
def _get_passwd() -> Dict[str, str]:
passwd_data = {}
with open("/etc/passwd", 'rt') as fp:
for line in fp:
line = line.strip()
if line == "":
continue
entry = line.strip().split(":")
user = entry[0]
passwd_data[user] = line
return passwd_data
2022-01-05 20:16:57 +01:00
def monitor_passwd():
2021-12-27 13:52:26 +01:00
# 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
stored_passwd_data = {}
try:
2022-01-05 20:16:57 +01:00
stored_passwd_data = load_state(STATE_DIR)
2021-12-27 13:52:26 +01:00
except Exception as e:
2022-01-05 20:16:57 +01:00
output_error(__file__, str(e))
2021-12-27 13:52:26 +01:00
return
curr_passwd_data = {}
try:
curr_passwd_data = _get_passwd()
except Exception as e:
2022-01-05 20:16:57 +01:00
output_error(__file__, str(e))
2021-12-27 13:52:26 +01:00
return
# Compare stored data with current one.
for stored_entry_user in stored_passwd_data.keys():
# Extract current entry belonging to the same user.
if stored_entry_user not in curr_passwd_data.keys():
2022-01-05 20:16:57 +01:00
message = "User '%s' was deleted." % stored_entry_user
2021-12-27 13:52:26 +01:00
2022-01-05 20:16:57 +01:00
output_finding(__file__, message)
2021-12-27 13:52:26 +01:00
continue
# Check entry was modified.
if stored_passwd_data[stored_entry_user] != curr_passwd_data[stored_entry_user]:
2022-01-05 20:16:57 +01:00
message = "Passwd entry for user '%s' was modified.\n\n" % stored_entry_user
2021-12-27 13:52:26 +01:00
message += "Old entry: %s\n" % stored_passwd_data[stored_entry_user]
message += "New entry: %s" % curr_passwd_data[stored_entry_user]
2022-01-05 20:16:57 +01:00
output_finding(__file__, message)
2021-12-27 13:52:26 +01:00
# Check new data was added.
for curr_entry_user in curr_passwd_data.keys():
if curr_entry_user not in stored_passwd_data.keys():
2022-01-05 20:16:57 +01:00
message = "User '%s' was added.\n\n" % curr_entry_user
2021-12-27 13:52:26 +01:00
message += "Entry: %s" % curr_passwd_data[curr_entry_user]
2022-01-05 20:16:57 +01:00
output_finding(__file__, message)
2021-12-27 13:52:26 +01:00
try:
2022-01-05 20:16:57 +01:00
store_state(STATE_DIR, curr_passwd_data)
2021-12-27 13:52:26 +01:00
except Exception as e:
2022-01-05 20:16:57 +01:00
output_error(__file__, str(e))
2021-12-27 13:52:26 +01:00
if __name__ == '__main__':
2022-01-05 20:16:57 +01:00
monitor_passwd()