Link Search Menu Expand Document

Broken Authentication in Python

Play SecureFlag Play Python Labs on this vulnerability with SecureFlag!

Vulnerable example

The following snippet contains a Flask web application written in Python, with administrative functionality to delete the database when a specific URL is called.

@app.route('/admin/init', methods=['POST'])
def reinitialize():
    cursor.execute("DROP DATABASE analytics")
    return 'Database has been dropped'

The /admin/init URI is available to everyone and should be protected by an authentication mechanism so that it can’t be abused by malicious actors.

Prevention

Apply the recommended authentication and authorization mechanisms depending on the web framework of choice.

Django

Django uses sessions with a request.user attribute, representing the current user. If the current user has not logged in, the attribute is set to AnonymousUser object. The authentication status can be easily checked with User.is_authenticated.

def admin_init(request):
  if request.user.is_authenticated:
      # Do something for authenticated users.
  else:
      # Do something for anonymous users.

Flask

Flask-Session is an extension for Flask that adds support for server-side sessions to a web application.

from flask import Flask, session
from flask_session import Session

app = Flask(__name__)
app.config.from_object(__name__)
Session(app)

@app.route('/admin/init')
def admin_init():
    if not session.get('logged_user'):
      abort(401)

FastAPI

FastAPI has built-in support for session management with web applications.

This example creates a unique session ID upon login and securely attaches it to a cookie. Other endpoints can use FastAPI’s dependency injection to validate the user’s identity for subsequent requests.

cookie_params = CookieParameters()

cookie = SessionCookie(
    cookie_name="cookie",
    identifier="general_verifier",
    auto_error=True,
    secret_key="DONOTUSE",
    cookie_params=cookie_params,
)

@app.post("/create_session/{name}")
async def create_session(name: str, response: Response):

    session = uuid4()
    data = SessionData(username=name)

    await backend.create(session, data)
    cookie.attach_to_response(response, session)

    return f"created session for {name}"

@app.get("/whoami", dependencies=[Depends(cookie)])
async def whoami(session_data: SessionData = Depends(verifier)):
    return session_data

References

CWE - CWE-287: Improper Authentication

OWASP - A07:2021 - Identification and Authentication Failures

OWASP - Authentication Cheat Sheet