-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #4 from OS2borgerPC/2-sikkerhedsscripts
issue #2 - tilføj sikkerhedsscripts. Disse vises under fanen 'Sikkerh…
- Loading branch information
Showing
6 changed files
with
400 additions
and
0 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
--- | ||
title: "Detekter nytilsluttet keyboard" | ||
parent: "Sikkerhed" | ||
source: scripts/detect_keyboard_event.py | ||
compatibility: | ||
- "22.04" | ||
- "BorgerPC" | ||
metadata: | ||
security: true | ||
--- | ||
|
||
## Beskrivelse | ||
Sikkerhedsscriptet identificerer ny-tilsluttede keyboards helt tilbage fra sidste gang systemet blev tjekket. Findes det resulterer det i en sikkerhedshændelse. | ||
At fjerne et keyboard giver IKKE en advarsel. | ||
|
||
BEMÆRK: Dette sikkerhedsscript er afhængigt af, om USB-enheden identificerer sig selv som et keyboard. Af denne grund, vil vi - såfremt det er muligt i jeres anvendelse - anbefale i stedet at benytte scriptet, der låser maskinen ved indsættelse af ALLE USB-enheder ("Bloker for login ved USB-event"), sammen med sikkerhedscriptet der giver en advarsel, når Borger-kontoen er blevet låst ("Detekter låst Borgerkonto"). | ||
|
||
Dette sikkerhedsscript virker både på OS2borgerPC og OS2borgerPC Kiosk, men vi mener det er mest relevant på førstnævnte, ift. faren ved keyloggers på publikumsmaskiner. | ||
|
||
VIGTIG BEMÆRKNING: | ||
Sikkerhedsscriptet er kun aktivt, når maskinen er tændt! | ||
|
||
Af ovenstående grund er det centralt, at besøgende ikke kan tilgå maskinerne mens de er slukket, uden at det opdages. | ||
|
||
Derfor foreslår vi at kombinere det med følgende tre scripts: | ||
|
||
1. Scriptet "Desktop - Fjern Luk Ned og Genstart fra sessionmenuen og blokér for nedlukning via systempolitik" | ||
|
||
2. Scriptet "OS2borgerPC - Blokér for login ved hård nedlukning" | ||
|
||
3. Sikkerhedsscriptet "Detekter låst Borgerkonto" | ||
|
||
Sammen betyder de tre: | ||
1. At brugeren ikke kan lukke maskinen ned fra menuen. | ||
2. Trykker de på knappen for at lukke den ned, eller hiver de strømstikket ud, så låses der for login for Borger-kontoen. (Da de potentielt være have indsat en keylogger) | ||
3. Hvis Borger-kontoen låses modtager man, pga. script tre, en sikkerhedshændelse | ||
|
||
Ønsker man slet ikke at Borgere skal kunne rode med USB-enheder så kan man bruge scriptet | ||
"OS2borgerPC - Blokér for login ved USB-event" | ||
Med dette andet script vil både at tilføje eller fjerne en USB-enhed mens maskinen er tændt, betyde at Borgeren logges øjeblikkeligt ud, og at der derefter låses for login. | ||
|
||
Når Borger-kontoen er låst kan man fra adminsitet køre scriptet "OS2borgerPC - Sæt bruger aktiv efter blokeret login (lås op)" for at åbne for login på Borger-kontoen igen. | ||
|
||
## Parametre | ||
Ingen |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
--- | ||
title: "Detekter sudo-kørsel" | ||
parent: "Sikkerhed" | ||
source: scripts/detect_sudo_event.py | ||
compatibility: | ||
- "22.04" | ||
- "BorgerPC" | ||
metadata: | ||
security: true | ||
--- | ||
|
||
## Beskrivelse | ||
Dette Sikkerhedsscript giver en sikkerhedshændelse ved sudo-kørsel. | ||
|
||
Dette script virker både på OS2borgerPC og OS2borgerPC Kiosk. | ||
|
||
Der gives både en advarsel hvis sudo køres med succes, hvis det fejler pga. det køres fra Borger fremfor superuser, eller den indtastede kode er forkert. | ||
Nærmere specifikt: | ||
sudo-kommandoen giver én tre forsøg på at indtaste koden - taster man forkert tre gange vil det give en advarsel. Taster man korrekt vil det ligeledes give en advarsel. | ||
|
||
Derfor: Hvis du har tilføjet en regel for en maskine, og du selv er inde på den fra superuser, vil der også komme en advarsel, hvis du kører sudo. | ||
|
||
Når du modtager en advarsel vil der ofte stå USER=root i beskeden. Dette betyder ikke, at brugeren allerede har root-adgang (dvs. administrator-adgang), men alene at brugeren, personen forsøger at køre kommandoer som, er administrator-kontoen. | ||
|
||
## Parametre | ||
Ingen |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
--- | ||
title: "Detekter låst Borgerkonto" | ||
parent: "Sikkerhed" | ||
source: scripts/detect_user_expired_event.py | ||
compatibility: | ||
- "22.04" | ||
- "BorgerPC" | ||
metadata: | ||
security: true | ||
--- | ||
|
||
## Beskrivelse | ||
Dette Sikkerhedsscript giver en Sikkerhedshændelse hvis Borger bliver låst ude/sat til udløbet. | ||
|
||
Dette script virker kun på OS2borgerPC, ikke OS2borgerPC Kiosk. | ||
|
||
Bruges sammen med en eller begge af følgende: | ||
- "Bloker for login ved USB-event" + "Sæt bruger aktiv efter blokeret login" | ||
- "OS2borgerPC - Bloker for login ved hård nedlukning" + "Sæt bruger aktiv efter blokeret login" | ||
|
||
## Parametre | ||
Ingen |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
#!/usr/bin/env python3 | ||
|
||
""" | ||
Security Script for finding USB keyboard attachment events | ||
""" | ||
|
||
import sys | ||
from datetime import datetime, timedelta | ||
import re | ||
|
||
__copyright__ = "Copyright 2017-2024 Magenta ApS" | ||
__license__ = "GPL" | ||
|
||
|
||
def log_read(last_security_check, log_name): | ||
"""Search a (system) log for events that occurred | ||
between "last_security_check" and now.""" | ||
log_event_tuples = [] | ||
now = datetime.now() | ||
|
||
with open(log_name) as f: | ||
for line in f.readlines(): | ||
line = str(line.replace("\0", "")) | ||
log_event_timestamp = line[:15] | ||
log_event = line.strip("\n") | ||
# convert from log event timestamp to security event log timestamp. | ||
log_event_datetime = datetime.strptime( | ||
str(now.year) + " " + log_event_timestamp, "%Y %b %d %H:%M:%S" | ||
) | ||
security_event_log_timestamp = datetime.strftime( | ||
log_event_datetime, "%Y%m%d%H%M%S" | ||
) | ||
# Detect lines from within the last x seconds to now. | ||
if last_security_check <= log_event_datetime <= now: | ||
log_event_tuples.append((security_event_log_timestamp, log_event)) | ||
|
||
return log_event_tuples | ||
|
||
|
||
def csv_writer(security_events): | ||
"""Write security events to security events file.""" | ||
with open("/etc/os2borgerpc/security/securityevent.csv", "at") as csvfile: | ||
for timestamp, security_problem_uid, log_event in security_events: | ||
event_line = log_event.replace("\n", " ").replace("\r", "").replace(",", "") | ||
csvfile.write(f"{timestamp},{security_problem_uid},{event_line}\n") | ||
|
||
|
||
def filter_duplicate_events(security_events): | ||
"""This function filters duplicate events related to | ||
the same keyboard""" | ||
|
||
unique_tuples = [] | ||
unique_keyboards = [] | ||
|
||
for security_event in security_events: | ||
# This identifier is based on the ID of the USB device. | ||
# The ID is identical for identical USB devices so | ||
# if two identical keyboards are inserted simultaneously, | ||
# only one event will be generated. | ||
regex = ( | ||
r"[0-9a-z]{4}:[0-9a-z]{4}:[0-9a-z]{4}" | ||
r"(?!.*/[0-9a-z]{4}:[0-9a-z]{4}:[0-9a-z]{4})" | ||
) | ||
match = re.search(regex, security_event[2], flags=re.IGNORECASE) | ||
# Keyboard event lines should always contain a match, but in order | ||
# to prevent possibly overlooking a relevant event, we always include | ||
# events with no match | ||
if match: | ||
keyboard_identifier = match.group(0) | ||
if keyboard_identifier not in unique_keyboards: | ||
unique_tuples.append(security_event) | ||
unique_keyboards.append(keyboard_identifier) | ||
else: # This part should never be relevant, but it is here just in case | ||
unique_tuples.append(security_event) | ||
|
||
return unique_tuples | ||
|
||
|
||
# The file to inspect for events | ||
log_name = "/var/log/syslog" | ||
|
||
now = datetime.now() | ||
# The default value in case lastcheck.txt is nonexisting or empty: | ||
last_security_check = now - timedelta(hours=24) | ||
try: | ||
with open("/etc/os2borgerpc/security/lastcheck.txt", "r") as fp: | ||
timestamp = fp.read() | ||
if timestamp: | ||
last_security_check = datetime.strptime(timestamp, "%Y%m%d%H%M%S") | ||
except IOError: | ||
pass | ||
|
||
log_event_tuples = log_read(last_security_check, log_name) | ||
|
||
security_problem_uid_template_var = "%SECURITY_PROBLEM_UID%" | ||
|
||
# Match keyboard events that are after 9.9999 seconds of boot up | ||
# (so we don't match upstart keyboard events), | ||
# Also remove system control and consumer control entries: | ||
# The reason is that some keyboards add three keyboard entries when connected. | ||
# Example from inserting a keyboard once: | ||
# Jun 28 14:24:43 kbh-nuc-venstre kernel: [ 1948.130701] input: Logitech HID compliant keyboard as /devices/pci0000:00/0000:00:14.0/usb1/1-3/1-3:1.0/0003:046D:C30E.000A/input/input25 | ||
# Jun 28 14:24:43 kbh-nuc-venstre kernel: [ 1948.264053] input: Logitech HID compliant keyboard System Control as /devices/pci0000:00/0000:00:14.0/usb1/1-3/1-3:1.1/0003:046D:C30E.000B/input/input27 | ||
# Jun 28 14:24:43 kbh-nuc-venstre kernel: [ 1948.204460] input: Logitech HID compliant keyboard Consumer Control as /devices/pci0000:00/0000:00:14.0/usb1/1-3/1-3:1.1/0003:046D:C30E.000B/input/input26 | ||
# Fortunately it seems Consumer Control and System Control aren't Logitech specific, as we've seen the exact same with Lenovo keyboards. | ||
# The second regex matches certain keyboards that do not generate a log line with "input:" and "Keyboard" | ||
# Most regular keyboards also generate a log line that matches the second regex, but | ||
# the duplicate events are removed by the filtering | ||
regexes = [ | ||
r".*\[[ ]{0,3}[0-9]{2,}\..*\] input: .*Keyboard " | ||
r"(?!((mouse )?system control))(?!((mouse )?consumer control)).*", | ||
r".*\[[ ]{0,3}[0-9]{2,}\..*\].*input,hidraw.*keyboard (?!mouse)", | ||
] | ||
|
||
# Filter log_event_tuples based on regex matches and put them | ||
# on the form the admin site expects: | ||
# (timestamp, security_problem_uid, summary) | ||
log_event_tuples = [ | ||
(log_timestamp, security_problem_uid_template_var, log_event) | ||
for (log_timestamp, log_event) in log_event_tuples | ||
if any([re.search(regex, log_event, flags=re.IGNORECASE) for regex in regexes]) | ||
] | ||
|
||
log_event_tuples = filter_duplicate_events(log_event_tuples) | ||
|
||
if not log_event_tuples: | ||
sys.exit() | ||
|
||
csv_writer(log_event_tuples) |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
#!/usr/bin/env python3 | ||
|
||
""" | ||
Security Script for finding sudo events | ||
""" | ||
|
||
import sys | ||
from datetime import datetime, timedelta | ||
import re | ||
|
||
__copyright__ = "Copyright 2017-2024 Magenta ApS" | ||
__license__ = "GPL" | ||
|
||
|
||
def log_read(last_security_check, log_name): | ||
"""Search a (system) log for events that occurred | ||
between "last_security_check" and now.""" | ||
log_event_tuples = [] | ||
now = datetime.now() | ||
|
||
with open(log_name) as f: | ||
for line in f.readlines(): | ||
line = str(line.replace("\0", "")) | ||
log_event_timestamp = line[:15] | ||
log_event = line.strip("\n") | ||
# convert from log event timestamp to security event log timestamp. | ||
log_event_datetime = datetime.strptime( | ||
str(now.year) + " " + log_event_timestamp, "%Y %b %d %H:%M:%S" | ||
) | ||
security_event_log_timestamp = datetime.strftime( | ||
log_event_datetime, "%Y%m%d%H%M%S" | ||
) | ||
# Detect lines from within the last x seconds to now. | ||
if last_security_check <= log_event_datetime <= now: | ||
log_event_tuples.append((security_event_log_timestamp, log_event)) | ||
|
||
return log_event_tuples | ||
|
||
|
||
def csv_writer(security_events): | ||
"""Write security events to security events file.""" | ||
with open("/etc/os2borgerpc/security/securityevent.csv", "at") as csvfile: | ||
for timestamp, security_problem_uid, log_event in security_events: | ||
event_line = log_event.replace("\n", " ").replace("\r", "").replace(",", "") | ||
csvfile.write(f"{timestamp},{security_problem_uid},{event_line}\n") | ||
|
||
|
||
# The file to inspect for events | ||
log_name = "/var/log/auth.log" | ||
|
||
now = datetime.now() | ||
# The default value in case lastcheck.txt is nonexisting or empty: | ||
last_security_check = now - timedelta(hours=24) | ||
try: | ||
with open("/etc/os2borgerpc/security/lastcheck.txt", "r") as fp: | ||
timestamp = fp.read() | ||
if timestamp: | ||
last_security_check = datetime.strptime(timestamp, "%Y%m%d%H%M%S") | ||
except IOError: | ||
pass | ||
|
||
log_event_tuples = log_read(last_security_check, log_name) | ||
|
||
security_problem_uid_template_var = "%SECURITY_PROBLEM_UID%" | ||
# Ignore if not a sudo event or if a sudo event from root | ||
regexes = [r"sudo:(?!\s*root).*COMMAND"] | ||
|
||
# Filter log_event_tuples based on regex matches and put them | ||
# on the form the admin site expects: | ||
# (timestamp, security_problem_uid, summary) | ||
log_event_tuples = [ | ||
(log_timestamp, security_problem_uid_template_var, log_event) | ||
for (log_timestamp, log_event) in log_event_tuples | ||
if any([re.search(regex, log_event, flags=re.IGNORECASE) for regex in regexes]) | ||
] | ||
|
||
if not log_event_tuples: | ||
sys.exit() | ||
|
||
csv_writer(log_event_tuples) |
Oops, something went wrong.