better readme
This commit is contained in:
@@ -1,116 +1,28 @@
|
||||
# OpenBSD-Notes
|
||||
|
||||
Time saver scripts installing and configuring basic stuff on secure OpenBSD installations
|
||||
|
||||
## Enviroment
|
||||
- Better prompt: Colors, Git, Exit Code,
|
||||
- Color ls
|
||||
- prompt : color prompt, git branch, latest exit Code
|
||||
- navigation: color ls
|
||||
- working : color grep, git aliases (ga, gs, gd, gc, gp)
|
||||
|
||||
## Packages
|
||||
- vim
|
||||
- git
|
||||
- iftop, tcodump
|
||||
|
||||
- vim (no plugins, monokai theme, extra keymaps, intro screen for keymaps)
|
||||
- git, ggrep
|
||||
- iftop, tcpdump
|
||||
|
||||
## Vim
|
||||
- Keymaps
|
||||
- Theme
|
||||
|
||||
|
||||
## Networking
|
||||
- netstat-tulp.ksh (from linux)
|
||||
|
||||
|
||||
|
||||
set -o vi
|
||||
|
||||
## Networking
|
||||
|
||||
Dynamic IP Address
|
||||
|
||||
`vi /etc/hostname.em0`
|
||||
|
||||
```sh
|
||||
dhcp
|
||||
```
|
||||
|
||||
Static IP Address
|
||||
|
||||
`vi /etc/hostname.stge0`
|
||||
|
||||
```sh
|
||||
media 100baseTX
|
||||
mediaopt full-duplex
|
||||
inet 192.168.2.1 0xffffff00
|
||||
```
|
||||
Routing
|
||||
|
||||
```sh
|
||||
route show
|
||||
netstat -r
|
||||
netstat -r -n
|
||||
netstat -r -f inet -n
|
||||
```
|
||||
|
||||
Default Gateway
|
||||
|
||||
`vi /etc/mygate`
|
||||
|
||||
```sh
|
||||
192.168.1.1
|
||||
```
|
||||
|
||||
Hostname
|
||||
|
||||
`vi /etc/myname`
|
||||
|
||||
```sh
|
||||
echo 'OpenBSD' > /etc/myname
|
||||
hostname OpenBSD
|
||||
```
|
||||
|
||||
Reload
|
||||
```sh
|
||||
|
||||
```
|
||||
|
||||
DNS
|
||||
|
||||
`vi /etc/resolv.conf`
|
||||
|
||||
```sh
|
||||
nameserver 9.9.9.9
|
||||
nameserver 1.1.1.1
|
||||
```
|
||||
|
||||
# Firewall
|
||||
|
||||
Control
|
||||
|
||||
```sh
|
||||
pfctl -sr # view rules
|
||||
pfctl -ss # view state
|
||||
pfctl -si # view stats
|
||||
pfctl -sa # view all
|
||||
```
|
||||
|
||||
Write Rules
|
||||
|
||||
`/etc/pf.conf`
|
||||
|
||||
```sh
|
||||
lan = stge0
|
||||
block out tcp from $lan to any port {80,443}
|
||||
```
|
||||
|
||||
Apply rules
|
||||
|
||||
```sh
|
||||
pfctl -d
|
||||
pfctl -f /etc/pf.conf
|
||||
pfctl -e
|
||||
```
|
||||
|
||||
|
||||
# Gitea
|
||||
|
||||
|
||||
|
||||
# WEB SERVER
|
||||
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
# Firewall
|
||||
|
||||
### Show rules
|
||||
|
||||
```sh
|
||||
pfctl -sr # view rules
|
||||
pfctl -ss # view state
|
||||
pfctl -si # view stats
|
||||
pfctl -sa # view all
|
||||
```
|
||||
|
||||
### Write rules
|
||||
|
||||
`/etc/pf.conf`
|
||||
|
||||
```sh
|
||||
lan = stge0
|
||||
block out tcp from $lan to any port {80,443}
|
||||
```
|
||||
|
||||
### Apply rules
|
||||
|
||||
```sh
|
||||
pfctl -d
|
||||
pfctl -f /etc/pf.conf
|
||||
pfctl -e
|
||||
```
|
||||
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
## Networking
|
||||
|
||||
### Set IP Address on interface `em0`
|
||||
|
||||
`vim /etc/hostname.em0`
|
||||
|
||||
Dynamic
|
||||
|
||||
```
|
||||
dhcp
|
||||
```
|
||||
|
||||
Static
|
||||
|
||||
```sh
|
||||
media 100baseTX
|
||||
mediaopt full-duplex
|
||||
inet 192.168.2.1 0xffffff00
|
||||
```
|
||||
### Routing
|
||||
|
||||
Show table
|
||||
|
||||
```sh
|
||||
route show
|
||||
netstat -r
|
||||
netstat -r -n
|
||||
netstat -r -f inet -n
|
||||
```
|
||||
|
||||
Set default Gateway
|
||||
|
||||
`vi /etc/mygate`
|
||||
|
||||
```sh
|
||||
192.168.1.1
|
||||
```
|
||||
|
||||
### Set hostname
|
||||
|
||||
`vi /etc/myname`
|
||||
|
||||
```sh
|
||||
echo 'OpenBSD' > /etc/myname
|
||||
hostname OpenBSD
|
||||
```
|
||||
|
||||
### Set DNS
|
||||
|
||||
`vi /etc/resolv.conf`
|
||||
|
||||
```sh
|
||||
nameserver 9.9.9.9
|
||||
nameserver 1.1.1.1
|
||||
```
|
||||
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
#!/bin/ksh
|
||||
|
||||
daemon="/usr/local/bin/node"
|
||||
daemon_user="_stevault"
|
||||
daemon_execdir="/usr/obj/stevault/backend"
|
||||
daemon_flags="/usr/obj/stevault/backend/dist/index.js"
|
||||
daemon_logger="daemon.info"
|
||||
|
||||
. /etc/rc.d/rc.subr
|
||||
|
||||
rc_reload=NO
|
||||
rc_bg=YES
|
||||
rc_cmd $1
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,3 @@
|
||||
pkg_add ggrep
|
||||
alias grep='ggrep --color=auto'
|
||||
. ~/.profile
|
||||
@@ -0,0 +1,285 @@
|
||||
#!/bin/ksh
|
||||
#
|
||||
# First-login security audit for OpenBSD.
|
||||
#
|
||||
# This script is intentionally diagnostic: it does not repair, install, or
|
||||
# reconfigure the host. OpenBSD security(8) may rotate its normal comparison
|
||||
# state in /var/backups, just as it does during the daily security run.
|
||||
# This script cannot prove that a host is clean.
|
||||
# A root-level attacker may alter the kernel, commands, logs, or this script's
|
||||
# view of the system. Treat warnings as reasons to investigate and credible
|
||||
# evidence of root compromise as a reason to isolate and reinstall the host.
|
||||
#
|
||||
# Exit status:
|
||||
# 0 No automatic red flags were found (not proof that the host is clean).
|
||||
# 1 One or more findings require manual review.
|
||||
# 2 The audit could not run correctly.
|
||||
|
||||
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin
|
||||
export PATH
|
||||
|
||||
umask 077
|
||||
|
||||
WARNINGS=0
|
||||
ERRORS=0
|
||||
|
||||
heading()
|
||||
{
|
||||
printf '\n===== %s =====\n' "$1"
|
||||
}
|
||||
|
||||
pass()
|
||||
{
|
||||
printf '[PASS] %s\n' "$1"
|
||||
}
|
||||
|
||||
info()
|
||||
{
|
||||
printf '[INFO] %s\n' "$1"
|
||||
}
|
||||
|
||||
warn()
|
||||
{
|
||||
printf '[WARN] %s\n' "$1"
|
||||
WARNINGS=$((WARNINGS + 1))
|
||||
}
|
||||
|
||||
error()
|
||||
{
|
||||
printf '[ERROR] %s\n' "$1" >&2
|
||||
ERRORS=$((ERRORS + 1))
|
||||
}
|
||||
|
||||
print_file()
|
||||
{
|
||||
if [ -s "$1" ]; then
|
||||
sed 's/^/ /' "$1"
|
||||
fi
|
||||
}
|
||||
|
||||
if [ "$(id -u)" -ne 0 ]; then
|
||||
printf 'Run this audit as root, for example:\n' >&2
|
||||
printf ' doas %s\n' "$0" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
if [ "$(uname -s)" != "OpenBSD" ]; then
|
||||
printf 'This script is intended only for OpenBSD.\n' >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
AUDIT_TMPDIR=$(mktemp -d /tmp/openbsd-audit.XXXXXXXXXX) || {
|
||||
printf 'Cannot create temporary audit directory.\n' >&2
|
||||
exit 2
|
||||
}
|
||||
|
||||
cleanup()
|
||||
{
|
||||
case "$AUDIT_TMPDIR" in
|
||||
/tmp/openbsd-audit.*)
|
||||
/bin/rm -rf "$AUDIT_TMPDIR"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
case "$AUDIT_TMPDIR" in
|
||||
/tmp/openbsd-audit.*)
|
||||
trap cleanup EXIT
|
||||
trap 'exit 2' HUP INT TERM
|
||||
;;
|
||||
*)
|
||||
printf 'Refusing unexpected temporary path: %s\n' "$AUDIT_TMPDIR" >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
|
||||
heading "IMPORTANT LIMITATION"
|
||||
cat <<'EOF'
|
||||
This report can find common integrity and persistence problems, but it cannot
|
||||
certify that the host is unhacked. A sufficiently privileged attacker can
|
||||
make a running system lie. For strong assurance, inspect from trusted boot
|
||||
media or reinstall from verified OpenBSD media and rotate exposed secrets.
|
||||
EOF
|
||||
|
||||
heading "SYSTEM IDENTITY"
|
||||
printf 'Date (UTC): %s\n' "$(date -u '+%Y-%m-%d %H:%M:%S UTC')"
|
||||
printf 'Hostname: %s\n' "$(hostname)"
|
||||
printf 'Kernel: %s\n' "$(uname -a)"
|
||||
printf 'Architecture: %s\n' "$(machine 2>/dev/null || uname -m)"
|
||||
printf 'Uptime: %s\n' "$(uptime)"
|
||||
|
||||
if [ -n "${SSH_CONNECTION:-}" ]; then
|
||||
set -- $SSH_CONNECTION
|
||||
printf 'SSH source: %s:%s\n' "$1" "$2"
|
||||
printf 'SSH destination: %s:%s\n' "$3" "$4"
|
||||
else
|
||||
printf 'SSH connection: not detected\n'
|
||||
fi
|
||||
|
||||
SECURELEVEL=$(sysctl -n kern.securelevel 2>/dev/null)
|
||||
if [ -z "$SECURELEVEL" ]; then
|
||||
error "Could not read kern.securelevel"
|
||||
elif [ "$SECURELEVEL" -ge 1 ] 2>/dev/null; then
|
||||
pass "kern.securelevel is $SECURELEVEL"
|
||||
else
|
||||
warn "kern.securelevel is $SECURELEVEL; review why it is below 1"
|
||||
fi
|
||||
|
||||
heading "OPENBSD SECURITY(8)"
|
||||
SECURITY_OUT="$AUDIT_TMPDIR/security.out"
|
||||
/usr/libexec/security >"$SECURITY_OUT" 2>&1
|
||||
SECURITY_RC=$?
|
||||
|
||||
if [ "$SECURITY_RC" -ne 0 ]; then
|
||||
warn "security(8) exited with status $SECURITY_RC"
|
||||
print_file "$SECURITY_OUT"
|
||||
elif [ -s "$SECURITY_OUT" ]; then
|
||||
warn "security(8) produced findings; review every line"
|
||||
print_file "$SECURITY_OUT"
|
||||
else
|
||||
pass "security(8) produced no findings"
|
||||
fi
|
||||
|
||||
heading "BASE SYSTEM PATCHES"
|
||||
printf '%s\n' "Installed syspatches:"
|
||||
syspatch -l 2>&1 | sed 's/^/ /'
|
||||
|
||||
SYSPATCH_OUT="$AUDIT_TMPDIR/syspatch.out"
|
||||
syspatch -c >"$SYSPATCH_OUT" 2>&1
|
||||
SYSPATCH_RC=$?
|
||||
|
||||
if [ "$SYSPATCH_RC" -ne 0 ]; then
|
||||
warn "Could not reliably check for missing syspatches (status $SYSPATCH_RC)"
|
||||
print_file "$SYSPATCH_OUT"
|
||||
elif [ -s "$SYSPATCH_OUT" ]; then
|
||||
warn "Available syspatches are not installed"
|
||||
print_file "$SYSPATCH_OUT"
|
||||
else
|
||||
pass "No missing syspatches were reported"
|
||||
fi
|
||||
|
||||
heading "INSTALLED PACKAGE INTEGRITY"
|
||||
PKG_OUT="$AUDIT_TMPDIR/pkg-check.out"
|
||||
pkg_check -n -F -x >"$PKG_OUT" 2>&1
|
||||
PKG_RC=$?
|
||||
|
||||
if [ "$PKG_RC" -ne 0 ]; then
|
||||
warn "pkg_check reported an error (status $PKG_RC)"
|
||||
print_file "$PKG_OUT"
|
||||
elif [ -s "$PKG_OUT" ]; then
|
||||
warn "pkg_check produced output; review package checksums and extra objects"
|
||||
print_file "$PKG_OUT"
|
||||
else
|
||||
pass "Installed package files and checksums passed pkg_check"
|
||||
fi
|
||||
|
||||
heading "PRIVILEGED ACCOUNTS"
|
||||
UID0_OUT="$AUDIT_TMPDIR/uid0.out"
|
||||
awk -F: '$3 == 0 { print $1 ":" $7 }' /etc/master.passwd >"$UID0_OUT"
|
||||
printf '%s\n' "Accounts with UID 0:"
|
||||
print_file "$UID0_OUT"
|
||||
|
||||
UID0_COUNT=$(wc -l <"$UID0_OUT" | tr -d ' ')
|
||||
if [ "$UID0_COUNT" -eq 1 ] && grep -q '^root:' "$UID0_OUT"; then
|
||||
pass "Only root has UID 0"
|
||||
else
|
||||
warn "Expected exactly one UID 0 account named root"
|
||||
fi
|
||||
|
||||
heading "SSH AUTHORIZED KEYS"
|
||||
KEY_LIST="$AUDIT_TMPDIR/authorized-keys.list"
|
||||
find /root /home -type f -path '*/.ssh/authorized_keys' -print \
|
||||
2>/dev/null >"$KEY_LIST"
|
||||
|
||||
if [ ! -s "$KEY_LIST" ]; then
|
||||
info "No authorized_keys files were found"
|
||||
else
|
||||
while IFS= read -r KEY_FILE; do
|
||||
printf '%s\n' "File: $KEY_FILE"
|
||||
ls -ld "$KEY_FILE" | sed 's/^/ /'
|
||||
ssh-keygen -lf "$KEY_FILE" 2>&1 | sed 's/^/ /'
|
||||
done <"$KEY_LIST"
|
||||
info "Confirm that every SSH key fingerprint belongs to an authorized person"
|
||||
fi
|
||||
|
||||
heading "RC SERVICES"
|
||||
printf '%s\n' "Enabled services:"
|
||||
rcctl ls on 2>&1 | sed 's/^/ /'
|
||||
|
||||
printf '%s\n' "Currently started services:"
|
||||
rcctl ls started 2>&1 | sed 's/^/ /'
|
||||
|
||||
FAILED_RC="$AUDIT_TMPDIR/rc-failed.out"
|
||||
rcctl ls failed >"$FAILED_RC" 2>&1
|
||||
FAILED_RC_STATUS=$?
|
||||
|
||||
if [ "$FAILED_RC_STATUS" -ne 0 ]; then
|
||||
warn "Could not query failed rc services"
|
||||
print_file "$FAILED_RC"
|
||||
elif [ -s "$FAILED_RC" ]; then
|
||||
warn "Some enabled services are in a failed state"
|
||||
print_file "$FAILED_RC"
|
||||
else
|
||||
pass "No failed rc services were reported"
|
||||
fi
|
||||
|
||||
heading "CRON PERSISTENCE LOCATIONS"
|
||||
if [ -d /var/cron/tabs ]; then
|
||||
find /var/cron/tabs -type f -exec ls -ld {} \; 2>/dev/null
|
||||
else
|
||||
warn "/var/cron/tabs does not exist"
|
||||
fi
|
||||
info "Review the content of every expected user crontab manually"
|
||||
|
||||
heading "RECENT LOGINS"
|
||||
last -20 2>&1
|
||||
|
||||
heading "RECENT SSH AUTHENTICATION EVENTS"
|
||||
if [ -r /var/log/authlog ]; then
|
||||
grep -Ei 'accepted|failed|invalid user|authentication' /var/log/authlog \
|
||||
2>/dev/null | tail -50
|
||||
else
|
||||
warn "Cannot read /var/log/authlog"
|
||||
fi
|
||||
|
||||
heading "RUNNING PROCESSES"
|
||||
ps auxww
|
||||
|
||||
heading "INTERNET SOCKETS AND CONNECTIONS"
|
||||
FSTAT_NET="$AUDIT_TMPDIR/fstat-network.out"
|
||||
fstat -n 2>/dev/null | grep -E 'internet|internet6' >"$FSTAT_NET"
|
||||
|
||||
if [ -s "$FSTAT_NET" ]; then
|
||||
cat "$FSTAT_NET"
|
||||
info "Confirm that every listener and remote connection is expected"
|
||||
else
|
||||
info "No internet sockets were reported by fstat"
|
||||
fi
|
||||
|
||||
heading "PF STATUS AND RULES"
|
||||
pfctl -si 2>&1
|
||||
printf '\nFilter rules:\n'
|
||||
pfctl -sr 2>&1
|
||||
printf '\nNAT and redirection rules:\n'
|
||||
pfctl -sn 2>&1
|
||||
|
||||
heading "FILESYSTEMS"
|
||||
mount
|
||||
df -h
|
||||
|
||||
heading "AUDIT RESULT"
|
||||
if [ "$ERRORS" -gt 0 ]; then
|
||||
printf '[ERROR] Audit incomplete: %d error(s), %d warning(s).\n' \
|
||||
"$ERRORS" "$WARNINGS"
|
||||
printf 'Do not treat this host as verified.\n'
|
||||
exit 2
|
||||
elif [ "$WARNINGS" -gt 0 ]; then
|
||||
printf '[WARN] Manual review required: %d warning(s).\n' "$WARNINGS"
|
||||
printf 'Warnings are not proof of compromise, but they must be explained.\n'
|
||||
exit 1
|
||||
else
|
||||
printf '[PASS] No automatic red flags were found.\n'
|
||||
printf 'This increases confidence but does not prove that the host is clean.\n'
|
||||
exit 0
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user