Security: Server-seitige Input-Validierung & Body-Size-Limit #67

Closed
opened 2026-05-16 22:53:36 +00:00 by jreinemann-euris · 1 comment
jreinemann-euris commented 2026-05-16 22:53:36 +00:00 (Migrated from github.com)

Problem

Analyse der Server-Routen hat fünf Sicherheits-/Stabilitätslücken aufgedeckt. Kein SQL-Injection-Risiko (Exposed ORM mit parametrisierten Queries), aber fehlende Input-Validierung kann zu DoS und unkontrollierten Server-Fehlern führen.

Findings (Priorität absteigend)

🔴 1. Kein Request-Body-Größenlimit (DoS)

Ktor hat kein \maxBodySize\ konfiguriert. Ein authentifizierter User kann ein \PUT /api/inventory\ mit beliebig großen Payloads senden → OOM auf dem VPS (1 GB RAM).

  • Fix: \install(RequestBodyLimit) { maxBodySize = 1 * 1024 * 1024 }\ in \Routing.kt\

🟠 2. Keine String-Längenvalidierung (Server-Fehler 500 statt 400)

Strings werden ohne Längenprüfung an die DB weitergegeben. Exposed wirft bei Überschreitung eine ungefangene Exception → HTTP 500.

Feld DB-Limit Geprüft?
\item.name\ varchar(255)
\item.unit\ varchar(50)
\item.id\ varchar(36)
\item.expiryDate\ varchar(10)
\category.name\ varchar(255)
\location.name\ varchar(255)
\settings.key\ varchar(255)
\username\ (Admin-Route) varchar(255) (nur isBlank())
  • Fix: Validierungsfunktion vor
    epository.saveInventory(), \patchItem()\ und \userRepository.create()\

🟠 3. \expiryDate\ Format nicht validiert

Beliebige Strings werden in das \ archar(10)-Feld gespeichert – kein Regex/Parse-Check für \YYYY-MM-DD.

  • Fix: Regex ^\d{4}-\d{2}-\d{2}$\ + \LocalDate.parse()-Validierung

🟡 4. Keine Array-Größenbeschränkung (DoS)

\PUT /api/inventory\ akzeptiert beliebig viele Items/Kategorien/Orte in einem Request.

  • Fix: Limit z. B. max. 10.000 Items, 500 Kategorien, 500 Orte

🟡 5. Settings-Keys unvalidiert

Beliebige Keys können gespeichert werden. Kein Whitelist-Check.

  • Fix: Whitelist bekannter Keys oder Längenbeschränkung

Akzeptanzkriterien

  • Ktor-Plugin: Body-Size-Limit 1 MB konfiguriert
  • \InventoryRoutes.kt: Alle String-Felder auf DB-konforme Länge geprüft, Fehler → HTTP 400
  • \InventoryRoutes.kt: \expiryDate\ per Regex validiert, Fehler → HTTP 400
  • \InventoryRoutes.kt: Array-Größen geprüft, Überschreitung → HTTP 422
  • \AdminRoutes.kt: Username-Länge validiert (max. 255)
  • Neue Tests: \InputValidationTest.kt\ mit je einem negativen Testfall pro Lücke
  • Alle bestehenden Server-Tests weiterhin grün
## Problem Analyse der Server-Routen hat fünf Sicherheits-/Stabilitätslücken aufgedeckt. Kein SQL-Injection-Risiko (Exposed ORM mit parametrisierten Queries), aber fehlende Input-Validierung kann zu DoS und unkontrollierten Server-Fehlern führen. ## Findings (Priorität absteigend) ### 🔴 1. Kein Request-Body-Größenlimit (DoS) Ktor hat kein \maxBodySize\ konfiguriert. Ein authentifizierter User kann ein \PUT /api/inventory\ mit beliebig großen Payloads senden → OOM auf dem VPS (1 GB RAM). - **Fix:** \install(RequestBodyLimit) { maxBodySize = 1 * 1024 * 1024 }\ in \Routing.kt\ ### 🟠 2. Keine String-Längenvalidierung (Server-Fehler 500 statt 400) Strings werden ohne Längenprüfung an die DB weitergegeben. Exposed wirft bei Überschreitung eine ungefangene Exception → HTTP 500. | Feld | DB-Limit | Geprüft? | |---|---|---| | \item.name\ | varchar(255) | ❌ | | \item.unit\ | varchar(50) | ❌ | | \item.id\ | varchar(36) | ❌ | | \item.expiryDate\ | varchar(10) | ❌ | | \category.name\ | varchar(255) | ❌ | | \location.name\ | varchar(255) | ❌ | | \settings.key\ | varchar(255) | ❌ | | \username\ (Admin-Route) | varchar(255) | ❌ (nur isBlank()) | - **Fix:** Validierungsfunktion vor \ epository.saveInventory()\, \patchItem()\ und \userRepository.create()\ ### 🟠 3. \expiryDate\ Format nicht validiert Beliebige Strings werden in das \ archar(10)\-Feld gespeichert – kein Regex/Parse-Check für \YYYY-MM-DD\. - **Fix:** Regex \^\\d{4}-\\d{2}-\\d{2}\$\ + \LocalDate.parse()\-Validierung ### 🟡 4. Keine Array-Größenbeschränkung (DoS) \PUT /api/inventory\ akzeptiert beliebig viele Items/Kategorien/Orte in einem Request. - **Fix:** Limit z. B. max. 10.000 Items, 500 Kategorien, 500 Orte ### 🟡 5. Settings-Keys unvalidiert Beliebige Keys können gespeichert werden. Kein Whitelist-Check. - **Fix:** Whitelist bekannter Keys oder Längenbeschränkung ## Akzeptanzkriterien - [ ] Ktor-Plugin: Body-Size-Limit 1 MB konfiguriert - [ ] \InventoryRoutes.kt\: Alle String-Felder auf DB-konforme Länge geprüft, Fehler → HTTP 400 - [ ] \InventoryRoutes.kt\: \expiryDate\ per Regex validiert, Fehler → HTTP 400 - [ ] \InventoryRoutes.kt\: Array-Größen geprüft, Überschreitung → HTTP 422 - [ ] \AdminRoutes.kt\: Username-Länge validiert (max. 255) - [ ] Neue Tests: \InputValidationTest.kt\ mit je einem negativen Testfall pro Lücke - [ ] Alle bestehenden Server-Tests weiterhin grün
jreinemann-euris commented 2026-05-16 23:20:57 +00:00 (Migrated from github.com)

Abgeschlossen (2026-05-17)

Zyklen: 1
Tests: 16 neue Tests, 532 gesamt, 0 Fehler

Implementierte Artefakte

  • Routing.kt: Content-Length-Intercept → HTTP 413, wenn Body > 1 MB
  • InventoryRoutes.kt: String-Längenvalidierung (name ≤255, unit ≤50, id ≤36, category/location ≤255, setting key ≤255), expiryDate-Regex \YYYY-MM-DD, Array-Limits (items ≤10.000, categories/locations ≤500)
  • AdminRoutes.kt: username-Länge ≤255 geprüft → HTTP 400
  • InputValidationTest.kt: 16 negative Tests (je ein Testfall pro Lücke)
## Abgeschlossen (2026-05-17) **Zyklen:** 1 **Tests:** ✅ 16 neue Tests, 532 gesamt, 0 Fehler ### Implementierte Artefakte - ✅ **Routing.kt**: Content-Length-Intercept → HTTP 413, wenn Body > 1 MB - ✅ **InventoryRoutes.kt**: String-Längenvalidierung (name ≤255, unit ≤50, id ≤36, category/location ≤255, setting key ≤255), expiryDate-Regex \YYYY-MM-DD\, Array-Limits (items ≤10.000, categories/locations ≤500) - ✅ **AdminRoutes.kt**: username-Länge ≤255 geprüft → HTTP 400 - ✅ **InputValidationTest.kt**: 16 negative Tests (je ein Testfall pro Lücke)
Sign in to join this conversation.
No description provided.