Unsachgemäße Validierung des angegebenen Eingabetyps
Beschreibung
Unsachgemäße Validierung des angegebenen Eingabetyps tritt auf, wenn ein Produkt eine Eingabe erwartet, die einem bestimmten Typ entsprechen soll, aber nicht validiert oder falsch validiert, ob die Eingabe tatsächlich diesem erwarteten Typ entspricht. Wenn Eingaben nicht dem erwarteten Typ entsprechen, können Angreifer unerwartete Fehler auslösen, falsche Aktionen verursachen oder latente Schwachstellen ausnutzen. Diese Schwachstelle tritt häufig in typunsicheren Sprachen oder solchen auf, die Typumwandlung/-konvertierung unterstützen.
Risiko
Unsachgemäße Typvalidierung hat schwerwiegende Sicherheitsauswirkungen. Type-Confusion-Angriffe sind möglich. Injection-Schwachstellen können auftreten. Integer-Overflows durch Typkonvertierung. Buffer Overflows durch Größenunterschiede. Umgehung der Geschäftslogik wird ermöglicht. Anwendungsabstürze können auftreten. Datenbeschädigung ist möglich. Sicherheitskontrollen können umgangen werden.
Lösung
Verwenden Sie eine Eingabevalidierungsstrategie nach dem Prinzip "bekannt Gutes akzeptieren" mit strikten Whitelists akzeptabler Eingaben. Validieren Sie alle relevanten Eigenschaften einschließlich Länge, Typ, Wertebereiche, Syntax und Geschäftsregelkonformität. Verwenden Sie stark typisierte Sprachen oder strikte Typprüfung. Validieren und konvertieren Sie Typen explizit vor der Verwendung. Denylists können zwar Angriffe erkennen, sind aber allein unzureichend.
Häufige Auswirkungen
| Auswirkung | Details |
|---|---|
| Sonstiges | Bereich: Sonstiges Auswirkung variiert je nachdem, wie die Typvalidierungsfehler ausgenutzt werden. |
| Integrität | Bereich: Integrität Type Confusion kann zu Datenbeschädigung führen. |
| Vertraulichkeit | Bereich: Vertraulichkeit Falsche Typen können unbeabsichtigte Daten offenlegen. |
Beispielcode und Lösung
Verwundbarer Code
# VERWUNDBAR: Keine Typvalidierung in Python
def vulnerable_process_age(age):
# VERWUNDBAR: Keine Typprüfung
# Könnte String, Liste, None usw. erhalten
if age > 18: # TypeError wenn age nicht vergleichbar ist
return "Adult"
return "Minor"
def vulnerable_calculate_discount(price, quantity):
# VERWUNDBAR: Keine Typvalidierung
# price könnte String "100; DROP TABLE users" sein
# quantity könnte negativ oder nicht-numerisch sein
total = price * quantity # Unerwartetes Verhalten bei falschen Typen
return total
def vulnerable_process_user_data(data):
# VERWUNDBAR: Nimmt an, dass data ein Dict ist, ohne zu prüfen
name = data['name'] # KeyError wenn fehlend, TypeError wenn kein Dict
email = data['email'] # Gleiche Probleme
age = data['age'] # Könnte String statt Int sein
# Verarbeitung ohne Typvalidierung
return f"{name} ({age}) - {email}"
# VERWUNDBAR: SQL-Query mit unvalidierter numerischer Eingabe
def vulnerable_get_user(user_id):
# VERWUNDBAR: user_id könnte String mit Injection sein
query = f"SELECT * FROM users WHERE id = {user_id}"
return execute_query(query)
# user_id = "1 OR 1=1" würde alle Benutzer offenlegen
// VERWUNDBAR: JavaScript Type-Coercion-Probleme
// VERWUNDBAR: Keine Typvalidierung
function vulnerableCalculateTotal(price, quantity) {
// JavaScript konvertiert Typen, möglicherweise falsch
return price * quantity;
// "10" * "5" = 50 (String-zu-Number-Konvertierung)
// "10" * "abc" = NaN
// [1,2] * 3 = NaN
}
// VERWUNDBAR: Nimmt Array an ohne zu prüfen
function vulnerableProcessItems(items) {
// VERWUNDBAR: Wenn items kein Array ist, wirft forEach Fehler
items.forEach(item => {
console.log(item.name); // Nimmt auch an, dass item name-Eigenschaft hat
});
}
// VERWUNDBAR: Objekteigenschaftszugriff ohne Typprüfung
function vulnerableGetUserAge(user) {
// VERWUNDBAR: Keine Validierung des user-Objekts
return user.profile.age; // Wirft Fehler wenn user/profile null/undefined ist
}
// VERWUNDBAR: parseInt-Verhalten
function vulnerableParseUserId(idString) {
// VERWUNDBAR: parseInt hat überraschendes Verhalten
return parseInt(idString);
// parseInt("42abc") = 42 (ignoriert nachfolgende Zeichen)
// parseInt("0x10") = 16 (Hex-Parsing)
// parseInt("08") könnte in älterem JS = 0 sein (Oktal)
}
// VERWUNDBAR: C Typbehandlungsprobleme
#include <stdio.h>
#include <stdlib.h>
// VERWUNDBAR: Keine Validierung des numerischen Strings
int vulnerable_parse_int(const char* str) {
// VERWUNDBAR: atoi gibt 0 für ungültige Eingabe zurück
// Kann "0" nicht von "ungültig" unterscheiden
return atoi(str);
}
// VERWUNDBAR: Type Confusion mit void-Pointer
void vulnerable_process_data(void* data, int type) {
// VERWUNDBAR: Vertraut dem Typ-Indikator des Aufrufers
if (type == 1) {
int* int_data = (int*)data;
printf("Integer: %d\n", *int_data);
} else if (type == 2) {
char* str_data = (char*)data;
printf("String: %s\n", str_data);
}
// Wenn Typ nicht mit tatsächlichen Daten übereinstimmt, undefiniertes Verhalten
// Angreifer, der 'type' kontrolliert, kann Type Confusion verursachen
}
// VERWUNDBAR: Größentyp-Nichtübereinstimmung
void vulnerable_copy(char* dest, const char* src, int size) {
// VERWUNDBAR: 'size' ist vorzeichenbehafteter int
// Negativer size könnte Prüfungen umgehen oder große Kopie verursachen
if (size < sizeof(dest)) { // Vergleichsprobleme mit negativem Wert
memcpy(dest, src, size); // size wird zu size_t (unsigned) gecastet
}
}
Sichere Lösung
# SICHER: Ordnungsgemäße Typvalidierung in Python
from typing import Dict, Any, Union
import numbers
def secure_process_age(age: Any) -> str:
"""Alter mit Typvalidierung verarbeiten."""
# SICHER: Typ validieren
if not isinstance(age, (int, float)):
raise TypeError(f"Alter muss numerisch sein, erhalten {type(age).__name__}")
# SICHER: Es ist eine vernünftige Zahl
if not isinstance(age, numbers.Real):
raise TypeError(f"Alter muss eine reelle Zahl sein")
age_float = float(age)
# SICHER: Bereich validieren
if age_float < 0 or age_float > 150:
raise ValueError(f"Alter muss zwischen 0 und 150 sein, erhalten {age}")
if age_float >= 18:
return "Adult"
return "Minor"
def secure_calculate_discount(price: Any, quantity: Any) -> float:
"""Rabatt mit validierten Typen berechnen."""
# SICHER: Preistyp validieren
if not isinstance(price, (int, float)):
raise TypeError(f"Preis muss numerisch sein, erhalten {type(price).__name__}")
# SICHER: Mengentyp validieren
if not isinstance(quantity, int):
raise TypeError(f"Menge muss Integer sein, erhalten {type(quantity).__name__}")
# SICHER: Bereiche validieren
if price < 0:
raise ValueError("Preis darf nicht negativ sein")
if quantity < 0:
raise ValueError("Menge darf nicht negativ sein")
return float(price) * quantity
def secure_process_user_data(data: Any) -> str:
"""Benutzerdaten mit Typvalidierung verarbeiten."""
# SICHER: data ist ein Dict
if not isinstance(data, dict):
raise TypeError(f"Daten müssen Dict sein, erhalten {type(data).__name__}")
# SICHER: Erforderliche Schlüssel existieren
required_keys = ['name', 'email', 'age']
for key in required_keys:
if key not in data:
raise ValueError(f"Fehlender erforderlicher Schlüssel: {key}")
# SICHER: Typen der Werte validieren
if not isinstance(data['name'], str):
raise TypeError("Name muss String sein")
if not isinstance(data['email'], str):
raise TypeError("E-Mail muss String sein")
if not isinstance(data['age'], int):
raise TypeError("Alter muss Integer sein")
return f"{data['name']} ({data['age']}) - {data['email']}"
# SICHER: Parametrisierte Abfrage mit validierter Eingabe
def secure_get_user(user_id: Any):
"""Benutzer mit validierter ID abrufen."""
# SICHER: Typ validieren
if not isinstance(user_id, int):
raise TypeError(f"Benutzer-ID muss Integer sein, erhalten {type(user_id).__name__}")
# SICHER: Bereich validieren
if user_id < 1:
raise ValueError("Benutzer-ID muss positiv sein")
# SICHER: Parametrisierte Abfrage verwenden
query = "SELECT * FROM users WHERE id = %s"
return execute_query(query, (user_id,))
// SICHER: JavaScript mit Typvalidierung
// SICHER: Typvalidierung mit expliziten Prüfungen
function secureCalculateTotal(price, quantity) {
// SICHER: Preistyp validieren
if (typeof price !== 'number' || Number.isNaN(price)) {
throw new TypeError(`Preis muss Number sein, erhalten ${typeof price}`);
}
// SICHER: Mengentyp validieren
if (!Number.isInteger(quantity)) {
throw new TypeError(`Menge muss Integer sein, erhalten ${typeof quantity}`);
}
// SICHER: Bereiche validieren
if (price < 0) {
throw new RangeError('Preis darf nicht negativ sein');
}
if (quantity < 0) {
throw new RangeError('Menge darf nicht negativ sein');
}
return price * quantity;
}
// SICHER: Array-Validierung vor Iteration
function secureProcessItems(items) {
// SICHER: items ist Array
if (!Array.isArray(items)) {
throw new TypeError(`Items muss Array sein, erhalten ${typeof items}`);
}
items.forEach(item => {
// SICHER: Jedes Item validieren
if (typeof item !== 'object' || item === null) {
throw new TypeError('Jedes Item muss ein Objekt sein');
}
if (typeof item.name !== 'string') {
throw new TypeError('Item-Name muss String sein');
}
console.log(item.name);
});
}
// SICHER: Sicherer Eigenschaftszugriff mit Validierung
function secureGetUserAge(user) {
// SICHER: Benutzerobjekt validieren
if (typeof user !== 'object' || user === null) {
throw new TypeError('Benutzer muss ein Objekt sein');
}
if (typeof user.profile !== 'object' || user.profile === null) {
throw new TypeError('Benutzerprofil muss ein Objekt sein');
}
if (typeof user.profile.age !== 'number') {
throw new TypeError('Benutzeralter muss eine Zahl sein');
}
return user.profile.age;
}
// SICHER: Striktes Integer-Parsing
function secureParseUserId(idString) {
// SICHER: Eingabetyp validieren
if (typeof idString !== 'string') {
throw new TypeError('ID muss String sein');
}
// SICHER: Format validieren (nur Ziffern)
if (!/^\d+$/.test(idString)) {
throw new Error('Ungültiges Benutzer-ID-Format');
}
const id = parseInt(idString, 10); // SICHER: Expliziter Radix
// SICHER: Ergebnis validieren
if (Number.isNaN(id) || id < 1) {
throw new Error('Ungültige Benutzer-ID');
}
return id;
}
// SICHER: C mit ordnungsgemäßer Typvalidierung
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <limits.h>
#include <stdbool.h>
// SICHER: Validiertes Integer-Parsing
bool secure_parse_int(const char* str, int* result) {
if (str == NULL || result == NULL) {
return false;
}
// SICHER: Auf leeren String prüfen
if (*str == '\0') {
return false;
}
char* endptr;
errno = 0;
// SICHER: strtol für ordnungsgemäße Fehlererkennung verwenden
long val = strtol(str, &endptr, 10);
// SICHER: Auf Konvertierungsfehler prüfen
if (errno == ERANGE) {
return false; // Überlauf/Unterlauf
}
if (endptr == str) {
return false; // Keine Ziffern gefunden
}
if (*endptr != '\0') {
return false; // Nachfolgende Zeichen
}
// SICHER: Int-Bereich prüfen
if (val < INT_MIN || val > INT_MAX) {
return false;
}
*result = (int)val;
return true;
}
// SICHER: Typsichere Datenverarbeitung
typedef enum {
DATA_TYPE_INT = 1,
DATA_TYPE_STRING = 2
} data_type_t;
typedef struct {
data_type_t type;
union {
int int_value;
char str_value[256];
} data;
} typed_data_t;
void secure_process_data(const typed_data_t* data) {
if (data == NULL) {
return;
}
// SICHER: Typ ist Teil der Datenstruktur, kein separater Parameter
switch (data->type) {
case DATA_TYPE_INT:
printf("Integer: %d\n", data->data.int_value);
break;
case DATA_TYPE_STRING:
printf("String: %s\n", data->data.str_value);
break;
default:
fprintf(stderr, "Unbekannter Datentyp: %d\n", data->type);
break;
}
}
// SICHER: Ordnungsgemäße Größentyp-Behandlung
bool secure_copy(char* dest, size_t dest_size, const char* src, size_t copy_size) {
// SICHER: Alle Parameter werden validiert
if (dest == NULL || src == NULL) {
return false;
}
// SICHER: size_t (unsigned) für Größen verwenden
if (copy_size == 0) {
return true; // Nichts zu kopieren
}
// SICHER: Grenzprüfung
if (copy_size > dest_size) {
return false; // Würde Ziel überlaufen
}
memcpy(dest, src, copy_size);
return true;
}
CVE-Beispiele
- CVE-2024-37032: LLM-Tool hat Digest-Format nicht validiert, was Path Traversal durch Type Confusion ermöglichte.
- CVE-2008-2223: SQL Injection durch unsachgemäß validierte numerische ID - String-Eingabe wurde verwendet, wo Integer erwartet wurde.
Verwandte CWEs
- CWE-20: Unsachgemäße Eingabevalidierung (übergeordnet)
- CWE-843: Zugriff auf Ressource mit inkompatiblem Typ (Type Confusion) (verwandt)
- CWE-136: Typfehler (Kategorie)
- CWE-1215: Datenvalidierungsprobleme (Kategorie)
Referenzen
- MITRE Corporation. "CWE-1287: Improper Validation of Specified Type of Input." https://cwe.mitre.org/data/definitions/1287.html
- OWASP. "Input Validation Cheat Sheet"
- CERT. "Type Safety Guidelines"