Created
March 19, 2026 12:55
-
-
Save SebastiaanKloos/56a3c9a06bf99ce4950c006c0feec16c to your computer and use it in GitHub Desktop.
Security check voor algemeen gebruik
This file contains hidden or 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
| #!/bin/bash | |
| # ============================================================ | |
| # Server Security Check Script | |
| # Controleert op verdachte processen, open poorten en | |
| # misconfiguraties na een incident of als preventieve check. | |
| # Gebruik: sudo bash security_check.sh | |
| # ============================================================ | |
| RED='\033[0;31m' | |
| YELLOW='\033[1;33m' | |
| GREEN='\033[0;32m' | |
| BLUE='\033[0;34m' | |
| NC='\033[0m' | |
| warn() { echo -e "${YELLOW}[WAARSCHUWING]${NC} $1"; } | |
| alert() { echo -e "${RED}[GEVAAR]${NC} $1"; } | |
| ok() { echo -e "${GREEN}[OK]${NC} $1"; } | |
| info() { echo -e "${BLUE}[INFO]${NC} $1"; } | |
| header() { echo -e "\n========== $1 =========="; } | |
| echo "============================================================" | |
| echo " Server Security Check — $(date)" | |
| echo " Hostname: $(hostname)" | |
| echo "============================================================" | |
| # ------------------------------------------------------------ | |
| header "1. VERDACHTE PROCESSEN" | |
| # ------------------------------------------------------------ | |
| # Bekende legitieme procesnamen voor whitelist | |
| KNOWN_SHORT="systemd|python|python3|nginx|mysqld|redis|redis-server|alloy|postfix|snapd|sshd|bash|sh|dash|node|perl5|flowguard|memcached|rsyslogd|journald|networkd|resolved|timesyncd|logind|polkitd|udisksd|upowerd|dockerd|containerd|irqbalance|multipathd|packagekitd|crond|atd|acpid|ModemManager|agetty|dbus-daemon|fail2ban|supervisord" | |
| # Processen zonder volledig pad — gebruik eenvoudigere grep zonder speciale haakjes | |
| echo "Processen zonder volledig pad (legitieme namen uitgefilterd):" | |
| SUSPICIOUS=$(ps aux | awk 'NR>1 {print $1, $2, $11}' \ | |
| | awk '$3 !~ /^\// && $3 !~ /^\[/' \ | |
| | grep -v "^root " \ | |
| | grep -vE "systemd|sshd|nginx|php|dbus|sd-pam|agetty|bash|sh|ps|grep|awk|sed|sort|uniq|cat|ls|find|cut|tr|head|tail|wc|date|tee|xargs|cp|mv|rm|chmod|python|node|docker|containerd") | |
| if [ -n "$SUSPICIOUS" ]; then | |
| echo "$SUSPICIOUS" | while IFS= read -r line; do | |
| alert "Verdacht proces zonder pad: $line" | |
| done | |
| else | |
| ok "Geen verdachte processen zonder pad" | |
| fi | |
| # Processen met exact 6-8 kleine letters als volledige naam | |
| echo "" | |
| echo "Processen met willekeurige korte naam (mogelijke malware):" | |
| RANDOM_NAMES=$(ps aux | awk 'NR>1 {print $11}' \ | |
| | grep -oE '^[a-z]{6,8}$' \ | |
| | grep -vE "^($KNOWN_SHORT)$" \ | |
| | sort -u) | |
| if [ -n "$RANDOM_NAMES" ]; then | |
| while IFS= read -r proc; do | |
| alert "Mogelijk verdacht proces: $proc" | |
| done <<< "$RANDOM_NAMES" | |
| else | |
| ok "Geen processen met verdacht willekeurige korte naam" | |
| fi | |
| # Perl processen | |
| echo "" | |
| echo "Perl processen (altijd handmatig controleren):" | |
| PERL_PROCS=$(ps aux | grep -E ' perl | perl$' | grep -v grep) | |
| if [ -n "$PERL_PROCS" ]; then | |
| warn "Perl processen gevonden — controleer of dit legitiem is:" | |
| echo "$PERL_PROCS" | |
| echo "$PERL_PROCS" | awk '{print $2}' | while read -r pid; do | |
| exe=$(ls -la /proc/$pid/exe 2>/dev/null) | |
| fd3=$(ls -la /proc/$pid/fd/3 2>/dev/null) | |
| info " PID $pid exe: $exe" | |
| [ -n "$fd3" ] && warn " PID $pid fd/3 (script): $fd3" | |
| done | |
| else | |
| ok "Geen Perl processen actief" | |
| fi | |
| # Hoog CPU gebruik | |
| echo "" | |
| echo "Processen met >10% CPU (mogelijke cryptominers):" | |
| LEGIT_CPU="nginx|php|mysql|mysqld|redis|node|python|docker|containerd|alloy|java|ruby|kworker|ksoftirq|migration|jbd2|kcompact" | |
| HIGH_CPU=$(ps aux | awk 'NR>1 && $3 > 10.0 {print}' | grep -vE "$LEGIT_CPU") | |
| if [ -n "$HIGH_CPU" ]; then | |
| warn "Hoog CPU gebruik door mogelijk onbekend proces:" | |
| echo "$HIGH_CPU" | |
| else | |
| ok "Geen onverwacht hoog CPU gebruik" | |
| fi | |
| # Processen die draaien vanuit /tmp of /var/tmp | |
| echo "" | |
| echo "Processen die draaien vanuit /tmp of /var/tmp:" | |
| TMP_PROCS="" | |
| for pid in /proc/[0-9]*; do | |
| exe=$(readlink "$pid/exe" 2>/dev/null) | |
| if echo "$exe" | grep -qE "^/tmp|^/var/tmp|^/dev/shm"; then | |
| cmdline=$(cat "$pid/cmdline" 2>/dev/null | tr '\0' ' ' | cut -c1-80) | |
| TMP_PROCS="$TMP_PROCS\nPID $(basename $pid): $exe | $cmdline" | |
| fi | |
| done | |
| if [ -n "$TMP_PROCS" ]; then | |
| alert "Processen gevonden die draaien vanuit tmp:" | |
| echo -e "$TMP_PROCS" | |
| else | |
| ok "Geen processen draaien vanuit /tmp of /var/tmp" | |
| fi | |
| # Deleted binaries — fileless malware | |
| echo "" | |
| echo "Processen met verwijderde binaries (fileless malware):" | |
| DELETED=$(ls -la /proc/[0-9]*/exe 2>/dev/null | grep " (deleted)" | grep -v "^total") | |
| if [ -n "$DELETED" ]; then | |
| alert "Processen met verwijderd binary — mogelijke fileless malware:" | |
| echo "$DELETED" | |
| else | |
| ok "Geen processen met verwijderde binaries" | |
| fi | |
| # ------------------------------------------------------------ | |
| header "2. OPEN NETWERK POORTEN" | |
| # ------------------------------------------------------------ | |
| echo "Alle luisterende services:" | |
| ss -tulpn 2>/dev/null | |
| echo "" | |
| echo "Controle op gevaarlijke publiek bereikbare services:" | |
| check_public() { | |
| local port=$1 | |
| local name=$2 | |
| local fix=$3 | |
| # Alleen gevaarlijk als het luistert op 0.0.0.0 of :: (alle interfaces) | |
| # 127.0.0.1 en [::1] zijn veilig (lokaal only) | |
| if ss -tulpn 2>/dev/null | grep ":$port " | grep -vE "127\.0\.0\.1|^\[::1\]|\[::1\]:" | grep -qE "0\.0\.0\.0|^\*|::$| ::|::\]"; then | |
| alert "$name luistert publiek op poort $port — aanvalsvector!" | |
| [ -n "$fix" ] && info "Fix: $fix" | |
| else | |
| ok "$name niet publiek bereikbaar" | |
| fi | |
| } | |
| check_public 11211 "Memcached" "sudo sed -i 's/-l 0.0.0.0/-l 127.0.0.1/' /etc/memcached.conf && sudo systemctl restart memcached" | |
| check_public 6379 "Redis" "sudo sed -i 's/^bind.*/bind 127.0.0.1/' /etc/redis/redis.conf && sudo systemctl restart redis" | |
| check_public 3306 "MySQL" "" | |
| check_public 5432 "PostgreSQL" "" | |
| check_public 27017 "MongoDB" "Voeg 'bindIp: 127.0.0.1' toe aan /etc/mongod.conf" | |
| # Onverwachte poorten | |
| echo "" | |
| echo "Onverwachte open poorten (mogelijke backdoors):" | |
| KNOWN_PORTS="21|22|25|53|80|443|587|3000|3306|5432|6379|8000|8080|8443|8461|9000|9090|9100|11080|11211|11443|12345|33060" | |
| UNEXPECTED=$(ss -tulpn 2>/dev/null \ | |
| | awk '{print $5}' \ | |
| | grep -oE '[0-9]+$' \ | |
| | sort -un \ | |
| | awk -v ports="$KNOWN_PORTS" \ | |
| 'BEGIN{n=split(ports,a,"|"); for(i=1;i<=n;i++) known[a[i]]=1} | |
| !known[$1] && $1 > 1024 {print $1}') | |
| if [ -n "$UNEXPECTED" ]; then | |
| while IFS= read -r port; do | |
| proc=$(ss -tulpn 2>/dev/null | grep ":$port " | grep -oP 'users:\(\("\K[^"]+' | head -1) | |
| warn "Onverwachte poort $port open (proces: ${proc:-onbekend})" | |
| done <<< "$UNEXPECTED" | |
| else | |
| ok "Geen onverwachte open poorten" | |
| fi | |
| # ------------------------------------------------------------ | |
| header "3. VERDACHTE BESTANDEN" | |
| # ------------------------------------------------------------ | |
| echo "Uitvoerbare bestanden in /tmp en /var/tmp:" | |
| EXEC_TMP=$(find /tmp /var/tmp -type f -executable 2>/dev/null \ | |
| | grep -vE "yarn|node_modules|\.cache") | |
| if [ -n "$EXEC_TMP" ]; then | |
| while IFS= read -r f; do | |
| alert "Uitvoerbaar bestand in tmp: $f" | |
| done <<< "$EXEC_TMP" | |
| else | |
| ok "Geen verdachte uitvoerbare bestanden in /tmp of /var/tmp" | |
| fi | |
| echo "" | |
| echo "Bestanden in /dev/shm:" | |
| DEV_SHM=$(find /dev/shm -type f 2>/dev/null) | |
| if [ -n "$DEV_SHM" ]; then | |
| warn "Bestanden gevonden in /dev/shm:" | |
| echo "$DEV_SHM" | |
| else | |
| ok "/dev/shm is leeg" | |
| fi | |
| echo "" | |
| echo "Recent aangemaakte bestanden in /var/tmp (laatste 7 dagen):" | |
| RECENT_VARTMP=$(find /var/tmp -type f -mtime -7 2>/dev/null | grep -vE "systemd-private") | |
| if [ -n "$RECENT_VARTMP" ]; then | |
| while IFS= read -r f; do warn "Recent bestand: $f"; done <<< "$RECENT_VARTMP" | |
| else | |
| ok "Geen recente bestanden in /var/tmp" | |
| fi | |
| # ------------------------------------------------------------ | |
| header "4. CRONTABS" | |
| # ------------------------------------------------------------ | |
| echo "Root crontab:" | |
| ROOT_CRON=$(crontab -l 2>/dev/null | grep -v "^#\|^$") | |
| if [ -n "$ROOT_CRON" ]; then | |
| warn "Root crontab heeft entries:" | |
| echo "$ROOT_CRON" | |
| else | |
| ok "Root crontab is leeg" | |
| fi | |
| echo "" | |
| echo "Gebruiker crontabs:" | |
| FOUND_CRON=0 | |
| for f in /var/spool/cron/crontabs/*; do | |
| [ -f "$f" ] || continue | |
| content=$(grep -v "^#\|^$" "$f" 2>/dev/null) | |
| if [ -n "$content" ]; then | |
| warn "Crontab voor $(basename $f):" | |
| echo "$content" | |
| FOUND_CRON=1 | |
| fi | |
| done | |
| [ $FOUND_CRON -eq 0 ] && ok "Alle gebruiker crontabs zijn leeg" | |
| echo "" | |
| echo "Recent aangepaste cron bestanden (laatste 7 dagen):" | |
| RECENT_CRON=$(find /etc/cron* /var/spool/cron -type f -newer /etc/passwd -mtime -7 2>/dev/null) | |
| if [ -n "$RECENT_CRON" ]; then | |
| while IFS= read -r f; do warn "Recent aangepast: $f"; done <<< "$RECENT_CRON" | |
| else | |
| ok "Geen recent aangepaste cron bestanden" | |
| fi | |
| # ------------------------------------------------------------ | |
| header "5. SSH AUTHORIZED KEYS" | |
| # ------------------------------------------------------------ | |
| for homedir in /root /home/*; do | |
| keyfile="$homedir/.ssh/authorized_keys" | |
| [ -f "$keyfile" ] || continue | |
| user=$(basename "$homedir") | |
| count=$(grep -c "^ssh" "$keyfile" 2>/dev/null || echo 0) | |
| info "$user: $count SSH key(s)" | |
| grep "^ssh" "$keyfile" | while IFS= read -r key; do | |
| comment=$(echo "$key" | awk '{print $NF}') | |
| echo " → $comment" | |
| done | |
| done | |
| # ------------------------------------------------------------ | |
| header "6. RECENTE LOGINS" | |
| # ------------------------------------------------------------ | |
| echo "Laatste 20 logins:" | |
| last | head -20 | |
| echo "" | |
| echo "Gefaalde loginpogingen (laatste 10):" | |
| if lastb 2>/dev/null | grep -q "[a-z]"; then | |
| lastb 2>/dev/null | head -10 | |
| else | |
| grep "Failed password" /var/log/auth.log 2>/dev/null | tail -10 \ | |
| || ok "Geen gefaalde logins gevonden" | |
| fi | |
| # ------------------------------------------------------------ | |
| header "7. SYSTEMD SERVICES" | |
| # ------------------------------------------------------------ | |
| KNOWN_SERVICES="systemd|docker|containerd|mysql|nginx|php|redis|memcach|network|cron|ssh|irq|rsyslog|snapd|multipathd|udisk|logind|polkit|dbus|udev|timesyncd|journald|packagekit|atd|fail2ban|supervisor|sendmail|getty|serial|alloy|postfix|sysstat|acpid|ModemManager|upower|flowguard|unattended|apparmor|apport|irqbalance|user@" | |
| echo "Actieve services buiten de standaard set:" | |
| UNKNOWN=$(systemctl list-units --type=service --state=running --no-pager 2>/dev/null \ | |
| | grep "\.service" \ | |
| | grep -vE "$KNOWN_SERVICES") | |
| if [ -n "$UNKNOWN" ]; then | |
| warn "Controleer deze services handmatig:" | |
| echo "$UNKNOWN" | |
| else | |
| ok "Geen onbekende actieve services" | |
| fi | |
| # ------------------------------------------------------------ | |
| header "8. UITGAANDE NETWERKVERBINDINGEN" | |
| # ------------------------------------------------------------ | |
| echo "Verbindingen naar externe IPs:" | |
| MYIPS=$(hostname -I) | |
| MYIP_PATTERN=$(echo "$MYIPS" | tr ' ' '\n' | grep -v '^$' | sed 's/\./\\./g' | paste -sd'|') | |
| EXTERNAL=$(ss -tp 2>/dev/null | grep ESTAB \ | |
| | grep -v "127\.0\.0\.1\|::1" \ | |
| | grep -vE "$MYIP_PATTERN" \ | |
| | grep -vE "nginx|php|mysql|sshd" \ | |
| | head -20) | |
| if [ -n "$EXTERNAL" ]; then | |
| echo "$EXTERNAL" | |
| else | |
| ok "Geen verdachte externe verbindingen" | |
| fi | |
| # ------------------------------------------------------------ | |
| header "SAMENVATTING" | |
| # ------------------------------------------------------------ | |
| echo "" | |
| echo "Check voltooid op $(date)." | |
| echo "" | |
| echo -e "Legenda:" | |
| echo -e " ${RED}[GEVAAR]${NC} = Direct actie vereist" | |
| echo -e " ${YELLOW}[WAARSCHUWING]${NC} = Controleer en beoordeel" | |
| echo -e " ${GREEN}[OK]${NC} = Geen probleem gevonden" | |
| echo -e " ${BLUE}[INFO]${NC} = Ter informatie" | |
| echo "" | |
| echo "Bij twijfel: isoleer de server en doe een clean rebuild." |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment