Broken Authentication in Python
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