Sicherheit von JavaScript-Anwendungen: Top-10 Schwachstellen
Moderne JavaScript-Anwendungen auf Node.js verarbeiten riesige Mengen sensibler Daten, was sie zu einem attraktiven Ziel für Angreifer macht. Laut OWASP erfolgen die meisten Hacks aufgrund typischer Fehler, die vermeidbar sind. In diesem Artikel analysieren wir die 10 häufigsten Schwachstellen, zeigen reale Codebeispiele und erläutern, wie Sie Ihre Anwendung schützen können.
1. XSS (Cross-Site Scripting)
Cross-Site Scripting ist eine der ältesten, aber immer noch aktuellen Bedrohungen. Ein Angreifer injiziert ein schädliches Skript in eine Webseite, das im Browser des Opfers ausgeführt wird.
// Angreifbarer Codeapp.get('/search', (req, res) => { const query = req.query.q; res.send(`<h2>Suchergebnisse für: ${query}</h2>`);});
// Sichere Versionconst escapeHtml = (str) => { return str.replace(/&/g, '&') .replace(/</g, '<') .replace(/>/g, '>') .replace(/"/g, '"') .replace(/'/g, ''');};
app.get('/search', (req, res) => { const query = escapeHtml(req.query.q || ''); res.send(`<h2>Suchergebnisse für: ${query}</h2>`);});2. SQL Injection
SQL-Injection tritt auf, wenn Benutzereingaben direkt in eine SQL-Abfrage konkateniert werden. Dies kann zu Datenlecks oder Datenlöschung führen.
// Angreifbarer Codeconst userId = req.body.id;const query = `SELECT * FROM users WHERE id = ${userId}`;
// Sichere Version mit parametrisierten Abfragenconst userId = req.body.id;const query = 'SELECT * FROM users WHERE id = ?';db.query(query, [userId], (err, results) => { // Ergebnisverarbeitung});3. Unsichere Deserialisierung
Node.js verwendet häufig JSON.parse(), aber wenn Sie mit anderen Formaten (z.B. Buffer) arbeiten, kann ein Angreifer schädliche Daten injizieren.
// Gefährlicher Ansatzconst data = JSON.parse(req.body.data); // kann __proto__ enthalten
// Sicherer Ansatzconst safeParse = (json) => { const data = JSON.parse(json); // Gefährliche Eigenschaften rekursiv entfernen return JSON.parse(JSON.stringify(data));};4. CSRF (Cross-Site Request Forgery)
Ein Angriff, bei dem ein Angreifer einen Benutzer dazu zwingt, eine unerwünschte Aktion auf einer Website auszuführen, auf der dieser authentifiziert ist.
// Schutz mit csurf einrichtenconst csrf = require('csurf');const csrfProtection = csrf({ cookie: true });
app.post('/transfer', csrfProtection, (req, res) => { // sichere Überweisungsverarbeitung});5. Unsichere Authentifizierung
Schwache Passwörter, fehlende Begrenzung von Anmeldeversuchen und die Speicherung von Passwörtern im Klartext sind häufige Probleme.
// Korrektes Hashing von Passwörternconst bcrypt = require('bcrypt');
async function createUser(password) { const salt = await bcrypt.genSalt(12); const hash = await bcrypt.hash(password, salt); // hash in der DB speichern}
async function checkPassword(plainPassword, hash) { return await bcrypt.compare(plainPassword, hash);}6. Leck vertraulicher Daten
Das Senden des Fehler-Stacks an den Client oder das Protokollieren von Passwörtern ist ein häufiger Entwicklerfehler.
// Falschapp.use((err, req, res, next) => { res.status(500).json({ error: err.stack });});
// Richtigapp.use((err, req, res, next) => { console.error(err); // auf dem Server protokollieren res.status(500).json({ error: 'Interner Serverfehler' });});7. Unsichere Konfiguration
Verwendung von Standardports, aktivierter Debug-Modus in der Produktion und schwache CORS-Richtlinien.
// Sichere CORS-Konfigurationconst cors = require('cors');cons