Hey there, ran into an XXE issue during a Burp scan that traced back to pysaml2. Not sure if it's something you would consider fixing on your end, but I figured it would be helpful to at least be aware.
Code Version
4.5.0
Expected Behavior
pysaml2 should reject all XXE attempts.
Current Behavior
It is possible to trigger external HTTP requests from the function saml_client.parse_authn_request_response (and possibly others) by adding the following to POST responses:
<!DOCTYPE saml2p:response PUBLIC "-//B/A/EN" "http://example.com/uhoh">
Possible Solution
So, the root cause it pretty interesting. It's the calls to xmlsec1 to verify payloads that make the external request. This is a known vulnerability (CVE-2017-1000061)
Versions of xmlsec1 below 1.2.23 are vulnerable. Unfortunately, secure versions aren't available in every package manager by default. In our case, the system was running Ubuntu xenial (by way of Heroku's Cedar stack), which was giving us version 1.2.20 when installed from apt. I'm sure there are lots more folks running systems like this out there, and it may be worthwhile to still be secure by default in this case.
Adding the flag forbid_dtd to the defusedxml calls would prevent the XXE vulnerability in cases of an old xmlsec1:
envelope = defusedxml.ElementTree.fromstring(text, forbid_dtd=True)
This causes pysaml2 to bail before calling out to xmlsec1.
This appears to only break tests that are supposed to fail for XXE vulnerabilities since a different error message is returned.
Steps to Reproduce
I can provide a runnable example if desired, but wanted to test the waters first.
Thanks!
Hey there, ran into an XXE issue during a Burp scan that traced back to pysaml2. Not sure if it's something you would consider fixing on your end, but I figured it would be helpful to at least be aware.
Code Version
4.5.0
Expected Behavior
pysaml2 should reject all XXE attempts.
Current Behavior
It is possible to trigger external HTTP requests from the function
saml_client.parse_authn_request_response(and possibly others) by adding the following to POST responses:<!DOCTYPE saml2p:response PUBLIC "-//B/A/EN" "http://example.com/uhoh">Possible Solution
So, the root cause it pretty interesting. It's the calls to
xmlsec1to verify payloads that make the external request. This is a known vulnerability (CVE-2017-1000061)Versions of
xmlsec1below 1.2.23 are vulnerable. Unfortunately, secure versions aren't available in every package manager by default. In our case, the system was running Ubuntu xenial (by way of Heroku's Cedar stack), which was giving us version 1.2.20 when installed from apt. I'm sure there are lots more folks running systems like this out there, and it may be worthwhile to still be secure by default in this case.Adding the flag
forbid_dtdto thedefusedxmlcalls would prevent the XXE vulnerability in cases of an oldxmlsec1:envelope = defusedxml.ElementTree.fromstring(text, forbid_dtd=True)This causes pysaml2 to bail before calling out to
xmlsec1.This appears to only break tests that are supposed to fail for XXE vulnerabilities since a different error message is returned.
Steps to Reproduce
I can provide a runnable example if desired, but wanted to test the waters first.
Thanks!