Les applications web Python interrogent la base via l'ORM de Django ou SQLAlchemy, qui tous deux lient les paramètres sur leurs chemins de requête normaux. L'injection apparaît au niveau des portes de sortie délibérées et aux endroits où une requête est assemblée à partir de chaînes plutôt que d'expressions.
Les ORM ici#
- ORM Django :
raw()etcursor.execute(), les fragments select et where deextra(), et la construction de lookups dansfilter(). - SQLAlchemy : les clauses
text()et leexecute()brut construits par formatage de chaînes plutôt que par paramètres liés.
Le schéma commun#
Les deux ORM sont sûrs lorsque la requête est exprimée via leur API avec des paramètres liés, et vulnérables lorsqu'un développeur formate une chaîne. Les raw()/extra() de Django et le text() de SQLAlchemy sont les surfaces brutes explicites ; le cas plus subtil est la construction d'un filtre, d'un lookup ou d'un ORDER BY à partir d'une entrée, où la structure (et pas seulement une valeur) provient de l'appelant. Les identifiants (noms de tables et de colonnes) ne sont jamais paramétrables, de sorte que tout chemin d'ORM qui interpole un identifiant choisi par l'utilisateur est un point d'entrée, quel que soit le binding.
Outils#
- sqlmap : exploitation des points d'entrée raw()/extra() de Django et text() de SQLAlchemy.
- Burp Repeater et Intruder : élaboration de payloads SQL bruts et abus de lookups ou de filtres.