Sicherheit von TypeScript-Anwendungen: Die Top-10 Schwachstellen in der Praxis
TypeScript ist eine Erweiterung von JavaScript, die statische Typisierung hinzufügt. Viele Entwickler gehen fälschlicherweise davon aus, dass strenge Typisierung eine Anwendung automatisch sicher macht. Das ist nicht der Fall. Der TypeScript-Compiler prüft Typen, schützt aber nicht vor logischen Fehlern, Injection-Angriffen oder Authentifizierungsproblemen. In diesem Artikel analysieren wir die 10 häufigsten Schwachstellen in TypeScript-Anwendungen, zeigen Codebeispiele und geben konkrete Empfehlungen zum Schutz. Der Artikel ist sowohl für Anfänger als auch für erfahrene Entwickler nützlich.
1. Cross-Site Scripting (XSS) durch unsachgemäße Eingabeverarbeitung
XSS bleibt eine der gefährlichsten Schwachstellen. TypeScript maskiert die Ausgabe nicht automatisch. Wenn Sie Benutzerdaten ohne Bereinigung in eine HTML-Vorlage einfügen, öffnen Sie Angriffen Tür und Tor.
Verwundbarer Code
function renderComment(comment: string): string { return `<div>${comment}</div>`;}
// Der Angreifer übergibt: <script>alert('XSS')</script>Korrigierter Code
import { escape } from 'lodash';
function renderComment(comment: string): string { const safeComment = escape(comment); return `<div>${safeComment}</div>`;}Empfehlung: Verwenden Sie immer Bibliotheken zur Maskierung (DOMPurify, lodash.escape) oder Template-Engines mit automatischer Maskierung (React JSX, Handlebars).
2. SQL-Injection durch String-Templates
TypeScript ermöglicht die Verwendung von Template-Strings zum Erstellen von SQL-Abfragen. Dies ist ein direkter Weg zur SQL-Injection, wenn Sie Benutzerdaten einsetzen.
Verwundbarer Code
async function getUser(id: string): Promise<User | null> { const query = `SELECT * FROM users WHERE id = '${id}'`; const result = await db.query(query); return result.rows[0];}Korrigierter Code
async function getUser(id: string): Promise<User | null> { const query = 'SELECT * FROM users WHERE id = $1'; const result = await db.query(query, [id]); return result.rows[0];}Empfehlung: Verwenden Sie parametrisierte Abfragen oder ORMs (TypeORM, Prisma, Sequelize). Verketten Sie niemals Strings für SQL.
3. Unsicherer Passwortvergleich
Ein Fehler bei der Implementierung des Passwortvergleichs kann zu Timing-Angriffen führen. TypeScript-Entwickler verwenden oft den Operator === zum Vergleichen von Hashes, was unsicher ist.
Verwundbarer Code
async function verifyPassword( inputPassword: string, storedHash: string): Promise<boolean> { const inputHash = await bcrypt.hash(inputPassword, 10); return inputHash === storedHash; // Schwachstelle: Timing-Angriff}Korrigierter Code
import bcrypt from 'bcrypt';
async function verifyPassword( inputPassword: string, storedHash: string): Promise<boolean> { return bcrypt.compare(inputPassword, storedHash);}Empfehlung: Verwenden Sie integrierte Vergleichsfunktionen aus Hashing-Bibliotheken (bcrypt.compare, argon2.verify). Diese sind gegen Timing-Angriffe geschützt.
4. Prototype Pollution durch rekursive Objektzusammenführung
TypeScript-Anwendungen verwenden häufig Funktionen zum tiefen Kopieren oder Zusammenführen von Objekten. Wenn die Schlüssel nicht kontrolliert werden, kann ein Angreifer den Object.prototype verunreinigen.
Verwundbarer Code
function merge(target: Record<string, any>, source: Record<string, any>) { for (const key in source) { if (typeof source[key] === 'object') { target[key] = merge(target[key] || {}, source[key]); } else { target[key] = source[key]; } } return target;}
// Der Angreifer ü