Lack of Administrator Control over Security

Description

Lack of Administrator Control over Security occurs when a product does not provide administrators with sufficient control to manage security settings and configurations. This includes hardcoded security policies, inability to change default credentials, missing audit controls, lack of security feature toggles, and absence of granular permission management. Administrators cannot adapt security posture to their organization's needs.

Risk

Organizations cannot enforce security policies. Default credentials remain unchanged. Security features cannot be enabled/disabled as needed. No ability to comply with regulatory requirements. Unable to respond to security incidents. Audit and monitoring gaps. One-size-fits-all security inappropriate for environment.

Solution

Provide comprehensive security configuration interfaces. Allow credential management and rotation. Implement granular role-based access control. Provide security audit logging with configurable levels. Enable/disable security features via configuration. Document all security settings. Support security policy customization.

Common Consequences

ImpactDetails
SecurityScope: Inability to Adapt

Security cannot be tailored to environment.
ComplianceScope: Regulatory Failure

Cannot meet security audit requirements.
OperationsScope: Incident Response

Cannot respond effectively to security events.

Example Code + Solution Code

Vulnerable Code

// VULNERABLE: No administrative security controls
public class VulnerableSecurityConfig {

    // VULNERABLE: Hardcoded credentials, no way to change
    private static final String ADMIN_USERNAME = "admin";
    private static final String ADMIN_PASSWORD = "admin123";

    public boolean authenticate(String username, String password) {
        // VULNERABLE: Cannot change these credentials
        return ADMIN_USERNAME.equals(username) &&
               ADMIN_PASSWORD.equals(password);
    }

    // VULNERABLE: Hardcoded session timeout
    private static final int SESSION_TIMEOUT = 3600;  // 1 hour, unchangeable

    // VULNERABLE: Hardcoded password policy
    public boolean isPasswordValid(String password) {
        return password.length() >= 6;  // Fixed, cannot be strengthened
    }

    // VULNERABLE: No audit control
    public void performAdminAction(String action) {
        // No logging, no audit trail
        executeAction(action);
    }

    // VULNERABLE: All-or-nothing permissions
    public boolean hasPermission(User user, String resource) {
        // Only admin or regular user, no granularity
        return user.isAdmin();
    }

    // VULNERABLE: Security features hardcoded
    private boolean mfaEnabled = false;  // Cannot be changed
    private boolean bruteForceProtection = false;  // No way to enable
}

// VULNERABLE: No security configuration API
@RestController
public class VulnerableAdminController {

    // No endpoints for:
    // - Changing security settings
    // - Managing users/roles
    // - Viewing audit logs
    // - Configuring authentication
}
# VULNERABLE: Python application without security controls
class VulnerableApp:

    # VULNERABLE: Hardcoded settings
    SECRET_KEY = "hardcoded_secret_key_12345"
    ADMIN_PASSWORD = "admin"

    # VULNERABLE: No configurable security policies
    PASSWORD_MIN_LENGTH = 4  # Fixed, too weak
    SESSION_DURATION = 86400  # 24 hours, unchangeable
    MAX_LOGIN_ATTEMPTS = None  # No rate limiting

    def __init__(self):
        # VULNERABLE: No way to configure
        self.debug_mode = True  # Always on
        self.ssl_verify = False  # Cannot enable

    # VULNERABLE: No audit logging configuration
    def admin_action(self, action, user):
        # No option to log, no severity levels
        self.execute(action)

    # VULNERABLE: Fixed authentication mechanism
    def authenticate(self, username, password):
        # No MFA option
        # No OAuth/SAML integration
        # Single fixed auth method
        return self.check_password(username, password)

    # VULNERABLE: No role customization
    def check_permission(self, user, action):
        # Hardcoded roles, cannot create custom ones
        return user.role == 'admin'

# VULNERABLE: No security configuration file support
# No way to load security settings from config
# No environment-specific security profiles
// VULNERABLE: Node.js app without security controls
const express = require('express');
const app = express();

// VULNERABLE: Hardcoded security settings
const config = {
    jwtSecret: 'hardcoded_jwt_secret',  // Cannot change
    sessionTimeout: 3600,  // Fixed
    corsOrigin: '*',  // Cannot restrict
    rateLimitEnabled: false  // Cannot enable
};

// VULNERABLE: No way to modify security headers
app.use((req, res, next) => {
    // Hardcoded headers, not configurable
    res.setHeader('X-Frame-Options', 'SAMEORIGIN');
    // Admin cannot change to DENY
    next();
});

// VULNERABLE: Fixed authentication
class VulnerableAuth {
    constructor() {
        // No configuration options
        this.hashRounds = 10;  // Fixed
        this.tokenExpiry = '1h';  // Fixed
        this.mfaEnabled = false;  // Cannot enable
    }

    // No admin methods for:
    // - Changing security settings
    // - Managing API keys
    // - Viewing security logs
    // - Configuring rate limits
}

// VULNERABLE: No security dashboard or management UI
// VULNERABLE: No API for security configuration
// VULNERABLE: No audit log access
<?php
// VULNERABLE: PHP application without admin controls

class VulnerableConfig {
    // VULNERABLE: Hardcoded security constants
    const ADMIN_USER = 'admin';
    const ADMIN_PASS = 'password123';

    const SESSION_LIFETIME = 3600;
    const PASSWORD_ALGO = PASSWORD_DEFAULT;
    const MIN_PASSWORD_LENGTH = 4;

    // No way to change any of these at runtime
    // No admin interface to modify
}

// VULNERABLE: No configurable security features
class VulnerableSecurityManager {

    private $features = [
        'csrf_protection' => true,  // Hardcoded
        'xss_filtering' => false,   // Cannot enable
        'sql_escaping' => true,
        'rate_limiting' => false,   // Cannot enable
        'ip_blocking' => false,     // Cannot enable
    ];

    // No setters, no admin interface
    public function isEnabled($feature) {
        return $this->features[$feature] ?? false;
    }

    // VULNERABLE: No audit capabilities
    public function logSecurityEvent($event) {
        // Logging is hardcoded off, no way to enable
        // No log level configuration
        // No log destination options
    }
}

// VULNERABLE: No user/role management
class VulnerableUserManager {
    // Hardcoded roles
    private $roles = ['admin', 'user'];  // Cannot add custom roles

    // Hardcoded permissions
    private $permissions = [
        'admin' => ['*'],
        'user' => ['read']
    ];
    // Cannot modify, no RBAC interface
}
?>

Fixed Code

// SAFE: Comprehensive administrative security controls
@Configuration
public class SecureSecurityConfig {

    @Value("${security.session.timeout:3600}")
    private int sessionTimeout;

    @Value("${security.password.minLength:12}")
    private int minPasswordLength;

    @Value("${security.mfa.enabled:false}")
    private boolean mfaEnabled;

    @Value("${security.bruteforce.protection:true}")
    private boolean bruteForceProtection;

    // SAFE: Credentials from secure configuration
    @Value("${admin.password.hash}")
    private String adminPasswordHash;

    // SAFE: Configurable password policy
    @Bean
    public PasswordPolicy passwordPolicy() {
        return PasswordPolicy.builder()
            .minLength(minPasswordLength)
            .requireUppercase(configService.getBoolean("password.requireUppercase", true))
            .requireNumber(configService.getBoolean("password.requireNumber", true))
            .requireSpecial(configService.getBoolean("password.requireSpecial", false))
            .build();
    }
}

// SAFE: Admin security management API
@RestController
@RequestMapping("/admin/security")
@PreAuthorize("hasRole('SECURITY_ADMIN')")
public class SecurityAdminController {

    @Autowired
    private SecurityConfigService securityConfigService;

    @Autowired
    private AuditService auditService;

    // SAFE: Update security settings
    @PutMapping("/settings")
    public ResponseEntity<?> updateSecuritySettings(@RequestBody SecuritySettings settings) {
        auditService.log("SECURITY_SETTINGS_CHANGE", settings);
        securityConfigService.update(settings);
        return ResponseEntity.ok().build();
    }

    // SAFE: Configure password policy
    @PutMapping("/password-policy")
    public ResponseEntity<?> updatePasswordPolicy(@RequestBody PasswordPolicy policy) {
        auditService.log("PASSWORD_POLICY_CHANGE", policy);
        securityConfigService.updatePasswordPolicy(policy);
        return ResponseEntity.ok().build();
    }

    // SAFE: Enable/disable MFA
    @PostMapping("/mfa/toggle")
    public ResponseEntity<?> toggleMFA(@RequestParam boolean enabled) {
        auditService.log("MFA_TOGGLE", enabled);
        securityConfigService.setMFAEnabled(enabled);
        return ResponseEntity.ok().build();
    }

    // SAFE: View security audit logs
    @GetMapping("/audit")
    public ResponseEntity<List<AuditEvent>> getAuditLogs(
            @RequestParam(required = false) String startDate,
            @RequestParam(required = false) String endDate,
            @RequestParam(required = false) String eventType) {
        return ResponseEntity.ok(auditService.query(startDate, endDate, eventType));
    }

    // SAFE: Manage security features
    @GetMapping("/features")
    public ResponseEntity<Map<String, Boolean>> getSecurityFeatures() {
        return ResponseEntity.ok(securityConfigService.getAllFeatures());
    }

    @PutMapping("/features/{feature}")
    public ResponseEntity<?> toggleFeature(
            @PathVariable String feature,
            @RequestParam boolean enabled) {
        auditService.log("FEATURE_TOGGLE", feature + ":" + enabled);
        securityConfigService.setFeature(feature, enabled);
        return ResponseEntity.ok().build();
    }
}

// SAFE: Role-based access control management
@RestController
@RequestMapping("/admin/rbac")
public class RBACAdminController {

    @PostMapping("/roles")
    public ResponseEntity<?> createRole(@RequestBody Role role) {
        return ResponseEntity.ok(rbacService.createRole(role));
    }

    @PutMapping("/roles/{roleId}/permissions")
    public ResponseEntity<?> updatePermissions(
            @PathVariable Long roleId,
            @RequestBody List<Permission> permissions) {
        return ResponseEntity.ok(rbacService.updatePermissions(roleId, permissions));
    }
}
# SAFE: Python with comprehensive admin controls
from dataclasses import dataclass
from typing import Dict, Any, Optional
import yaml

@dataclass
class SecuritySettings:
    session_timeout: int = 3600
    password_min_length: int = 12
    password_require_uppercase: bool = True
    password_require_number: bool = True
    password_require_special: bool = True
    mfa_enabled: bool = False
    rate_limiting_enabled: bool = True
    max_login_attempts: int = 5
    lockout_duration: int = 900
    audit_level: str = 'INFO'

class SecurityConfigService:
    def __init__(self, config_path: str = '/etc/app/security.yaml'):
        self.config_path = config_path
        self.settings = self._load_settings()
        self.audit_logger = AuditLogger()

    def _load_settings(self) -> SecuritySettings:
        """Load settings from config file"""
        try:
            with open(self.config_path) as f:
                config = yaml.safe_load(f)
                return SecuritySettings(**config.get('security', {}))
        except FileNotFoundError:
            return SecuritySettings()

    def update_setting(self, key: str, value: Any, admin_user: str):
        """Admin can update any security setting"""
        old_value = getattr(self.settings, key, None)

        # Audit the change
        self.audit_logger.log(
            event='SECURITY_SETTING_CHANGE',
            user=admin_user,
            details={
                'setting': key,
                'old_value': old_value,
                'new_value': value
            }
        )

        setattr(self.settings, key, value)
        self._save_settings()

    def _save_settings(self):
        """Persist settings to config file"""
        with open(self.config_path, 'w') as f:
            yaml.dump({'security': asdict(self.settings)}, f)

    def get_all_settings(self) -> Dict[str, Any]:
        """Get all settings for admin UI"""
        return asdict(self.settings)

# SAFE: Admin API for security management
from flask import Flask, request, jsonify
from functools import wraps

app = Flask(__name__)
security_service = SecurityConfigService()

def require_security_admin(f):
    @wraps(f)
    def decorated(*args, **kwargs):
        user = get_current_user()
        if not user.has_role('SECURITY_ADMIN'):
            return jsonify({'error': 'Forbidden'}), 403
        return f(*args, **kwargs)
    return decorated

@app.route('/admin/security/settings', methods=['GET'])
@require_security_admin
def get_security_settings():
    """Get all security settings"""
    return jsonify(security_service.get_all_settings())

@app.route('/admin/security/settings/<key>', methods=['PUT'])
@require_security_admin
def update_security_setting(key):
    """Update a security setting"""
    value = request.json.get('value')
    admin_user = get_current_user().username
    security_service.update_setting(key, value, admin_user)
    return jsonify({'success': True})

@app.route('/admin/security/audit', methods=['GET'])
@require_security_admin
def get_audit_logs():
    """Query security audit logs"""
    start = request.args.get('start')
    end = request.args.get('end')
    event_type = request.args.get('type')
    logs = audit_service.query(start, end, event_type)
    return jsonify(logs)

@app.route('/admin/security/features', methods=['GET', 'PUT'])
@require_security_admin
def manage_features():
    """Manage security feature toggles"""
    if request.method == 'GET':
        return jsonify(security_service.get_features())
    else:
        feature = request.json.get('feature')
        enabled = request.json.get('enabled')
        security_service.toggle_feature(feature, enabled, get_current_user())
        return jsonify({'success': True})

# SAFE: Role and permission management
@app.route('/admin/rbac/roles', methods=['GET', 'POST'])
@require_security_admin
def manage_roles():
    if request.method == 'GET':
        return jsonify(rbac_service.get_all_roles())
    else:
        role = request.json
        created = rbac_service.create_role(role)
        return jsonify(created), 201
// SAFE: Node.js with admin security controls
const express = require('express');
const fs = require('fs');
const yaml = require('js-yaml');

class SecurityConfigService {
    constructor(configPath = '/etc/app/security.yaml') {
        this.configPath = configPath;
        this.settings = this.loadSettings();
        this.auditLogger = new AuditLogger();
    }

    loadSettings() {
        try {
            const config = yaml.load(fs.readFileSync(this.configPath));
            return {
                sessionTimeout: config.session?.timeout ?? 3600,
                passwordMinLength: config.password?.minLength ?? 12,
                mfaEnabled: config.mfa?.enabled ?? false,
                rateLimitEnabled: config.rateLimit?.enabled ?? true,
                maxLoginAttempts: config.rateLimit?.maxAttempts ?? 5,
                corsOrigins: config.cors?.origins ?? [],
                auditLevel: config.audit?.level ?? 'INFO',
                ...config
            };
        } catch (e) {
            return this.getDefaultSettings();
        }
    }

    updateSetting(key, value, adminUser) {
        const oldValue = this.settings[key];

        this.auditLogger.log({
            event: 'SECURITY_SETTING_CHANGE',
            user: adminUser,
            setting: key,
            oldValue,
            newValue: value
        });

        this.settings[key] = value;
        this.saveSettings();
    }

    saveSettings() {
        fs.writeFileSync(this.configPath, yaml.dump(this.settings));
    }

    getAllSettings() {
        return { ...this.settings };
    }
}

// SAFE: Admin security API
const router = express.Router();
const securityService = new SecurityConfigService();

// Middleware for security admin check
const requireSecurityAdmin = (req, res, next) => {
    if (!req.user?.hasRole('SECURITY_ADMIN')) {
        return res.status(403).json({ error: 'Forbidden' });
    }
    next();
};

router.use(requireSecurityAdmin);

// Get all security settings
router.get('/settings', (req, res) => {
    res.json(securityService.getAllSettings());
});

// Update security setting
router.put('/settings/:key', (req, res) => {
    const { key } = req.params;
    const { value } = req.body;
    securityService.updateSetting(key, value, req.user.username);
    res.json({ success: true });
});

// Manage security features
router.get('/features', (req, res) => {
    res.json(securityService.getFeatures());
});

router.put('/features/:feature', (req, res) => {
    const { feature } = req.params;
    const { enabled } = req.body;
    securityService.toggleFeature(feature, enabled, req.user);
    res.json({ success: true });
});

// Query audit logs
router.get('/audit', async (req, res) => {
    const { start, end, type } = req.query;
    const logs = await auditService.query(start, end, type);
    res.json(logs);
});

// RBAC management
router.get('/roles', (req, res) => {
    res.json(rbacService.getAllRoles());
});

router.post('/roles', (req, res) => {
    const role = rbacService.createRole(req.body);
    res.status(201).json(role);
});

router.put('/roles/:roleId/permissions', (req, res) => {
    rbacService.updatePermissions(req.params.roleId, req.body.permissions);
    res.json({ success: true });
});

module.exports = router;

Exploited in the Wild

Hardcoded Credentials

Default passwords that cannot be changed exploited at scale.

Compliance Failures

Organizations failing audits due to inflexible security.

Incident Response Gaps

Unable to respond to breaches due to missing controls.


Tools to test/exploit

  • Security configuration scanners.

  • Compliance audit tools.

  • Default credential scanners.


CVE Examples

  • Numerous CVEs from hardcoded credentials.

  • IoT devices with unchangeable passwords.


References

  1. MITRE. "CWE-671: Lack of Administrator Control over Security." https://cwe.mitre.org/data/definitions/671.html

  2. NIST security configuration guidelines.