Mass Assignment in Python
Using Flask
Vulnerable Example
In the below example of a vulnerability, the parameters coming from an HTTP request are deserialized to a Python dictionary to then be used in a downstream context, for example a SQL query. The logic below allows a malicious user to override a sensible field in a SQL insert query:
@object.route("/insert", methods=['POST'])
def object_insert():
# initialise the dictionary with a predefined value
values = {'isAdmin': get_admin_status()}
# update the values (sensitive_field may be overridden)
values.update(request.form.to_dict(flat=True))
# pass the dictionary to the SQL query
sql_statement = 'INSERT INTO messages VALUES (:isAdmin, :values_from_user)'
conn = sqlite3.connect('db.sqlite')
conn.cursor().execute(sql_statement, values)
conn.commit()
return redirect("/", code=201)
The following POST request causes the insertion of true
instead of get_admin_status()
in isAdmin
:
isAdmin=true&values_from_user=yyy
Prevention
Flask does not provide any specific control to prevent Mass Assignment; it is up to the developer to restrict the fields that are safe to be retrieved from an HTTP request:
values = {
'isAdmin': get_admin_status(),
'values_from_user': request.form.get('values_from_user')
}
References
CWE - CWE-915: Improperly Controlled Modification of Dynamically-Determined Object Attributes