Überblick — was diese Seite leistet
Sicherheitsdiagnose führt auf Ihren registrierten Servern einen Scan auf Rootkit-Spuren sowie einen Systemhärtungs-Scan aus, bewertet jedes Ergebnis mit einem Punktwert von 0 bis 100 und einer Note von A bis F und zeigt die Sicherheitslage Ihrer gesamten Flotte auf einem Bildschirm. Zu jeder Prüfung gehört eine Erläuterung nach dem Muster Was/Warum/Wie beheben, und jeder Befund, der ein Fehlschlag mit kritischem Schweregrad (fail + crit) ist, wird automatisch zu einem Fall der Problemlösung hochgestuft (dedupliziert und automatisch aufgelöst, sobald die Prüfung später besteht).
Kernbestandteile:
- Probe
infr_seccheck_probe.cjs— ein Node-Skript, das lokal und nur lesend auf dem Zielhost läuft (ohne Zugangsdaten). Es führt 36 Prüfungen aus und gibt JSON aus. - Kanonischer Katalog
App\Support\SecurityCheckbook— besitzt die 9 Kategorien, Prüfschlüssel, Gewichte und Schweregrade (sprachunabhängig, cachesicher). Die Erläuterungstexte liegen inresources/lang/{ko,en}/seccheck.php. - Engine
App\Services\Security\DiagnosticsService— Aufnahme → Bewertung → Fallhochstufung/-auflösung → Dashboard-Aggregation. - Speicher
infr_sec_scan(Migration000766) — eine Zeile = ein Host-Scan;findingswird inline als JSON abgelegt.
Wird die Probe als root ausgeführt, sind privilegierte Prüfungen wie
/etc/shadow,sudoersundsshd -Tmöglich. Ohne root werden privilegierte Prüfungen aufskipherabgestuft und aus dem Nenner des Punktwerts ausgeschlossen (keine Abwertung).
Wann Sie das nutzen
- Validierung der Härtungs-Baseline, bevor Sie einen neuen Server in die Produktion übernehmen.
- Schnelle Triage von Rootkit-/Backdoor-Spuren auf einem verdächtigen Host (versteckte Prozesse, Injektion über
ld.so.preload, NIC im Promiscuous-Modus usw.). - Ein wiederkehrender Compliance-Rhythmus — eine tägliche Cron-Probe, die die Punktwerte über den API-Reporter sendet und so automatisch einen Trend aufbaut.
- Auditbereitschaft — auf einen Blick sehen, welche Hosts ein Betriebssystem ohne Support (EOL) fahren, nicht eingespielte Sicherheitsupdates haben oder die SSH-Anmeldung als root zulassen.
Aufbau
| Bereich | Inhalt |
|---|---|
| KPI-Leiste | Durchschnittspunktwert der Flotte · Anzahl gescannter Hosts · offene kritische Fälle · Gesamtzahl fehlgeschlagener Prüfungen · Zeitpunkt des letzten Scans |
| Notenverteilung | Histogramm der Host-Anzahl je Note A/B/C/D/F |
| Kategoriewerte | Zusammenfassung der 9 Kategorien (Flottendurchschnitt, Katalogreihenfolge, Tonfarbe) |
| Punktwert-Verlauf | Die letzten 60 Scans in chronologischer Reihenfolge |
| Hosts nach Note | Raster aus Host-Karten — zuerst der niedrigste (riskanteste) Punktwert. Jede Karte zeigt Note, die Zähler pass/warn/fail/crit, die Eingangsquelle und die Scan-Zeit. Klick → Berichts-Dialog |
| Berichts-Dialog | Gesamtpunktwert/-note + Zusammenfassung (OS/Kernel) + Details je Prüfung (Was/Warum/Behebung/Nachweis) + Link zum hochgestuften Fall |
Obere Werkzeugleiste: [Scan starten] (Remote-Lauf über mehrere Server) · [Ergebnis einfügen] · Aktualisieren · Schalter für automatische Aktualisierung · Vollbild.
Verwendung
Vier Eingangswege
infr_sec_scan.source klassifiziert, wie ein Scan entgegengenommen wurde:
| source | Einstiegspunkt | Methode |
|---|---|---|
emulate |
Dialog [Scan starten] | Instanzen auswählen → Probe entfernt ausbringen und ausführen. Ein Einfügen bzw. eine Remote-Emulate-Übernahme mit instance_id wird ebenfalls als emulate erfasst |
paste |
Dialog [Ergebnis einfügen] | Fügen Sie das direkt auf dem Ziel erzeugte Probe-JSON ein, ohne Bindung an eine Instanz |
api |
POST /api/v1/security/scan |
Der Cron jedes Hosts führt die Probe aus → sendet sie über einen API-Schlüssel (der Weg des Reporters) |
manual |
Rückfallebene | Standard, wenn der Wert von source nicht gültig ist |
1) Remote-Lauf über mehrere Server — asynchrones Polling
Ein synchroner Komplettlauf würde über viele Hosts hinweg die Ausführungszeit von PHP überschreiten, daher lautet der Ablauf registrieren → Worker starten und nicht warten → pollen.
- [Scan starten] → die Zielinstanzen ankreuzen (jede zeigt erreichbar / nicht erreichbar).
POST /security/diagnostics/run→ legt einen Fortschrittseintrag an und liefertrun_idsofort zurück (Cache, TTL 30 Min.).- Das Frontend ruft
POST /security/diagnostics/run-worker/{runId}ohne zu warten auf → der Worker arbeitet alle Hosts nacheinander unterset_time_limit(0)undignore_user_abortab (ein fehlschlagender Host stoppt die übrigen nicht). - Das Frontend pollt
GET /security/diagnostics/run-status/{runId}, um den Fortschritt zu aktualisieren (done/total/ok).
Eine als nicht erreichbar markierte Instanz passt zu keinem Knoten des
run_report-Collectors und kann deshalb nicht entfernt ausgeführt werden. Führen Sie die Probe direkt auf dem Host aus und übermitteln Sie sie über [Ergebnis einfügen]. Zur Verdrahtung des Remote-Laufs siehe Remote Emulate.
2) Einfügen / JSON-Aufnahme
Führen Sie die Probe auf dem Zielhost aus und fügen Sie ihr JSON ein.
# Auf dem Zielhost (empfohlen: root)
node infr_seccheck_probe.cjs --min
--min gibt einzeiliges JSON aus. Form der Ausgabe:
{
"host": "web-01",
"generated_at": "2026-08-13T03:30:00Z",
"os": "Rocky Linux 9.3",
"kernel": "5.14.0-362.el9",
"root": true,
"checks": [
{ "key": "ssh_root_login", "category": "ssh", "status": "fail", "severity": "crit", "detail": "PermitRootLogin yes", "evidence": "/etc/ssh/sshd_config:32" },
{ "key": "svc_firewall", "category": "services", "status": "pass", "severity": "crit", "detail": "firewalld active" }
],
"summary": {}
}
Entgegengenommen wird es von POST /security/diagnostics/ingest. Eine Instanzbindung wird als source=emulate erfasst; ohne Bindung wird source=paste erfasst.
3) API-Reporter (Automatisierung)
Der Cron jedes Hosts führt die Probe aus und schickt das Ergebnis an InfraGuard. Den API-Schlüssel geben Sie unter Verwaltung ▸ API-Schlüssel aus; der Schlüssel muss den Scope scan.write tragen.
30 3 * * * node /opt/infr/infr_seccheck_probe.cjs --min | curl -sS -X POST https://infraguard.example.com/api/v1/security/scan -H "Authorization: Bearer YOUR_API_KEY" -H "Content-Type: application/json" --data @-
Antwort (201):
{ "ok": true, "scan_id": 812, "host": "web-01", "score": 74, "grade": "C" }
Bewertung — SecurityCheckbook
Der Punktwert ist ein gewichtetes Verhältnis aus Gewicht und Status jeder Prüfung.
Statusfaktor (STATUS_FACTOR) — nur diese zählen; skip/info werden aus dem Nenner ausgeschlossen:
| Status | Faktor |
|---|---|
pass |
1.0 |
warn |
0.6 |
fail |
0.0 |
skip · info |
ausgeschlossen |
Schweregrad-Multiplikator (SEV_MUL) — je schwerer die Folgen eines Fehlschlags wiegen, desto stärker verschiebt er den Punktwert:
| fail_severity | Multiplikator |
|---|---|
crit |
1.6 |
warn |
1.0 |
info |
0.5 |
Gewicht je Prüfung w = check_weight(1–3) × severity_multiplier; Gesamtpunktwert = round(100 × Σ(w × status_factor) / Σw). Die Kategoriewerte verwenden dieselbe Formel je Kategorie.
Note und Ton:
| Punktwert | Note | Ton |
|---|---|---|
| ≥ 90 | A | good |
| ≥ 80 | B | good |
| ≥ 70 | C | warn |
| ≥ 60 | D | warn |
| < 60 | F | crit |
(Die Noten sind A/B/C/D/F; der Ton ist good ≥ 80 · warn ≥ 60 · crit < 60.)
9 Kategorien · 36 Prüfungen
Jede Kategorie hat ein Anzeigegewicht und ein Symbol; die eigentliche Bewertung nutzt das oben beschriebene Gewicht je Prüfung × Schweregrad-Multiplikator.
| Kategorie | Bezeichnung | Prüfungen | Bemerkenswerte Prüfungen (Bedeutung im Fehlerfall) |
|---|---|---|---|
rootkit |
Rootkit / Schadsoftware | 6 | rk_known_files·rk_ld_preload·rk_hidden_proc (crit) |
patch |
Patches / Updates | 3 | pt_security_updates·pt_eol_os (crit) |
ssh |
SSH-Konfiguration | 5 | ssh_root_login·ssh_empty_pass (crit) |
accounts |
Konten / Berechtigungen | 5 | acc_uid0·acc_empty_pass (crit) |
network |
Netzwerk-Exposition | 3 | net_legacy_services·net_db_exposed (crit) |
filesystem |
Dateisystemrechte | 5 | fs_shadow_perm (crit)·fs_world_writable·fs_suid (warn) |
hardening |
Systemhärtung | 5 | hd_selinux·hd_aslr·hd_syncookies (warn) |
services |
Dienste / Firewall | 2 | svc_firewall (crit)·svc_unnecessary (info) |
logging |
Audit / Protokollierung | 2 | log_auditd·log_syslog (warn) |
Unbekannte Schlüssel werden in der Kategorie other aufgefangen. Der Text „Was / Warum / Behebung“ jeder Prüfung wird im Berichts-Dialog aus seccheck.check.* gerendert.
Kritische Befunde → Hochstufung zur Problemlösung
Bei jeder Aufnahme gleicht reconcileCases() die Fälle des Hosts ab.
- Hochgestuft werden nur Befunde mit
status = failUNDseverity = crit. Deduplizierungsschlüssel: ein internerfingerprint. - Existiert bereits ein offener Fall, erhöht er
occurrence_count++undlast_occurred_at; andernfalls legt er einen neuen Fall an:infr_incident(area=security,source=detection,entity_type=seccheck,entity_key=host,severity=crit,status=open) sowie eininfr_incident_event(kind=created). - Automatische Auflösung: Ein zuvor offener Fall, der in diesem Scan nicht mehr fail+crit ist (behoben oder nicht mehr erkannt), wird auf
status=resolvedmitresolved_atund einem Hinweis zur automatischen Auflösung gesetzt.
Hochgestufte Prüfungen erscheinen im Berichts-Dialog mit dem Abzeichen „zur Problemlösung hochgestuft“ und einem Link [Fall anzeigen]. Bearbeitet werden die Fälle auf dem Board Sicherheit ▸ Problemlösung.
Das Löschen eines Scans (
POST /security/diagnostics/delete) löscht die daraus hochgestuften Fälle nicht — beide sind unabhängig voneinander.
Datenquellen
| Quelle | Rolle |
|---|---|
infr_sec_scan (000766) |
Scan-Ergebnisse (eines pro Host). JSON aus score·grade·pass/warn/fail/crit/total_count·category_scores·summary·findings. Indizes (host,scanned_at)·(instance_id,scanned_at)·grade·score |
infr_instance |
Zielinstanzen (löst host → instance_id über alias/hostname auf) |
infr_incident / infr_incident_event |
Hochgestufte kritische Fälle und deren Zeitleiste |
infr_api_key |
Authentifizierung des API-Reporters (Scope scan.write) |
| Cache | Dashboard-Aggregat 20 s zwischengespeichert (infr:sec:diag:build) · Fortschrittseintrag des asynchronen Laufs (TTL 1800 s) |
infr_seccheck_probe.cjs |
Die Quell-Probe (lokal, nur lesend) |
- Aggregationsdisziplin: Innerhalb der 500 jüngsten Scans nur den jeweils neuesten je Host behalten (Deduplizierung) → Flottenliste, Durchschnitt, Kategoriezusammenfassung, Verlauf, Anzahl offener kritischer Fälle.
- Kategorie und Schweregrad der Probe sind lediglich Hinweise; der Server normalisiert sie über
SecurityCheckbookerneut auf die kanonischen Werte.
Zugriff
- Lesen: erfordert Zugriff auf den Rollenbereich Sicherheit (in der aktuellen Stufung staff = 5 / admin = 10; demo = 1 sieht den Bereich Sicherheit nicht). Erlaubt die Ansicht von Dashboard und Berichten.
- Schreiben (Ausführen / Aufnehmen / Löschen): erfordert
infr_user_level >= 2in der Sitzung (canWrite()). Darunter liefernrun·ingest·deleteeine 403 (seccheck.toast.forbidden). - API-Reporter: die Middleware
infr.apikeysowie ein Schlüssel mit dem Scopescan.write; andernfalls 403forbidden_scope. - Audit: Jeder Schreibvorgang wird in
infr_audit_logfestgehalten —sec.diag_run(Anzahl der Ziele),sec.diag_ingest(scan_id·score·source),sec.diag_delete(id des Scans). Prüfen Sie das im Audit-Protokoll.
Zum Ebenenmodell allgemein (Middleware infr.level:N) siehe RBAC-Ebenen.
Fehlerbehebung und FAQ
Q. Eine Instanz erscheint in [Scan starten] als „nicht erreichbar“.
Sie passt zu keinem Knoten des run_report-Collectors, es gibt also keine Verdrahtung für den Remote-Lauf. Führen Sie die Probe direkt auf dem Host aus und übermitteln Sie sie über [Ergebnis einfügen].
Q. Fehler „No checks found“.
Das eingefügte JSON enthält kein Array checks (oder items), oder den Einträgen fehlt ein key. Fügen Sie die Ausgabe von infr_seccheck_probe.cjs --min unverändert ein.
Q. Der Punktwert ist niedrig, obwohl es nur wenige Fehlschläge gibt.
Das ist der Schweregrad-Multiplikator. Ein crit-Fehlschlag wiegt das 1,6-Fache eines warn. Nutzen Sie die Kategoriewerte und den Berichts-Dialog, um zu sehen, welcher Befund den Punktwert nach unten zieht.
Q. Alle privilegierten Prüfungen stehen auf skip.
Die Probe lief unter einem Konto ohne root-Rechte. Prüfungen wie /etc/shadow, sudoers oder sshd -T benötigen root. skip ist vom Nenner ausgenommen (keine Abwertung), führen Sie sie für eine vollständige Diagnose aber als root (oder über das Gateway) aus.
Q. Ein Lauf dauert eine Weile — kann ich den Browser schließen?
Ja. Der Worker läuft nach dem Start ohne Warten weiter und arbeitet unter ignore_user_abort selbst dann, wenn die Anfrage abbricht. Öffnen Sie die Seite erneut und pollen Sie run-status, oder lesen Sie die Noten einfach, sobald sie im Dashboard erscheinen. Der Fortschrittseintrag bleibt 30 Minuten erhalten.
Q. Ein Fall ist von selbst verschwunden. Meldet ein späterer Scan diesen Befund nicht mehr als fail+crit (behoben oder nicht erkannt), löst die Engine den Fall automatisch auf. Das ist so vorgesehen.
Verwandte Themen
- Sicherheit ▸ Problemlösung — Arbeitsablauf für hochgestufte kritische Fälle
- Remote Emulate — Ausbringung der Probe auf mehrere Server und Verdrahtung des Laufs
- API-Schlüssel — Schlüssel für den Reporter-Weg (Scope
scan.write) - Assets ▸ Instanzen — das Register der Ziel-Betriebssysteminstanzen
- Sicherheit ▸ Übersicht — die vollständige Erzählung des Abwehrtrichters
- Audit-Protokoll — Verlauf von Ausführung / Aufnahme / Löschung
