Einleitung: Warum die Sicherheit von JavaScript-Anwendungen keine Option, sondern eine Notwendigkeit ist
JavaScript (insbesondere auf der Node.js-Plattform) ist zur dominierenden Sprache für die Erstellung sowohl von Client- als auch von Serveranwendungen geworden. Mit der wachsenden Beliebtheit steigt jedoch auch die Anzahl der Angriffe. Laut OWASP sind die meisten Hacks auf typische Fehler zurückzuführen, die vermeidbar sind. In diesem Artikel analysieren wir die Top-10-JavaScript-Schwachstellen (Node.js) mit realen Codebeispielen und Schutzmethoden. Das Material ist sowohl für Anfänger als auch für erfahrene Entwickler nützlich, die die Sicherheit ihrer Projekte stärken möchten.
1. Injection (SQL, NoSQL, Command Injection)
Injection-Angriffe bleiben die gefährlichste Kategorie von Schwachstellen. In Node.js sind häufig MongoDB und PostgreSQL betroffen.
Beispiel für anfälligen Code (NoSQL-Injection):
// Anfälliger Codeapp.post('/login', async (req, res) => { const { username, password } = req.body; const user = await db.collection('users').findOne({ username: username, password: password }); // Wenn { "username": { "$ne": null }, "password": { "$ne": null } } übergeben wird, wird der erste Benutzer zurückgegeben});So beheben Sie es:
- Verwenden Sie ORM/ODM mit Parametrisierung (Mongoose, Sequelize).
- Validieren und bereinigen Sie Eingabedaten (Bibliothek
validatoroderjoi). - Verwenden Sie für Befehle
execFileanstelle vonexec.
2. Cross-Site-Scripting (XSS)
XSS ermöglicht es einem Angreifer, ein bösartiges Skript in eine Seite einzuschleusen, die von anderen Benutzern angezeigt wird.
Beispiel für anfälligen Code (Reflected XSS):
// Anfällige Express-Routeapp.get('/search', (req, res) => { const query = req.query.q; res.send(`<h1>Suchergebnisse für: ${query}</h1>`); // Wenn ?q=<script>alert('XSS')</script> übergeben wird, wird das Skript ausgeführt});Schutz:
- Escape-Ausgabe: Verwenden Sie
res.rendermit Template-Engines (EJS, Pug) oderencodeURIComponent. - Setzen Sie den HTTP-Header
Content-Security-Policy. - Verwenden Sie auf dem Client kein
innerHTML– verwenden SietextContent.
3. Unsichere Authentifizierung und Sitzungsverwaltung
Schwache Authentifizierung ist eine der Hauptursachen für Datenlecks. Oft hardcoden Entwickler Schlüssel oder verwenden schwache Passwörter.
Typische Fehler:
- Speicherung von Passwörtern im Klartext (statt bcrypt/argon2).
- Verwendung vorhersagbarer JWT-Geheimnisse (
secret123). - Fehlende Begrenzung der Anzahl der Anmeldeversuche.
Beispiel für eine korrekte Implementierung:
const bcrypt = require('bcrypt');const saltRounds = 12;
app.post('/register', async (req, res) => { const hash = await bcrypt.hash(req.body.password, saltRounds); // Hash in der DB speichern});
app.post('/login', async (req, res) => { const user = await db.getUser(req.body.username); const match = await bcrypt.compare(req.body.password, user.passwordHash); if (match) { // JWT mit kurzer Gültigkeitsdauer erstellen const token = jwt.sign({ id: user.id }, process.env.JWT_SECRET, { expiresIn: '15m' }); res.json({ token }); }});4. SSRF (Server-Side Request Forgery)
Die SSRF-Schwachstelle ermöglicht es einem Angreifer, den Server zu zwingen, Anfragen an interne Ressourcen zu senden (z. B. an die Metadaten des Cloud-Anbieters).
Beispiel:
// Anfälliger Code: Avatar per URL herunterladenapp.post('/avatar', async (req, res) => { const { url } = req.body; const response = await fetch(url); // Es kann http://169.254.169.254/latest/meta-data/ übergeben werden // Antwort verarbeiten});Schutz:
- Erstellen Sie eine Whitelist erlaubter Domänen.
- Block