Skip to content

Commit 05f8ce7

Browse files
committed
Properly detect canonicalization failure
1 parent 6f2b9b2 commit 05f8ce7

File tree

2 files changed

+70
-2
lines changed

2 files changed

+70
-2
lines changed

tests/SAML2/Response/SignatureValidationTest.php

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@
2222
use SimpleSAML\SAML2\XML\samlp\Response;
2323
use SimpleSAML\Test\SAML2\Constants as C;
2424
use SimpleSAML\XML\DOMDocumentFactory;
25+
use SimpleSAML\XMLSecurity\Alg\Signature\SignatureAlgorithmFactory;
26+
use SimpleSAML\XMLSecurity\CryptoEncoding\PEM;
27+
use SimpleSAML\XMLSecurity\Exception\CanonicalizationFailedException;
28+
use SimpleSAML\XMLSecurity\Key\PublicKey;
2529
use SimpleSAML\XMLSecurity\TestUtils\PEMCertificatesMock;
2630
use SimpleSAML\XMLSecurity\Utils\Certificate;
2731

@@ -46,12 +50,12 @@ final class SignatureValidationTest extends MockeryTestCase
4650
private ServiceProvider $serviceProviderConfiguration;
4751

4852
/**
49-
* @var \Mockery\MockInterface Mock of \SAML2\Assertion\ProcessorBuilder
53+
* @var \Mockery\MockInterface Mock of \SimpleSAML\SAML2\Assertion\ProcessorBuilder
5054
*/
5155
private MockInterface $assertionProcessorBuilder;
5256

5357
/**
54-
* @var \Mockery\MockInterface Mock of \SAML2\Assertion\Processor
58+
* @var \Mockery\MockInterface Mock of \SimpleSAML\SAML2\Assertion\Processor
5559
*/
5660
private MockInterface $assertionProcessor;
5761

@@ -180,6 +184,32 @@ public function testThatAnUnsignedResponseWithNoSignedAssertionsThrowsAnExceptio
180184
}
181185

182186

187+
/**
188+
* CVE-2025-66475
189+
*/
190+
#[PreserveGlobalState(false)]
191+
#[RunInSeparateProcess]
192+
public function testSignedResponseWithStrayXmlnsThrowsAnException(): void
193+
{
194+
$doc = DOMDocumentFactory::fromFile(
195+
dirname(__DIR__, 2) . '/resources/xml/vulnerabilities/CVE-2025-66475.xml',
196+
);
197+
198+
$response = Response::fromXML($doc->documentElement);
199+
$assertion = $response->getAssertions()[0];
200+
201+
$verifier = (new SignatureAlgorithmFactory())->getAlgorithm(
202+
$assertion->getSignature()->getSignedInfo()->getSignatureMethod()->getAlgorithm()->getValue(),
203+
new PublicKey(
204+
new PEM(PEM::TYPE_PUBLIC_KEY, $assertion->getSignature()->getKeyInfo()->getInfo()[0]->getData()[0]->getContent()->getValue()),
205+
),
206+
);
207+
208+
$this->expectException(CanonicalizationFailedException::class);
209+
$assertion->verify($verifier);
210+
}
211+
212+
183213
/**
184214
* @return \SimpleSAML\SAML2\XML\samlp\Response
185215
*/
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?xml version="1.0"?>
2+
<samlp:Response xmlns:example="1" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="_8cdf9a4d-a007-4fca-b160-df63064505e0" Version="2.0" IssueInstant="2014-07-17T01:01:48Z" Destination="http://localhost:8008/index.php" InResponseTo="ONELOGIN_4fee3b046395c4e751011e97f8900b5273d56685">
3+
<saml:Issuer>http://localhost:7007/saml/metadata</saml:Issuer>
4+
<samlp:Status>
5+
<samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
6+
</samlp:Status>
7+
<saml:Assertion xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" ID="_8cdf9a4d-a007-4fca-b160-df63064505ef" Version="2.0" IssueInstant="2014-07-17T01:01:48Z">
8+
<saml:Issuer>http://localhost:7007/saml/metadata</saml:Issuer><ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:SignedInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/><ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/><ds:Reference URI="#_8cdf9a4d-a007-4fca-b160-df63064505ef"><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#sha256"/><ds:DigestValue>47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>ZoMimqpvmI7CvzorrBzvKDzwOODF9SjUfMhayHqDPAZYAyI+1DyUcDyZTqvicCnvHg+ru6/uvy4btXAg71UntBqvQac7+eR5FwBO1n4sVj6cddCXiODwEZJOgNo+sD6uptpSuWqMau+M49OlBpozWTPeYsgvac56lh/pub6bintG/+0iAhGKnCuM9IN52kQt/nlz9Oq4W8OhwbsVZaj3n2CoMQOz9VztH3KWtRTAcFqdbABHgDqDneuHzvjgcd9RR8ySkD7xmd3Nsnv+YKToWnVnderiaj6yxrny6El8FOjPu6ijpD2RsDHVF4/GktGhBcvnIOEk2UATwr//ijF3Pw==</ds:SignatureValue><ds:KeyInfo><ds:X509Data><ds:X509Certificate>MIIDjTCCAnWgAwIBAgIUdyJH8PSoz8kG7eyfZuvmx7ey/PswDQYJKoZIhvcNAQELBQAwVjELMAkGA1UEBhMCVVMxDjAMBgNVBAgMBVN0YXRlMQ0wCwYDVQQHDARDaXR5MRUwEwYDVQQKDAxPcmdhbml6YXRpb24xETAPBgNVBAMMCHNhbWwtaWRwMB4XDTI1MDcyMDIxMjYzNVoXDTI2MDcyMDIxMjYzNVowVjELMAkGA1UEBhMCVVMxDjAMBgNVBAgMBVN0YXRlMQ0wCwYDVQQHDARDaXR5MRUwEwYDVQQKDAxPcmdhbml6YXRpb24xETAPBgNVBAMMCHNhbWwtaWRwMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAj8yIUUgSxlQ81y7CVBPhtgZN0Aje5b2SOtXLuk5HYwISdGXZLVLa+uzogkzvnMW/NKfLPCJhfpQ+9ZAMe9O1EguBPHH0g1j14cwI24rEDZElFGXCAKmJcqA7TfZDf/YAW/YHKT4fgZ2YWf3ZrnYrbYgkSsDMVPHdjhRV/lCcu0D/piPJQHjbobol+EUkJlqpUucT2sK0kmBlrn8LNvHK593niLOhZmaa21zH+EltdS9R5zhwu8bvoPkjCk5GvRtCU+Pbprie82Xwl2Ju46y1Zs/NgdCVAW7waKqkH8VvZyp98ffgRsCJdRfNbsq2FS5zj5mbIdmj7DLPJOGCTlJUnQIDAQABo1MwUTAdBgNVHQ4EFgQULkKObinJPgUmM0mh/0JSn4Ht0EcwHwYDVR0jBBgwFoAULkKObinJPgUmM0mh/0JSn4Ht0EcwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAcn6Hfg770sOFqQZWNZpHIaQ2yC87x0CebRjnvVJqU6/wyGTPsF5GsDCHKh0cWXl5QHtJXvn8buzx9isql927tgkhWmMEO8/iOZTCLTxrUuOPLty/vaNq1hfRqYMYqtfdN3VQ9RX/tAPggSL9gDvR4PNAkG1emWbFHkcWGJNbmWnK0LL92rtiXGqumfwHd2OeE2tY/WNY0FyQCMFajUsx5CKG0jlNHzqOobmW5SZ4j8kafjsGJXHmGhHlO3d5OlSG1ne+tZmetqo2i9qEOLGKeRB80sGNvq4SVHYIcdgNEc3K8LDBXNyaiiyGxAP4LtD+RpAE4ViMUxmOXOwgZ/vSLg==</ds:X509Certificate></ds:X509Data></ds:KeyInfo></ds:Signature>
9+
<saml:Subject>
10+
<saml:NameID SPNameQualifier="http://localhost:8080" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient">_ce3d2948b4cf20146dee0a0b3dd6f69b6cf86f62d7</saml:NameID>
11+
<saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
12+
<saml:SubjectConfirmationData NotBefore="2014-07-17T01:01:18Z" NotOnOrAfter="2026-01-18T06:21:48Z"/>
13+
</saml:SubjectConfirmation>
14+
</saml:Subject>
15+
<saml:Conditions NotBefore="2014-07-17T01:01:18Z" NotOnOrAfter="2026-01-18T06:21:48Z">
16+
<saml:AudienceRestriction>
17+
<saml:Audience>http://localhost:8080</saml:Audience>
18+
</saml:AudienceRestriction>
19+
</saml:Conditions>
20+
<saml:AuthnStatement AuthnInstant="2014-07-17T01:01:48Z" SessionNotOnOrAfter="2026-07-17T09:01:48Z" SessionIndex="_be9967abd904ddcae3c0eb4189adbe3f71e327cf93">
21+
<saml:AuthnContext>
22+
<saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml:AuthnContextClassRef>
23+
</saml:AuthnContext>
24+
</saml:AuthnStatement>
25+
<saml:AttributeStatement>
26+
<saml:Attribute Name="uid" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
27+
<saml:AttributeValue xsi:type="xs:string">admin</saml:AttributeValue>
28+
</saml:Attribute>
29+
<saml:Attribute Name="mail" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
30+
<saml:AttributeValue xsi:type="xs:string">test@example.com</saml:AttributeValue>
31+
</saml:Attribute>
32+
<saml:Attribute Name="eduPersonAffiliation" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
33+
<saml:AttributeValue xsi:type="xs:string">users</saml:AttributeValue>
34+
<saml:AttributeValue xsi:type="xs:string">examplerole1</saml:AttributeValue>
35+
</saml:Attribute>
36+
</saml:AttributeStatement>
37+
</saml:Assertion>
38+
</samlp:Response>

0 commit comments

Comments
 (0)