Skip to content

CWE-749: Exposed Dangerous Method or Function

Overview

Exposed dangerous methods (admin functions, debug endpoints, internal APIs, privileged operations) accessible without proper authorization enable attackers to invoke sensitive functionality directly, bypassing normal access controls and security checks.

OWASP Classification

A01:2025 - Broken Access Control

Risk

Critical: Exposed dangerous methods enable direct invocation of admin functions, database operations, file system access, code execution, configuration changes, and user impersonation without authentication/authorization checks.

Remediation Strategy

Make Methods Private/Internal (Primary Defense)

# VULNERABLE - public dangerous method

class UserController:
    def delete_all_users(self):  # Public!
        db.execute("DELETE FROM users")
        return {"deleted": "all users"}

# Attacker: POST /api/users/delete_all_users

# SECURE - private method with authorization

class UserController:
    @require_authentication
    @require_role('SUPER_ADMIN')
    @audit_log
    def delete_user(self, user_id):
        # Can only delete one user at a time
        # Requires authentication and authorization
        if not self._validate_delete(user_id):
            raise PermissionError()
        user = User.query.get_or_404(user_id)
        db.session.delete(user)
        db.session.commit()

    def _validate_delete(self, user_id):
        # Internal helper - not exposed
        return user_id != current_user.id

Remove Debug/Admin Endpoints from Production

# VULNERABLE - debug endpoint in production

@app.route('/admin/execute_sql')
def execute_sql():
    query = request.args.get('query')
    result = db.execute(query)  # SQL injection + exposed!
    return jsonify(result)

# SECURE - remove entirely or protect

import os

if os.getenv('ENVIRONMENT') == 'development':
    @app.route('/dev/debug')
    @require_local_access  # Only from localhost
    @require_dev_token
    def debug_endpoint():
        # Only available in dev
        return {"debug": get_debug_info()}

Implement Proper Access Controls

// VULNERABLE - no access control
@RestController
public class AdminController {
    @PostMapping("/api/admin/grant-admin")
    public Response grantAdmin(@RequestParam Long userId) {
        // Anyone can call this!
        userService.setRole(userId, Role.ADMIN);
        return Response.ok();
    }
}

// SECURE - proper authorization
@RestController
@RequestMapping("/api/admin")
@PreAuthorize("hasRole('SUPER_ADMIN')")
public class AdminController {

    @PostMapping("/grant-admin")
    @PreAuthorize("#userId != authentication.principal.id")  // Can't self-promote
    @AuditLog(action = "GRANT_ADMIN")
    public Response grantAdmin(
            @RequestParam Long userId,
            @AuthenticationPrincipal User currentUser) {

        // Additional validation
        if (!canGrantAdminTo(currentUser, userId)) {
            throw new AccessDeniedException();
        }

        userService.setRole(userId, Role.ADMIN);
        return Response.ok();
    }
}

Use Allowlists for Exposed Functions

// VULNERABLE - dynamic method invocation
app.post('/api/invoke', (req, res) => {
    const method = req.body.method;
    const args = req.body.args;

    // Attacker can call ANY method!
    const result = controller[method](...args);
    res.json(result);
});

// SECURE - allowlist of safe methods
const ALLOWED_METHODS = new Set([
    'getUserProfile',
    'updateProfile',
    'changePassword'
]);

app.post('/api/invoke', authenticate, (req, res) => {
    const method = req.body.method;

    if (!ALLOWED_METHODS.has(method)) {
        return res.status(403).json({error: 'Method not allowed'});
    }

    // Additional authorization check
    if (!canInvoke(req.user, method)) {
        return res.status(403).json({error: 'Unauthorized'});
    }

    const result = controller[method](req.user, req.body.args);
    res.json(result);
});

Remediation Steps

Core principle: Do not expose dangerous functionality to untrusted actors; gate high-risk operations behind strong controls.

  1. Identify exposed dangerous methods
  2. Determine exposure paths
  3. Check authorization gaps
  4. Make methods private/internal: Change visibility modifiers, remove from public API, move to internal classes
  5. Add access controls: Require authentication tokens, verify user roles, implement permission checks before execution
  6. Test unauthorized access: Attempt to invoke dangerous methods without proper credentials (should return 401/403)
  7. Audit all exposed endpoints: Review entire API surface to identify other potentially dangerous methods

Common Exposed Dangerous Methods

Admin Functions:

# Exposed without auth

@app.route('/admin/reset_database')
def reset_database():
    db.drop_all()
    db.create_all()

@app.route('/admin/set_config')
def set_config():
    key = request.args['key']
    value = request.args['value']
    config[key] = value

File Operations:

@GetMapping("/files/delete")
public void deleteFile(@RequestParam String path) {
    new File(path).delete();  // Anyone can delete any file!
}

Code Execution:

@app.route('/eval')
def evaluate():
    code = request.args.get('code')
    return str(eval(code))  # Remote code execution!

Direct Database Access:

<?php
// Direct SQL execution endpoint
if ($_GET['action'] == 'query') {
    $result = mysqli_query($conn, $_GET['sql']);
    echo json_encode(mysqli_fetch_all($result));
}

Additional Resources