
* Add rule information * Add lxml * Add Python stdlib * Change the XPath queries such that they're correct * Remove nonexistant highlighting reference * Add lxml as allowed framework * Split up parameterized queries and validation * Fix typo * Make changes in Java docs * Fix .NET text * Update rules/S2091/python/how-to-fix-it/python.adoc Co-authored-by: Pierre-Loup <49131563+pierre-loup-tristant-sonarsource@users.noreply.github.com> * Update common texts * Update code samples * Fix typo * Use correct syntax for lxml * Apply code review fixes Co-authored-by: Pierre-Loup <49131563+pierre-loup-tristant-sonarsource@users.noreply.github.com>
55 lines
1.7 KiB
Plaintext
55 lines
1.7 KiB
Plaintext
=== How to fix it in lxml
|
|
|
|
The following noncompliant code is vulnerable to XPath injections because untrusted data is
|
|
concatenated to an XPath query without prior validation.
|
|
|
|
==== Noncompliant code example
|
|
|
|
[source,python,diff-id=1,diff-type=noncompliant]
|
|
----
|
|
from flask import request
|
|
from lxml import etree
|
|
|
|
@app.route('/authenticate')
|
|
def authenticate():
|
|
username = request.args['username']
|
|
password = request.args['password']
|
|
expression = "./users/user[@name='" + username + "' and @pass='" + password + "']"
|
|
tree = etree.parse('resources/users.xml')
|
|
|
|
if tree.find(expression) is None:
|
|
return "Invalid credentials", 401
|
|
else:
|
|
return "Success", 200
|
|
----
|
|
|
|
==== Compliant solution
|
|
|
|
[source,python,diff-id=1,diff-type=compliant]
|
|
----
|
|
from flask import request
|
|
from lxml import etree
|
|
|
|
@app.route('/authenticate')
|
|
def authenticate():
|
|
username = request.args['username']
|
|
password = request.args['password']
|
|
expression = "./users/user[@name=$username and @pass=$password]"
|
|
tree = etree.parse('resources/users.xml')
|
|
|
|
if tree.xpath(expression, username=username, password=password) is None:
|
|
return "Invalid credentials", 401
|
|
else:
|
|
return "Success", 200
|
|
----
|
|
|
|
=== How does this work?
|
|
|
|
As a rule of thumb, the best approach to protect against injections is to
|
|
systematically ensure that untrusted data cannot break out of the initially
|
|
intended logic.
|
|
|
|
include::../../common/fix/parameterized-queries.adoc[]
|
|
|
|
In the example, the username and password are passed as https://lxml.de/xpathxslt.html#:~:text=The%20xpath()%20method%20has%20support%20for%20XPath%20variables%3A[XPath variables] rather than concatenated to the XPath query. By using a parameterized query, injection is successfully prevented.
|