Abhängigkeit von Security through Obscurity

Beschreibung

Abhängigkeit von Security through Obscurity tritt auf, wenn eine Anwendung primär oder ausschließlich darauf angewiesen ist, Sicherheitsmechanismen geheim zu halten, anstatt auf mathematisch oder architektonisch fundierte Sicherheit zu setzen. Dies umfasst versteckte URLs, verschleierten Code, geheime Algorithmen, undokumentierte APIs und die Annahme, dass Angreifer keine Implementierungsdetails entdecken werden. Verschleierung kann gute Sicherheit ergänzen, sollte aber niemals die primäre Verteidigung sein.

Risiko

Sobald das "Geheimnis" entdeckt wird, gibt es keine Sicherheit mehr. Reverse Engineering enthüllt versteckte Funktionalität. Quellcode-Lecks legen verschleierte Mechanismen offen. Angreifer teilen entdeckte Geheimnisse weitreichend. Compliance-Anforderungen verlangen oft transparente Sicherheit. Versteckte Backdoors werden zu permanenten Schwachstellen, wenn sie entdeckt werden.

Lösung

Verwenden Sie bewährte, öffentliche Sicherheitsalgorithmen. Implementieren Sie Defense in Depth, wobei Verschleierung eine Schicht ist. Gehen Sie davon aus, dass Angreifer Ihr Systemdesign kennen (Kerckhoffs-Prinzip). Verwenden Sie ordnungsgemäße Authentifizierung und Zugriffskontrolle. Implementieren Sie Kryptografie mit gut geprüften Algorithmen. Machen Sie die Sicherheit unabhängig von Implementierungsgeheimnissen.

Häufige Auswirkungen

AuswirkungDetails
VertraulichkeitBereich: Vollständige Offenlegung

Sobald entdeckt, werden alle "geschützten" Daten offengelegt.
ZugriffskontrolleBereich: Vollständige Umgehung

Versteckte Kontrollen bieten keinen Widerstand, wenn sie gefunden werden.
IntegritätBereich: Vollständige Kompromittierung

Geheime Mechanismen leicht umgehbar.

Beispielcode und Lösung

Verwundbarer Code

// VERWUNDBAR: Versteckte Admin-URL
@RestController
public class VulnerableAdminController {

    // VERWUNDBAR: Sicherheit durch obskure URL
    @GetMapping("/xK9mN2pL/admin/users")  // "Niemand wird das erraten!"
    public List<User> getAllUsers() {
        // Keine Authentifizierung - verlässt sich auf geheime URL
        return userRepository.findAll();
    }

    // VERWUNDBAR: Verschleierter Parametername für Admin-Zugriff
    @GetMapping("/api/data")
    public Object getData(@RequestParam(required = false) String qX7zM) {
        if ("secretValue123".equals(qX7zM)) {
            // Versteckter Admin-Modus
            return adminRepository.getAllData();
        }
        return publicRepository.getData();
    }
}

// VERWUNDBAR: Eigener "Verschlüsselungs"-Algorithmus
public class VulnerableObfuscation {

    // VERWUNDBAR: Selbstgemachte "Verschlüsselung"
    public String encrypt(String data) {
        // Sicherheit hängt davon ab, dass der Algorithmus geheim ist
        StringBuilder result = new StringBuilder();
        for (char c : data.toCharArray()) {
            result.append((char)(c + 13));  // ROT13 + geheimer Offset
        }
        return Base64.encode(result.toString().getBytes());
    }

    // VERWUNDBAR: "Geheimer" Prüfsummen-Algorithmus
    public String calculateHash(String data) {
        // Eigener, unbewiesener Algorithmus
        int hash = 0;
        for (int i = 0; i < data.length(); i++) {
            hash = ((hash << 5) + hash) + data.charAt(i) * 31;
        }
        return Integer.toHexString(hash);
    }
}

// VERWUNDBAR: Versteckte Funktionalität über magische Werte
public class VulnerableMagicValues {

    public void processRequest(String action, String data) {
        // VERWUNDBAR: Geheime Aktionscodes
        if (action.equals("xYz123")) {
            // Admin-Befehl ausführen
            Runtime.getRuntime().exec(data);
        } else if (action.equals("aBc456")) {
            // Datenbank ausgeben
            dumpAllData();
        }
    }
}
# VERWUNDBAR: Versteckte API-Endpunkte
from flask import Flask, request

app = Flask(__name__)

# VERWUNDBAR: Geheimer Admin-Endpunkt
@app.route('/api/v1/internal/7f8e9d2c/admin')
def hidden_admin():
    # Keine Auth - verlässt sich darauf, dass URL geheim ist
    return get_all_admin_data()

# VERWUNDBAR: Backdoor-Parameter
@app.route('/api/login', methods=['POST'])
def login():
    username = request.form['username']
    password = request.form['password']

    # VERWUNDBAR: Versteckte Hintertür
    if username == 'support_debug_account' and password == 'internal_debug_2023':
        return {'token': create_admin_token()}

    return normal_login(username, password)

# VERWUNDBAR: Eigene Verschleierung
def obfuscate_data(data):
    # VERWUNDBAR: Sicherheit hängt von Algorithmus-Geheimhaltung ab
    key = 'secret_key_nobody_knows'
    result = ''
    for i, char in enumerate(data):
        result += chr(ord(char) ^ ord(key[i % len(key)]))
    return base64.b64encode(result.encode()).decode()

# VERWUNDBAR: Versteckter Debug-Modus
@app.route('/api/data')
def get_data():
    # VERWUNDBAR: Geheimer Parameter aktiviert Debug
    if request.args.get('_debug_mode') == 'enabled_2023':
        return {'data': get_all_data(), 'internal': get_debug_info()}
    return {'data': get_public_data()}

# VERWUNDBAR: Sicherheitstoken mit obskurem Algorithmus
def generate_token(user_id):
    # VERWUNDBAR: Vorhersagbar, sobald Algorithmus entdeckt
    timestamp = int(time.time())
    secret = f"{user_id}_{timestamp}_magic_string"
    return hashlib.md5(secret.encode()).hexdigest()
// VERWUNDBAR: Versteckte Funktionalität in JavaScript
class VulnerableApp {
    constructor() {
        // VERWUNDBAR: "Versteckte" Admin-Funktionen
        this.secretAdminKey = 'xK9mN2pL';
    }

    // VERWUNDBAR: Verschleierte Admin-Prüfung
    checkAccess(key) {
        // Client-seitige Prüfung mit "geheimem" Schlüssel
        // Leicht in Browser-DevTools zu entdecken
        if (key === this.secretAdminKey) {
            return true;  // Admin-Zugriff gewähren
        }
        return false;
    }

    // VERWUNDBAR: Versteckter API-Endpunkt
    async getSecretData() {
        // URL kann im Netzwerk-Tab gefunden werden
        const response = await fetch('/api/internal/debug/qX7zM9pL');
        return response.json();
    }

    // VERWUNDBAR: "Verschlüsselter" Speicher
    storeSecure(data) {
        // Verschleierung, keine Verschlüsselung
        const encrypted = btoa(JSON.stringify(data));  // Nur Base64!
        localStorage.setItem('secure_data', encrypted);
    }
}

// VERWUNDBAR: Versteckte Routen
const hiddenRoutes = {
    '/admin/xK9mN2pL': AdminPanel,        // "Niemand wird das finden"
    '/debug/internal/7f8e9d': DebugPanel,  // Verstecktes Debug-Panel
    '/api/backdoor/support': SupportAccess // Support-Hintertür
};

// VERWUNDBAR: Sicherheit durch verschleierten Code
function $_0x4a2b(data) {
    // Verschleierte Funktion - nach Entschleierung keine Sicherheit
    var _0x1234 = 'secret';
    return data.split('').map(c =>
        String.fromCharCode(c.charCodeAt(0) ^ _0x1234.charCodeAt(0))
    ).join('');
}
<?php
// VERWUNDBAR: Versteckte Admin-Seite
// Datei: xK9mN2pL_admin.php
// "Sicherheit" durch obskuren Dateinamen

// Keine Authentifizierung - Dateiname ist die "Sicherheit"
$users = $db->query("SELECT * FROM users");
display_admin_panel($users);

// VERWUNDBAR: Hintertür im Code
function authenticate($username, $password) {
    // VERWUNDBAR: Hartcodierte Hintertür
    if ($username === 'support' && $password === 'internal_2023_debug') {
        return create_admin_session();
    }

    return normal_auth($username, $password);
}

// VERWUNDBAR: Eigene "Verschlüsselung"
function secure_data($data) {
    // VERWUNDBAR: Selbstgemachter Algorithmus
    $key = 'super_secret_key';
    $result = '';
    for ($i = 0; $i < strlen($data); $i++) {
        $result .= chr(ord($data[$i]) ^ ord($key[$i % strlen($key)]));
    }
    return base64_encode($result);
}

// VERWUNDBAR: Versteckte Parameter
if ($_GET['debug_mode'] === 'enabled_secret_2023') {
    // Interne Daten offenlegen
    echo json_encode($db->query("SELECT * FROM internal_data"));
}

// VERWUNDBAR: Sicherheit durch Dateistandort
// Annahme, dass /includes/secret/ nicht zugänglich ist
include '/includes/secret/database_credentials.php';
?>

Sichere Lösung

// SICHER: Ordnungsgemäße Authentifizierung unabhängig von der URL
@RestController
public class SecureAdminController {

    @GetMapping("/admin/users")
    @PreAuthorize("hasRole('ADMIN')")  // Echte Zugriffskontrolle
    public List<User> getAllUsers(@AuthenticationPrincipal User user) {
        auditLog.log("Admin user list accessed by: " + user.getId());
        return userRepository.findAll();
    }

    // SICHER: Dokumentierte API mit ordnungsgemäßer Autorisierung
    @GetMapping("/api/data")
    @PreAuthorize("isAuthenticated()")
    public Object getData(@AuthenticationPrincipal User user) {
        if (user.hasRole("ADMIN")) {
            return adminRepository.getAllData();
        }
        return publicRepository.getData();
    }
}

// SICHER: Standard-kryptografische Algorithmen
public class SecureCrypto {

    // SICHER: Bewährte Verschlüsselung verwenden
    public String encrypt(String data, SecretKey key) throws Exception {
        Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
        cipher.init(Cipher.ENCRYPT_MODE, key);
        byte[] iv = cipher.getIV();
        byte[] ciphertext = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));

        // IV + Ciphertext zurückgeben
        return Base64.getEncoder().encodeToString(
            ByteBuffer.allocate(iv.length + ciphertext.length)
                .put(iv)
                .put(ciphertext)
                .array()
        );
    }

    // SICHER: Standard-Hashing
    public String calculateHash(String data) {
        return DigestUtils.sha256Hex(data);
    }
}

// SICHER: Dokumentierte Aktionen mit ordnungsgemäßer Autorisierung
public class SecureActionProcessor {

    @PreAuthorize("hasRole('ADMIN')")
    public void executeAdminCommand(User user, String command) {
        // Validierte, protokollierte, autorisierte Befehlsausführung
        if (!ALLOWED_COMMANDS.contains(command)) {
            throw new SecurityException("Command not allowed");
        }
        auditLog.log("Admin command: " + command + " by " + user.getId());
        commandExecutor.execute(command);
    }
}
# SICHER: Ordnungsgemäße Authentifizierung und Autorisierung
from flask import Flask, request
from flask_login import login_required, current_user
from functools import wraps

app = Flask(__name__)

def admin_required(f):
    @wraps(f)
    @login_required
    def decorated(*args, **kwargs):
        if not current_user.is_admin:
            abort(403)
        return f(*args, **kwargs)
    return decorated

# SICHER: Dokumentierter Admin-Endpunkt mit Auth
@app.route('/api/admin/users')
@admin_required
def admin_users():
    audit_log('Admin accessed user list', current_user.id)
    return get_all_users()

# SICHER: Keine Hintertüren, ordnungsgemäße Authentifizierung
@app.route('/api/login', methods=['POST'])
def login():
    username = request.form['username']
    password = request.form['password']

    user = User.query.filter_by(username=username).first()
    if user and user.verify_password(password):
        # Standard-Authentifizierung
        return {'token': create_token(user)}

    return {'error': 'Invalid credentials'}, 401

# SICHER: Standard-Verschlüsselung
from cryptography.fernet import Fernet

def encrypt_data(data, key):
    # Bewährte Bibliothek verwenden
    f = Fernet(key)
    return f.encrypt(data.encode()).decode()

def decrypt_data(encrypted, key):
    f = Fernet(key)
    return f.decrypt(encrypted.encode()).decode()

# SICHER: Debug-Modus durch ordnungsgemäße Autorisierung
@app.route('/api/data')
@login_required
def get_data():
    data = {'data': get_public_data()}

    # Debug-Info nur für autorisierte Admins
    if current_user.is_admin and current_user.has_permission('debug'):
        data['debug'] = get_debug_info()

    return data

# SICHER: Sichere Token-Generierung
import secrets
import jwt

def generate_token(user_id):
    # Kryptografisch sicherer Token
    return jwt.encode(
        {'user_id': user_id, 'exp': datetime.utcnow() + timedelta(hours=24)},
        app.config['SECRET_KEY'],
        algorithm='HS256'
    )
// SICHER: Ordnungsgemäße Authentifizierung in JavaScript
class SecureApp {
    constructor(authService) {
        this.authService = authService;
    }

    // SICHER: Server-seitige Autorisierung
    async checkAccess(token) {
        // Token server-seitig überprüfen, nicht client-seitig
        const response = await fetch('/api/auth/verify', {
            headers: { 'Authorization': `Bearer ${token}` }
        });
        return response.ok;
    }

    // SICHER: Dokumentierte API mit Authentifizierung
    async getData() {
        const token = this.authService.getToken();
        const response = await fetch('/api/data', {
            headers: { 'Authorization': `Bearer ${token}` }
        });

        if (!response.ok) {
            throw new AuthError('Unauthorized');
        }

        return response.json();
    }

    // SICHER: Web Crypto API verwenden
    async encryptData(data, key) {
        const encoder = new TextEncoder();
        const encodedData = encoder.encode(JSON.stringify(data));

        const iv = crypto.getRandomValues(new Uint8Array(12));
        const encrypted = await crypto.subtle.encrypt(
            { name: 'AES-GCM', iv },
            key,
            encodedData
        );

        return { iv: Array.from(iv), data: Array.from(new Uint8Array(encrypted)) };
    }
}

// SICHER: Dokumentierte Routen mit ordnungsgemäßer Auth
const routes = [
    { path: '/admin', component: AdminPanel, requiresAuth: true, requiresRole: 'admin' },
    { path: '/debug', component: DebugPanel, requiresAuth: true, requiresRole: 'developer' },
    { path: '/dashboard', component: Dashboard, requiresAuth: true }
];

// Routenwächter, der die Authentifizierung prüft
function checkRouteAccess(route, user) {
    if (route.requiresAuth && !user.isAuthenticated) {
        return false;
    }
    if (route.requiresRole && !user.hasRole(route.requiresRole)) {
        return false;
    }
    return true;
}
<?php
// SICHER: Ordnungsgemäße Authentifizierung für Admin
class SecureAdminController {
    private $authService;
    private $auditLog;

    public function __construct($authService, $auditLog) {
        $this->authService = $authService;
        $this->auditLog = $auditLog;
    }

    public function adminDashboard() {
        // Echte Authentifizierungsprüfung
        if (!$this->authService->isAdmin()) {
            http_response_code(403);
            return ['error' => 'Forbidden'];
        }

        $this->auditLog->log('Admin dashboard accessed', $_SESSION['user_id']);
        return $this->loadDashboard();
    }
}

// SICHER: Keine Hintertüren, Standard-Authentifizierung
function authenticate($username, $password) {
    $user = getUserByUsername($username);

    if (!$user) {
        return false;
    }

    // Standard-Passwortüberprüfung
    if (password_verify($password, $user['password_hash'])) {
        createSession($user);
        return true;
    }

    return false;
}

// SICHER: Standard-Verschlüsselung
function encryptData($data, $key) {
    // OpenSSL mit Standardalgorithmus verwenden
    $iv = openssl_random_pseudo_bytes(16);
    $encrypted = openssl_encrypt(
        $data,
        'AES-256-GCM',
        $key,
        OPENSSL_RAW_DATA,
        $iv,
        $tag
    );

    return base64_encode($iv . $tag . $encrypted);
}

// SICHER: Debug-Modus mit ordnungsgemäßer Autorisierung
function apiEndpoint() {
    $response = ['data' => getPublicData()];

    // Debug nur für authentifizierte Admins mit Debug-Berechtigung
    if (isAdmin() && hasPermission('debug')) {
        $response['debug'] = getDebugInfo();
    }

    return json_encode($response);
}
?>

Ausgenutzt in der Praxis

Offengelegte Admin-Panels

"Versteckte" Admin-URLs entdeckt und ausgenutzt.

Entschleierter Code

Client-seitige Sicherheit nach Entschleierung umgangen.

Geleakte Algorithmen

Eigene Verschlüsselung nach Quellcode-Leak gebrochen.


Tools zum Testen und Ausnutzen

  • URL-/Pfad-Entdeckungstools (DirBuster, gobuster).

  • JavaScript-Entschleierer.

  • API-Endpunkt-Fuzzer.


CVE-Beispiele

  • CVEs durch hartcodierte Anmeldedaten.

  • In kommerzieller Software entdeckte Hintertüren.


Referenzen

  1. MITRE. "CWE-656: Reliance on Security Through Obscurity." https://cwe.mitre.org/data/definitions/656.html

  2. Kerckhoffs-Prinzip.