better readme
This commit is contained in:
@@ -1,116 +1,28 @@
|
|||||||
# OpenBSD-Notes
|
# OpenBSD-Notes
|
||||||
|
|
||||||
|
Time saver scripts installing and configuring basic stuff on secure OpenBSD installations
|
||||||
|
|
||||||
## Enviroment
|
## Enviroment
|
||||||
- Better prompt: Colors, Git, Exit Code,
|
- prompt : color prompt, git branch, latest exit Code
|
||||||
- Color ls
|
- navigation: color ls
|
||||||
|
- working : color grep, git aliases (ga, gs, gd, gc, gp)
|
||||||
|
|
||||||
## Packages
|
## Packages
|
||||||
- vim
|
- vim (no plugins, monokai theme, extra keymaps, intro screen for keymaps)
|
||||||
- git
|
- git, ggrep
|
||||||
- iftop, tcodump
|
- iftop, tcpdump
|
||||||
|
|
||||||
|
|
||||||
## Vim
|
## Vim
|
||||||
- Keymaps
|
- Keymaps
|
||||||
- Theme
|
- Theme
|
||||||
|
|
||||||
|
## Networking
|
||||||
|
- netstat-tulp.ksh (from linux)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
set -o vi
|
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
|
# 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