Verwendung von verbotenem Code

Beschreibung

Verwendung von verbotenem Code tritt auf, wenn ein Produkt eine Funktion, Bibliothek oder Drittanbieterkomponente verwendet, die explizit verboten wurde, sei es durch den Entwickler oder den Kunden. Organisationen können bestimmten Code aus verschiedenen Gründen verbieten: bekannte Sicherheitsschwachstellen, Schwierigkeit bei der sicheren Implementierung, Exportkontroll- oder Lizenzbeschränkungen, veralteter oder als veraltet gekennzeichneter Status oder geplante Entfernung. Das Pflegen und Durchsetzen von Listen verbotener Funktionen hilft, das Schwachstellenrisiko zu reduzieren, obwohl diese Praxis kontinuierliche Wartung und Bewusstsein erfordert.

Risiko

Die Verwendung von verbotenem Code hat erhebliche Sicherheitsauswirkungen. Bekanntermaßen verwundbare Funktionen können ausgenutzt werden. Verbotene Funktionen haben oft sicherere Alternativen. Compliance-Anforderungen können das Vermeiden bestimmten Codes vorschreiben. Veraltete Funktionen können in zukünftigen Versionen entfernt werden. Verstöße gegen Exportkontrollen können rechtliche Konsequenzen haben. Audit-Befunde können aus der Verwendung verbotenen Codes resultieren. Sicherheitszertifizierungen können gefährdet sein. Legacy-Code kann ungepatchte Schwachstellen haben.

Lösung

Pflegen Sie eine Liste verbotener Funktionen und Bibliotheken. Verwenden Sie statische Analysetools zur Erkennung von verbotenem Code. Konfigurieren Sie Compiler-Warnungen für veraltete Funktionen. Implementieren Sie Pre-Commit-Hooks zum Blockieren von verbotenem Code. Schulen Sie Entwickler zu sicheren Alternativen. Dokumentieren Sie, warum jede Funktion verboten ist. Aktualisieren Sie die Verbotsliste regelmäßig. Verwenden Sie genehmigte Bibliotheken mit aktiver Sicherheitswartung. Erwägen Sie die Verwendung sicherer Wrapper-Funktionen. Etablieren Sie einen Prozess für Ausnahmen mit Sicherheitsüberprüfung.

Häufige Auswirkungen

AuswirkungDetails
SonstigesBereich: Sonstiges

Reduzierte Wartbarkeit - Die Verwendung von verbotenem Code erschwert die Wartung und kann Probleme verursachen, wenn Code schließlich entfernt wird oder nicht mehr funktioniert.
Vertraulichkeit/Integrität/VerfügbarkeitBereich: Alle

Sicherheitsschwachstellen - Verbotene Funktionen sind oft aufgrund bekannter Sicherheitsprobleme wie Pufferüberläufen verboten.

Beispielcode

Verwundbarer Code

// Verwundbar: Verwendung verbotener C-Funktionen

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

// VERBOTEN: gets() - keine Puffergrößenbeschränkung, immer unsicher
void read_input() {
    char buffer[100];
    printf("Name eingeben: ");
    gets(buffer);  // VERBOTEN: Verwenden Sie stattdessen fgets()
    printf("Hallo, %s\n", buffer);
}

// VERBOTEN: strcpy() - keine Grenzenprüfung
void copy_string(char *dest, const char *src) {
    strcpy(dest, src);  // VERBOTEN: Verwenden Sie strncpy() oder strlcpy()
}

// VERBOTEN: strcat() - keine Grenzenprüfung
void append_string(char *dest, const char *src) {
    strcat(dest, src);  // VERBOTEN: Verwenden Sie strncat() oder strlcat()
}

// VERBOTEN: sprintf() - keine Puffergrößenbeschränkung
void format_message(char *buffer, const char *name, int id) {
    sprintf(buffer, "Benutzer: %s, ID: %d", name, id);  // VERBOTEN: Verwenden Sie snprintf()
}

// VERBOTEN: scanf() mit %s - keine Längenbeschränkung
void read_username() {
    char username[50];
    scanf("%s", username);  // VERBOTEN: Verwenden Sie fgets() oder scanf mit Breitenangabe
}

// VERBOTEN: atoi() - keine Fehlerprüfung
int parse_number(const char *str) {
    return atoi(str);  // VERBOTEN: Verwenden Sie strtol() mit Fehlerprüfung
}

// VERBOTEN: rand() für Sicherheitszwecke
void generate_token(char *token, int length) {
    for (int i = 0; i < length; i++) {
        token[i] = 'A' + (rand() % 26);  // VERBOTEN: Nicht kryptographisch sicher
    }
}
// Verwundbar: Verwendung veralteter/unsicherer Windows-APIs

#include <windows.h>

// VERBOTEN: lstrcpy() - keine Grenzenprüfung
void copy_win_string(LPTSTR dest, LPCTSTR src) {
    lstrcpy(dest, src);  // VERBOTEN: Verwenden Sie StringCchCopy()
}

// VERBOTEN: wsprintf() - keine Pufferbeschränkung
void format_win_message(LPWSTR buffer, LPCWSTR format, ...) {
    va_list args;
    va_start(args, format);
    wvsprintf(buffer, format, args);  // VERBOTEN: Verwenden Sie StringCchPrintf()
    va_end(args);
}

// VERBOTEN: GetVersion() - veraltet
void check_version() {
    DWORD version = GetVersion();  // VERBOTEN: Verwenden Sie VerifyVersionInfo() oder
                                   // Version Helper APIs
}
# Verwundbar: Verwendung verbotener Python-Funktionen/-Muster

import pickle
import yaml
import os

# VERBOTEN: pickle.loads() auf nicht vertrauenswürdigen Daten - beliebige Codeausführung
def deserialize_data(data):
    return pickle.loads(data)  # VERBOTEN: Verwenden Sie JSON oder sichere Alternativen

# VERBOTEN: yaml.load() ohne Loader - beliebige Codeausführung
def load_yaml_config(yaml_string):
    return yaml.load(yaml_string)  # VERBOTEN: Verwenden Sie yaml.safe_load()

# VERBOTEN: eval() - beliebige Codeausführung
def calculate(expression):
    return eval(expression)  # VERBOTEN: Verwenden Sie ast.literal_eval() oder sicheren Parser

# VERBOTEN: exec() mit Benutzereingabe
def run_user_code(code):
    exec(code)  # VERBOTEN: Führen Sie niemals nicht vertrauenswürdigen Code aus

# VERBOTEN: input() in Python 2 - führt Code aus (nur Python 2)
# name = input("Name: ")  # VERBOTEN in Py2: Verwenden Sie raw_input()

# VERBOTEN: shell=True mit nicht vertrauenswürdiger Eingabe
def run_command(user_command):
    os.system(user_command)  # VERBOTEN: Verwenden Sie subprocess mit shell=False
// Verwundbar: Verwendung verbotener Java-Methoden

import java.util.Random;
import java.security.MessageDigest;

public class ProhibitedExamples {

    // VERBOTEN: Math.random() für Sicherheitszwecke
    public String generateToken() {
        StringBuilder token = new StringBuilder();
        for (int i = 0; i < 32; i++) {
            token.append((char) ('A' + Math.random() * 26));
            // VERBOTEN: Verwenden Sie SecureRandom
        }
        return token.toString();
    }

    // VERBOTEN: MD5 für Passwort-Hashing
    public String hashPassword(String password) throws Exception {
        MessageDigest md = MessageDigest.getInstance("MD5");
        // VERBOTEN: MD5 ist kryptographisch gebrochen
        // Verwenden Sie bcrypt, scrypt oder Argon2
        byte[] hash = md.digest(password.getBytes());
        return bytesToHex(hash);
    }

    // VERBOTEN: SHA-1 für Sicherheitszwecke
    public String sha1Hash(String data) throws Exception {
        MessageDigest md = MessageDigest.getInstance("SHA-1");
        // VERBOTEN: SHA-1 hat bekannte Schwächen
        // Verwenden Sie SHA-256 oder besser
        return bytesToHex(md.digest(data.getBytes()));
    }

    // VERBOTEN: Runtime.exec() mit String-Befehl
    public void runCommand(String command) throws Exception {
        Runtime.getRuntime().exec(command);
        // VERBOTEN: Command-Injection-Risiko
        // Verwenden Sie ProcessBuilder mit Array von Argumenten
    }

    // VERBOTEN: java.util.Random für Sicherheit verwenden
    private Random random = new Random();

    public int generateSecurityCode() {
        return random.nextInt(1000000);
        // VERBOTEN: Verwenden Sie SecureRandom für sicherheitsrelevante Werte
    }
}

Lösung

// Behoben: Sichere Alternativen zu verbotenen Funktionen verwenden

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>

// arc4random oder /dev/urandom für kryptographische Zufallszahlen verwenden
#ifdef __linux__
#include <sys/random.h>
#endif

// Sicher: fgets() statt gets()
void read_input() {
    char buffer[100];
    printf("Name eingeben: ");
    if (fgets(buffer, sizeof(buffer), stdin) != NULL) {
        // Zeilenumbruch entfernen falls vorhanden
        buffer[strcspn(buffer, "\n")] = '\0';
        printf("Hallo, %s\n", buffer);
    }
}

// Sicher: strncpy() mit expliziter Null-Terminierung
void copy_string(char *dest, size_t dest_size, const char *src) {
    if (dest_size == 0) return;

    strncpy(dest, src, dest_size - 1);
    dest[dest_size - 1] = '\0';  // Null-Terminierung sicherstellen
}

// Sicher: strncat() mit Größenberechnung
void append_string(char *dest, size_t dest_size, const char *src) {
    size_t dest_len = strlen(dest);
    if (dest_len >= dest_size - 1) return;

    strncat(dest, src, dest_size - dest_len - 1);
}

// Sicher: snprintf() mit Puffergröße
void format_message(char *buffer, size_t buffer_size, const char *name, int id) {
    snprintf(buffer, buffer_size, "Benutzer: %s, ID: %d", name, id);
}

// Sicher: fgets() statt scanf %s
void read_username(char *username, size_t size) {
    if (fgets(username, size, stdin) != NULL) {
        username[strcspn(username, "\n")] = '\0';
    }
}

// Sicher: strtol() mit Fehlerprüfung
int parse_number(const char *str, int *error) {
    char *endptr;
    errno = 0;

    long value = strtol(str, &endptr, 10);

    if (errno != 0 || endptr == str || *endptr != '\0') {
        *error = 1;
        return 0;
    }

    if (value > INT_MAX || value < INT_MIN) {
        *error = 1;
        return 0;
    }

    *error = 0;
    return (int)value;
}

// Sicher: Kryptographisch sichere Zufallszahlen
void generate_token(char *token, int length) {
#ifdef __linux__
    unsigned char random_bytes[length];
    getrandom(random_bytes, length, 0);
    for (int i = 0; i < length; i++) {
        token[i] = 'A' + (random_bytes[i] % 26);
    }
#else
    // arc4random auf BSD/macOS verwenden
    for (int i = 0; i < length; i++) {
        token[i] = 'A' + (arc4random_uniform(26));
    }
#endif
    token[length] = '\0';
}
# Behoben: Sichere Alternativen in Python verwenden

import json
import yaml
import subprocess
import secrets
import ast
from pathlib import Path

# Sicher: JSON statt pickle für nicht vertrauenswürdige Daten
def deserialize_data(json_string):
    return json.loads(json_string)

# Sicher: yaml.safe_load() für YAML
def load_yaml_config(yaml_string):
    return yaml.safe_load(yaml_string)

# Sicher: ast.literal_eval() für sichere Literal-Auswertung
def parse_literal(expression):
    """Literal-Ausdruck sicher auswerten."""
    try:
        return ast.literal_eval(expression)
    except (ValueError, SyntaxError) as e:
        raise ValueError(f"Ungültiger Ausdruck: {e}")

# Sicher: Richtigen Parser für Berechnungen verwenden
def calculate(expression):
    """Sicheren Ausdrucks-Parser verwenden (Beispiel mit Bibliothek)."""
    # Sicheren mathematischen Ausdrucks-Parser wie 'numexpr' oder 'simpleeval' verwenden
    # Oder eigenen mit Whitelist von Operationen implementieren
    import simpleeval
    return simpleeval.simple_eval(expression)

# Sicher: subprocess mit shell=False und Argumentliste
def run_command(command, args):
    """Befehl sicher ohne Shell-Interpretation ausführen."""
    result = subprocess.run(
        [command] + args,
        shell=False,  # Niemals shell=True mit Benutzereingabe
        capture_output=True,
        text=True,
        check=True
    )
    return result.stdout

# Sicher: secrets-Modul für kryptographische Zufallszahlen
def generate_token(length=32):
    """Kryptographisch sicheres Token generieren."""
    return secrets.token_urlsafe(length)

def generate_numeric_code(digits=6):
    """Sicheren numerischen Code generieren."""
    return ''.join(str(secrets.randbelow(10)) for _ in range(digits))
// Behoben: Sichere Alternativen in Java verwenden

import java.security.SecureRandom;
import java.security.MessageDigest;
import java.util.Base64;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;

public class SafeExamples {

    private static final SecureRandom secureRandom = new SecureRandom();

    // Sicher: SecureRandom für sicherheitsrelevante Werte
    public String generateToken() {
        byte[] bytes = new byte[32];
        secureRandom.nextBytes(bytes);
        return Base64.getUrlEncoder().withoutPadding().encodeToString(bytes);
    }

    // Sicher: bcrypt/PBKDF2 für Passwort-Hashing
    public String hashPassword(String password) throws Exception {
        byte[] salt = new byte[16];
        secureRandom.nextBytes(salt);

        PBEKeySpec spec = new PBEKeySpec(
            password.toCharArray(),
            salt,
            100000,  // Iterationen
            256      // Schlüssellänge
        );

        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
        byte[] hash = factory.generateSecret(spec).getEncoded();

        // Salt und Hash zur Speicherung kombinieren
        byte[] combined = new byte[salt.length + hash.length];
        System.arraycopy(salt, 0, combined, 0, salt.length);
        System.arraycopy(hash, 0, combined, salt.length, hash.length);

        return Base64.getEncoder().encodeToString(combined);
    }

    // Sicher: SHA-256 für Integritätsprüfung
    public String sha256Hash(String data) throws Exception {
        MessageDigest md = MessageDigest.getInstance("SHA-256");
        byte[] hash = md.digest(data.getBytes("UTF-8"));
        return bytesToHex(hash);
    }

    // Sicher: ProcessBuilder mit expliziten Argumenten
    public String runCommand(String[] command) throws Exception {
        ProcessBuilder pb = new ProcessBuilder(command);
        pb.redirectErrorStream(true);

        Process process = pb.start();
        String output = new String(process.getInputStream().readAllBytes());
        int exitCode = process.waitFor();

        if (exitCode != 0) {
            throw new RuntimeException("Befehl fehlgeschlagen: " + exitCode);
        }

        return output;
    }

    // Sicher: SecureRandom für Sicherheitscodes
    public int generateSecurityCode() {
        return secureRandom.nextInt(1000000);
    }

    private static String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02x", b));
        }
        return sb.toString();
    }
}

CVE-Beispiele

Zahlreiche CVEs resultieren aus der Verwendung verbotener Funktionen. Beispiele sind:

  • Buffer Overflow-CVEs durch gets(), strcpy(), sprintf()-Verwendung
  • Beliebige Codeausführung durch pickle.loads(), eval(), yaml.load()
  • Schwache Kryptographie-CVEs durch MD5/SHA-1-Verwendung

Verwandte CWEs

  • CWE-710: Unsachgemäße Einhaltung von Codierungsstandards (übergeordnet)
  • CWE-242: Verwendung einer inhärent gefährlichen Funktion (untergeordnet)
  • CWE-676: Verwendung einer potenziell gefährlichen Funktion (untergeordnet)
  • CWE-327: Verwendung eines gebrochenen oder riskanten kryptographischen Algorithmus (verwandt)

Referenzen

  1. MITRE Corporation. "CWE-1177: Use of Prohibited Code." https://cwe.mitre.org/data/definitions/1177.html
  2. Microsoft SDL Banned Function List
  3. CERT C Coding Standard - Banned Functions
  4. OWASP - Unsafe Functions