Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/XML/saml/Assertion.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
use SimpleSAML\SAML2\XML\EncryptableElementTrait;
use SimpleSAML\SAML2\XML\SignableElementTrait;
use SimpleSAML\SAML2\XML\SignedElementTrait;
use SimpleSAML\XML\DOMDocumentFactory;
use SimpleSAML\XML\SchemaValidatableElementInterface;
use SimpleSAML\XML\SchemaValidatableElementTrait;
use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException;
Expand Down Expand Up @@ -326,7 +327,10 @@ public static function fromXML(Dom\Element $xml): static
if (!empty($signature)) {
$assertion->setSignature($signature[0]);
$assertion->wasSignedAtConstruction = true;
$assertion->setXML($xml);

$doc = DOMDocumentFactory::create();
$doc->appendChild($doc->importNode($xml, true));
$assertion->setXML($doc->documentElement);
}

return $assertion;
Expand Down
31 changes: 19 additions & 12 deletions tests/Vulnerabilities/GoldenSAMLResponseTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,40 +16,47 @@
use function dirname;

/**
* CVE-2025-66475
*
* @package simplesamlphp/saml2
*/
#[Group('vulnerabilities')]
final class GoldenSAMLResponseTest extends TestCase
{
/**
* CVE-2025-66475 / Void Canonicalization ("Golden SAML Response")
*
* A relative namespace on an ancestor causes libxml2 C14N to fail.
* After the fix this must be treated as fatal; the signature must not
* be accepted (even though DigestValue is the SHA-256 of the empty string).
*/
public function testSignedResponseWithStrayXmlnsThrowsAnException(): void
public function testGoldenSAMLResponseWithRelativeXmlnsIsRejected(): void
{
$doc = DOMDocumentFactory::fromFile(
dirname(__DIR__, 1) . '/resources/xml/vulnerabilities/CVE-2025-66475.xml',
);

$response = Response::fromXML($doc->documentElement);
$assertion = $response->getAssertions()[0];
/** @var \SimpleSAML\XMLSecurity\XML\ds\X509Data $data */
$data = $assertion->getSignature()->getKeyInfo()->getInfo()[0];

// Key material taken from the Signature in the fixture
/** @var \SimpleSAML\XMLSecurity\XML\ds\X509Data $x509Data */
$x509Data = $assertion->getSignature()->getKeyInfo()->getInfo()[0];
$cert = $x509Data->getData()[0]->getContent()->getValue();

$alg = $assertion->getSignature()
->getSignedInfo()
->getSignatureMethod()
->getAlgorithm()
->getValue();

$verifier = (new SignatureAlgorithmFactory())->getAlgorithm(
$assertion->getSignature()->getSignedInfo()->getSignatureMethod()->getAlgorithm()->getValue(),
$alg,
new PublicKey(
new PEM(
PEM::TYPE_PUBLIC_KEY,
$data->getData()[0]->getContent()->getValue(),
),
new PEM(PEM::TYPE_PUBLIC_KEY, $cert),
),
);

$this->expectException(CanonicalizationFailedException::class);

// When PHP 8.5 becomes the minimum:
// (void)@$assertion->verify($verifier);
@$assertion->verify($verifier);
}
}
Loading