Link Search Menu Expand Document

M6: Insecure Authorization

It is important to distinguish between authentication and authorization: the former is the act of identifying an individual whereas the latter is the act of checking that the identified individual has the necessary permissions to perform the act. To exploit Insecure Authorization, adversaries usually log in to the application as a legitimate user first, then they typically force-browse to a vulnerable endpoint.

Because authentication precedes authorization, if an application fails to identify an individual before making an API request, then it automatically suffers from Insecure Authorization.

Usually, Insecure Authorization is greatly associated with IDOR - Insecure Direct Object Reference, but it is also found on hidden endpoints that developers assume will be accessed only by someone with the right role. If the mobile application sends the user role or permissions to the back-end as part of the request, it is likely vulnerable to Insecure Authorization.

The movie below demonstrates how Insecure Authorization can be exploited on Goatlin.

Insecure Authorization in Goatlin is clearly a back-end issue. Although API routes include authentication middleware when appropriate, no permissions (authorization) are validated:

router.put('/accounts/:username/notes/:note', auth, async (req, res, next) => {
    // ...
});

router.get('/accounts/:username/notes', auth, async (req, res, next) => {
    // ...
});

In this case, resources can be managed only by their owner. This is the validation that our authorization middleware will be responsible for:

function ownership (req, res, next) {
    if (req.params.username !== req.account.username) {
        res.statusMessage = "Unauthorized"
        return res.status(403).end();
    }

    next();
}

This is how API routes look like when they include both authentication and authorization middlewares:

router.put('/accounts/:username/notes/:note', [auth, ownership], async (req, res, next) => {
    // ...
});

router.get('/accounts/:username/notes', [auth, ownership], async (req, res, next) => {
    // ...
});

Resources

Readings