Egon Okerman f22ae4c3e2 [APPSEC-271] Modify rule S2091: Change text to the education framework format [Python] (#1396)
* 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>
2023-03-02 19:03:03 +01:00

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.