Authentifizierungsumgehung über alternativen Pfad oder Kanal
Beschreibung
Authentifizierungsumgehung über alternativen Pfad oder Kanal tritt auf, wenn ein System, das Authentifizierung erfordert, über einen alternativen Einstiegspunkt umgangen werden kann, der nicht dieselben Authentifizierungsanforderungen durchsetzt. Dies umfasst direkten Zugriff auf Backend-APIs, Verwendung von Legacy-Endpunkten, Ausnutzung von Mobile-App-APIs, Zugriff auf administrative Schnittstellen über verschiedene Ports oder Verwendung alternativer Protokolle, die Authentifizierungskontrollen umgehen.
Risiko
Alternative Pfad-Umgehungen umgehen Authentifizierungskontrollen vollständig und geben Angreifern denselben Zugang wie authentifizierten Benutzern. Dies ist besonders häufig in modernen Multi-Interface-Anwendungen, bei denen Web-, Mobile- und API-Schnittstellen inkonsistente Sicherheit haben können. Legacy-Endpunkte, die für Abwärtskompatibilität beibehalten werden, haben oft keine modernen Sicherheitskontrollen. Interne APIs, von denen angenommen wird, dass sie vom Internet nicht zugänglich sind, können exponiert sein. Das Risiko erstreckt sich auf jedes System mit mehreren Einstiegspunkten – das schwächste Glied bestimmt die Gesamtsicherheit.
Lösung
Wenden Sie konsistente Authentifizierung über alle Schnittstellen und Einstiegspunkte an. Implementieren Sie Authentifizierung auf der API/Service-Ebene statt nur auf der Präsentationsebene. Entfernen oder sichern Sie Legacy-Endpunkte ordnungsgemäß. Verwenden Sie API-Gateways, um konsistente Authentifizierungsrichtlinien durchzusetzen. Prüfen Sie alle netzwerkzugänglichen Schnittstellen auf Authentifizierungsanforderungen. Implementieren Sie Netzwerksegmentierung für nur interne Dienste. Wenden Sie Defense in Depth an – verlassen Sie sich nicht allein auf Netzwerkisolierung. Regelmäßige Sicherheitstests sollten die Enumeration alternativer Pfade einschließen.
Häufige Auswirkungen
| Auswirkung | Details |
|---|---|
| Zugriffskontrolle | Bereich: Authentifizierungsumgehung Angreifer greifen ohne Authentifizierung auf geschützte Ressourcen zu. |
| Vertraulichkeit | Bereich: Datenoffenlegung Sensible Daten über ungeschützte alternative Pfade zugänglich. |
| Integrität | Bereich: Unbefugte Modifikation Angreifer können Daten über umgangene Schnittstellen modifizieren. |
Beispielcode + Korrigierter Code
Anfälliger Code
# ANFÄLLIG: Web-Interface gesichert, aber API nicht
from flask import Flask, request, session, jsonify
# Web-Interface - erfordert Authentifizierung
@app.route('/dashboard')
def dashboard():
if 'user_id' not in session:
return redirect('/login')
return render_template('dashboard.html')
# API-Endpunkt - KEINE AUTHENTIFIZIERUNG!
@app.route('/api/v1/users')
def api_get_users():
# Angreifer kann direkt zugreifen!
return jsonify([u.to_dict() for u in User.query.all()])
@app.route('/api/v1/data')
def api_get_data():
# Keine Auth-Prüfung auf API!
return jsonify(get_sensitive_data())
# ANFÄLLIG: Legacy-Endpunkt noch erreichbar
@app.route('/legacy/admin')
def legacy_admin():
# Alte Admin-Schnittstelle ohne moderne Auth!
return render_template('legacy_admin.html')
# ANFÄLLIG: Interner Dienst ohne Auth exponiert
@app.route('/internal/metrics')
def internal_metrics():
# Angenommen nur intern, aber tatsächlich erreichbar!
return jsonify(get_system_metrics())
# ANFÄLLIG: Unterschiedliche Auth für verschiedene Ports
# Haupt-App auf Port 443 erfordert Auth
# Admin-Interface auf Port 8080 hat schwache Auth
// ANFÄLLIG: Web gesichert, REST API nicht
@Controller
public class WebController {
// Web-Interface - Spring Security konfiguriert
@GetMapping("/dashboard")
public String dashboard() {
// Durch Spring Security Konfiguration gesichert
return "dashboard";
}
}
@RestController
@RequestMapping("/api/v1")
public class ApiController {
// API umgeht Web-Sicherheit!
// Spring Security nur für Web-Pfade konfiguriert
@GetMapping("/users")
public List<User> getUsers() {
// Keine Authentifizierung!
return userService.getAllUsers();
}
@PostMapping("/admin/action")
public ResponseEntity<String> adminAction(@RequestBody ActionRequest request) {
// Admin-Aktion ohne Auth!
return ResponseEntity.ok(performAction(request));
}
}
// ANFÄLLIG: Spring Security Fehlkonfiguration
@Configuration
@EnableWebSecurity
public class VulnerableSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/dashboard/**").authenticated()
// /api/** nicht konfiguriert - Standard erlaubt alles!
);
return http.build();
}
}
// ANFÄLLIG: Actuator-Endpunkte exponiert
// application.properties
// management.endpoints.web.exposure.include=*
// Keine Authentifizierung auf Actuator!
// ANFÄLLIG: Express mit inkonsistenter Authentifizierung
const express = require('express');
const app = express();
// Web-Routen - Authentifizierungs-Middleware angewandt
app.use('/web', requireAuth);
app.get('/web/dashboard', (req, res) => {
res.render('dashboard');
});
// API-Routen - KEINE Authentifizierungs-Middleware!
app.get('/api/users', (req, res) => {
// Ohne Auth zugänglich!
User.find({}).then(users => res.json(users));
});
app.get('/api/admin/config', (req, res) => {
// Admin-Konfiguration exponiert!
res.json(getConfig());
});
// ANFÄLLIG: GraphQL umgeht REST-Auth
const graphqlSchema = `
type Query {
users: [User]
adminData: AdminData
}
`;
// GraphQL-Endpunkt hat keine Auth!
app.use('/graphql', graphqlHTTP({
schema: schema,
graphiql: true // Exponiert auch GraphiQL-Interface!
}));
// ANFÄLLIG: WebSocket ohne Auth
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
wss.on('connection', (ws) => {
// Keine Authentifizierung auf WebSocket!
ws.on('message', (message) => {
handleMessage(JSON.parse(message));
});
});
// ANFÄLLIG: Mobile API mit schwächerer Auth
app.post('/mobile/login', (req, res) => {
// Mobile API akzeptiert schwächere Anmeldedaten
if (req.body.device_id) { // Nur Geräte-ID!
res.json({ token: generateToken() });
}
});
Korrigierter Code
# SICHER: Konsistente Authentifizierung über alle Pfade
from flask import Flask, request, session, jsonify
from functools import wraps
app = Flask(__name__)
# Zentraler Authentifizierungs-Decorator
def require_auth(f):
@wraps(f)
def decorated(*args, **kwargs):
# Session für Web-Anfragen prüfen
if 'user_id' in session:
return f(*args, **kwargs)
# API-Token für API-Anfragen prüfen
auth_header = request.headers.get('Authorization')
if auth_header and auth_header.startswith('Bearer '):
token = auth_header.split(' ')[1]
user = verify_api_token(token)
if user:
request.current_user = user
return f(*args, **kwargs)
return jsonify({'error': 'Authentifizierung erforderlich'}), 401
return decorated
# Standardmäßig auf ALLE Routen anwenden
@app.before_request
def check_authentication():
# Whitelist öffentlicher Endpunkte
public_endpoints = {'login', 'register', 'health', 'static'}
if request.endpoint and request.endpoint not in public_endpoints:
# Authentifizierung prüfen
if not is_authenticated():
return jsonify({'error': 'Authentifizierung erforderlich'}), 401
# SICHER: Sowohl Web als auch API erfordern Authentifizierung
@app.route('/dashboard')
@require_auth
def dashboard():
return render_template('dashboard.html')
@app.route('/api/v1/users')
@require_auth
def api_get_users():
return jsonify([u.to_dict() for u in User.query.all()])
@app.route('/api/v1/data')
@require_auth
def api_get_data():
return jsonify(get_sensitive_data())
# SICHER: Legacy-Endpunkte entfernen oder sichern
# @app.route('/legacy/admin') - ENTFERNT
# SICHER: Interne Dienste nicht exponiert oder ordnungsgemäß gesichert
# Interne Metriken auf separatem internen Port bereitgestellt
# Oder mit derselben Authentifizierung gesichert
@app.route('/internal/metrics')
@require_auth
@require_role('admin')
def internal_metrics():
return jsonify(get_system_metrics())
# SICHER: API-Gateway-Muster
class APIGateway:
"""Zentrale Authentifizierung für alle Dienste."""
def __init__(self):
self.routes = {}
def register(self, path, handler, auth_required=True):
self.routes[path] = {
'handler': handler,
'auth_required': auth_required
}
def handle_request(self, path, request):
route = self.routes.get(path)
if not route:
return {'error': 'Nicht gefunden'}, 404
if route['auth_required']:
if not self.authenticate(request):
return {'error': 'Authentifizierung erforderlich'}, 401
return route['handler'](request)
// SICHER: Konsistente Spring Security für alle Pfade
@Configuration
@EnableWebSecurity
public class SecureSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
// Auf ALLE Pfade anwenden
.authorizeHttpRequests(auth -> auth
// Öffentliche Endpunkte explizit whitelisten
.requestMatchers("/login", "/register", "/health").permitAll()
// Alles andere erfordert Authentifizierung
.anyRequest().authenticated()
)
// REST API Authentifizierung
.oauth2ResourceServer(oauth2 -> oauth2.jwt())
// Sitzungsauthentifizierung für Web
.formLogin(form -> form.loginPage("/login"));
return http.build();
}
}
// SICHER: Alle Controller erfordern standardmäßig Authentifizierung
@RestController
@RequestMapping("/api/v1")
public class SecureApiController {
@GetMapping("/users")
@PreAuthorize("isAuthenticated()")
public List<User> getUsers() {
return userService.getAllUsers();
}
@PostMapping("/admin/action")
@PreAuthorize("hasRole('ADMIN')")
public ResponseEntity<String> adminAction(@RequestBody ActionRequest request) {
return ResponseEntity.ok(performAction(request));
}
}
// SICHER: Sichere Actuator-Endpunkte
// application.properties
// management.endpoints.web.exposure.include=health,info
// management.endpoint.health.show-details=when_authorized
// management.endpoints.web.base-path=/actuator
// spring.security.user.name=admin
// spring.security.user.password=${ACTUATOR_PASSWORD}
@Configuration
public class ActuatorSecurityConfig {
@Bean
public SecurityFilterChain actuatorFilterChain(HttpSecurity http) throws Exception {
http
.securityMatcher(EndpointRequest.toAnyEndpoint())
.authorizeHttpRequests(auth -> auth
.requestMatchers(EndpointRequest.to("health", "info")).permitAll()
.anyRequest().hasRole("ACTUATOR_ADMIN")
)
.httpBasic(Customizer.withDefaults());
return http.build();
}
}
// SICHER: WebSocket mit Authentifizierung
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void configureClientInboundChannel(ChannelRegistration registration) {
registration.interceptors(new AuthChannelInterceptor());
}
}
public class AuthChannelInterceptor implements ChannelInterceptor {
@Override
public Message<?> preSend(Message<?> message, MessageChannel channel) {
StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message);
if (StompCommand.CONNECT.equals(accessor.getCommand())) {
String token = accessor.getFirstNativeHeader("Authorization");
if (!validateToken(token)) {
throw new AccessDeniedException("Ungültiges Token");
}
}
return message;
}
}
// SICHER: Konsistente Authentifizierung über alle Pfade
const express = require('express');
const app = express();
// Zentrale Authentifizierungs-Middleware
const requireAuth = async (req, res, next) => {
// Session prüfen
if (req.session?.userId) {
req.user = await User.findById(req.session.userId);
return next();
}
// Bearer-Token prüfen
const authHeader = req.headers.authorization;
if (authHeader?.startsWith('Bearer ')) {
const token = authHeader.slice(7);
try {
const decoded = jwt.verify(token, process.env.JWT_SECRET);
req.user = await User.findById(decoded.userId);
return next();
} catch (err) {
// Ungültiges Token
}
}
return res.status(401).json({ error: 'Authentifizierung erforderlich' });
};
// Authentifizierung auf ALLE Routen außer Whitelist anwenden
const publicPaths = ['/login', '/register', '/health'];
app.use((req, res, next) => {
if (publicPaths.includes(req.path)) {
return next();
}
return requireAuth(req, res, next);
});
// SICHER: Alle Routen erfordern jetzt Authentifizierung
app.get('/web/dashboard', (req, res) => {
res.render('dashboard');
});
app.get('/api/users', (req, res) => {
User.find({}).then(users => res.json(users));
});
app.get('/api/admin/config', requireRole('admin'), (req, res) => {
res.json(getConfig());
});
// SICHER: GraphQL mit Authentifizierung
const { ApolloServer } = require('apollo-server-express');
const server = new ApolloServer({
schema,
context: async ({ req }) => {
// Benutzer aus Anfrage extrahieren (bereits durch Middleware authentifiziert)
if (!req.user) {
throw new AuthenticationError('Nicht authentifiziert');
}
return { user: req.user };
},
introspection: process.env.NODE_ENV !== 'production' // In Produktion deaktivieren
});
// SICHER: WebSocket mit Authentifizierung
const WebSocket = require('ws');
const wss = new WebSocket.Server({
port: 8080,
verifyClient: async (info, callback) => {
// Token aus Query-String oder Headers verifizieren
const token = new URL(info.req.url, 'ws://localhost').searchParams.get('token');
if (!token) {
callback(false, 401, 'Authentifizierung erforderlich');
return;
}
try {
const decoded = jwt.verify(token, process.env.JWT_SECRET);
info.req.user = await User.findById(decoded.userId);
callback(true);
} catch (err) {
callback(false, 401, 'Ungültiges Token');
}
}
});
// SICHER: Mobile API mit denselben Authentifizierungsstandards
app.post('/mobile/login', async (req, res) => {
const { username, password } = req.body;
// Dieselbe Authentifizierung wie Web!
const user = await authenticate(username, password);
if (!user) {
return res.status(401).json({ error: 'Ungültige Anmeldedaten' });
}
const token = jwt.sign({ userId: user._id }, process.env.JWT_SECRET, {
expiresIn: '15m'
});
res.json({ token });
});
Ausgenutzt in der Praxis
API-Endpunkt-Umgehungen
Zahlreiche Breaches traten auf, als Angreifer unauthentifizierte API-Endpunkte hinter authentifizierten Web-Interfaces entdeckten.
Spring Boot Actuator-Exposition
Exponierte Actuator-Endpunkte haben Angreifern ermöglicht, auf Umgebungsvariablen, Heap-Dumps und andere sensible Informationen zuzugreifen.
Mobile API-Exploits
Mobile Apps mit schwächerer API-Authentifizierung wurden ausgenutzt, um Web-Sicherheitskontrollen zu umgehen.
Tools zum Testen/Ausnutzen
-
Burp Suite — Alternative Pfade und Parameter testen.
-
ffuf — Nach alternativen Endpunkten fuzzen.
-
Nuclei — Templates für exponierte Dienste.
-
API-Dokumentationsanalyse auf Inkonsistenzen.
CVE-Beispiele
-
CVE-2020-5902 — F5 BIG-IP alternativer Pfad-Bypass.
-
CVE-2021-22986 — F5 iControl REST-Bypass.
-
CVE-2019-11510 — Pulse Secure Pfad-Bypass.
Referenzen
-
MITRE. "CWE-288: Authentication Bypass Using an Alternate Path or Channel." https://cwe.mitre.org/data/definitions/288.html
-
OWASP. "Testing for Bypassing Authentication Schema." https://owasp.org/www-project-web-security-testing-guide/