Skip to content

Add linter for broken function level authorization #27

@mschwager

Description

@mschwager

Per the OWASP API Security Top 10, broken function level authorization is a big security concern. Adding a linter to detect this would be very useful. Most Python web application frameworks use decorators on function-level API routes (e.g. rest_framework.decorators.api_view in Django REST framework, flask_login.login_required in Flask-Login).

One way I can envision implementing this would be looking for decorator anomalies in Python files that look like they contain API routes. E.g.

@api.route("/users")
@login_required
def users(request):
    ...

@api.route("/groups")
@login_required
def groups(request):
    ...

@api.route("/settings")
def settings(request):
    # Oops, did we forget @login_required?
    ...

@api.route("/jobs")
@login_required
def jobs(request):
    ...

If XX% of API routes in a file are missing what looks like an authentication decorator, we can flag the function missing the decorator. Another common one for authorization might look something like:

@app.route("/users", roles=[User.Admin])
def users(request):
    ...

@api.route("/groups", roles=[User.Admin])
def groups(request):
    ...

@api.route("/settings", roles=[User.Regular])
def settings(request):
    # Oops, can all users access this sensitive endpoint?
    ...

This may seem trivial, but it gets more difficult as you have many different authentication methods, authorization schemes, and user roles.

This will probably involve some of the following:

  • Looking for common API route decorators and systems used by major Python web frameworks.
  • Using this information to determine if we're in a API route module.
  • Determining what "unusual" looks like in this case (e.g. missing login_required).
  • Performing heuristics, possibly with a configurable threshold, to make the judgement whether a finding is in fact unusual.

There's also some low-hanging fruit here, like just searching for existing "security-off" switches for web framework routes, like:

  • django.views.decorators.csrf.csrf_exempt
  • flask_wtf.csrf.exempt
  • rest_framework.permissions.AllowAny or permission_classes = []
  • Likely many more in well-known third-party packages...

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions