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
| Auswirkung | Details |
|---|---|
| Vertraulichkeit | Bereich: Vollständige Offenlegung Sobald entdeckt, werden alle "geschützten" Daten offengelegt. |
| Zugriffskontrolle | Bereich: Vollständige Umgehung Versteckte Kontrollen bieten keinen Widerstand, wenn sie gefunden werden. |
| Integrität | Bereich: 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
-
MITRE. "CWE-656: Reliance on Security Through Obscurity." https://cwe.mitre.org/data/definitions/656.html
-
Kerckhoffs-Prinzip.