Skip to content

Commit dac6cfe

Browse files
authored
Merge branch 'master' into strict-destination-match
2 parents c898e94 + e163da2 commit dac6cfe

19 files changed

+303
-51
lines changed

CHANGELOG

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,18 @@
11
CHANGELOG
22
=========
3+
v.2.18.0
4+
* Support rejecting unsolicited SAMLResponses.
5+
* Reject SAMLResponse if requestID was provided to the validotr but the InResponseTo attributeof the SAMLResponse is missing
6+
* Check destination against the getSelfURLNoQuery as well on LogoutRequest and LogoutResponse as we do on Response
7+
* Improve getSelfRoutedURLNoQuery method
8+
* Only add responseUrl to the settings if ResponseLocation present in the IdPMetadataParser
9+
* Remove use of $_GET on static method validateBinarySign
10+
* Fix error message when Assertion and NameId are both encrypted (not supported)
11+
12+
v.2.17.1
13+
* Update xmlseclibs to 3.0.4
14+
* Remove Comparison atribute from RequestedAuthnContext when setting has empty value
15+
316
v.2.17.0
417
* Set true as the default value for strict setting
518
* Support 'x509cert' and 'privateKey' on signMetadata security settings

README.md

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@ and supported by OneLogin Inc.
1212
Warning
1313
-------
1414

15+
Version 2.18.0 introduces the 'rejectUnsolicitedResponsesWithInResponseTo' setting parameter, by default disabled, that will allow invalidate unsolicited SAMLResponse. This version as well will reject SAMLResponse if requestId was provided to the validator but the SAMLResponse does not contain a InResponseTo attribute.
16+
as well as the 'destinationStrictlyMatches' parameter, by default disabled, that will force that the Destination URL should strictly match to the address that process the SAMLResponse.
17+
18+
Version 2.17.1 updates xmlseclibs to 3.0.4 (CVE-2019-3465), but php-saml was not directly affected since it implements additional checks that prevent to exploit that vulnerability.
19+
1520
Version 2.17.0 sets strict mode active by default
1621

1722
Update php-saml to 2.15.0, this version includes a security patch related to XEE attacks
@@ -100,7 +105,11 @@ Since [PHP 5.3 is officially unsupported](http://php.net/eol.php) we recommend y
100105

101106
### Code ###
102107

103-
#### Option 1. Download from github ####
108+
#### Option 1. clone the repository from github ####
109+
110+
git clone [email protected]:onelogin/php-saml.git
111+
112+
#### Option 2. Download from github ####
104113

105114
The toolkit is hosted on github. You can download it from:
106115

@@ -111,7 +120,10 @@ Copy the core of the library inside the php application. (each application has i
111120
structure so take your time to locate the PHP SAML toolkit in the best place).
112121
See the "Guide to add SAML support to my app" to know how.
113122

114-
#### Option 2. Composer ####
123+
Take in mind that the compressed file only contains the main files.
124+
If you plan to play with the demos, use the Option 1.
125+
126+
#### Option 3. Composer ####
115127

116128
The toolkit supports [composer](https://getcomposer.org/). You can find the `onelogin/php-saml` package at https://packagist.org/packages/onelogin/php-saml
117129

@@ -515,6 +527,10 @@ $advancedSettings = array (
515527
// will be accepted.
516528
'destinationStrictlyMatches' => false,
517529

530+
// If true, SAMLResponses with an InResponseTo value will be rejectd if not
531+
// AuthNRequest ID provided to the validation method.
532+
'rejectUnsolicitedResponsesWithInResponseTo' => false,
533+
518534
// Algorithm that the toolkit will use on signing process. Options:
519535
// 'http://www.w3.org/2000/09/xmldsig#rsa-sha1'
520536
// 'http://www.w3.org/2000/09/xmldsig#dsa-sha1'

advanced_settings_example.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,10 @@
9191
// will be accepted.
9292
'destinationStrictlyMatches' => false,
9393

94+
// If true, SAMLResponses with an InResponseTo value will be rejectd if not
95+
// AuthNRequest ID provided to the validation method.
96+
'rejectUnsolicitedResponsesWithInResponseTo' => false,
97+
9498
// Algorithm that the toolkit will use on signing process. Options:
9599
// 'http://www.w3.org/2000/09/xmldsig#rsa-sha1'
96100
// 'http://www.w3.org/2000/09/xmldsig#dsa-sha1'

extlib/xmlseclibs/CHANGELOG.txt

Lines changed: 60 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,64 @@
11
xmlseclibs.php
2-
??, ??? ????, 2.0.0
3-
Features:
4-
- Support for locating specific signature when multiple exist in
5-
document. (griga3k)
2+
3+
06, Nov 2019, 3.0.4
4+
Security Improvements:
5+
- Insure only a single SignedInfo element exists within a signature during
6+
verification. Refs CVE-2019-3465.
7+
Bug Fixes:
8+
- Fix variable casing.
9+
10+
15, Nov 2018, 3.0.3
11+
Bug Fixes:
12+
- Fix casing of class name. (Willem Stuursma-Ruwen)
13+
- Fix Xpath casing. (Tim van Dijen)
14+
15+
Improvements:
16+
- Make PCRE2 compliant. (Stefan Winter)
17+
- Add PHP 7.3 support. (Stefan Winter)
18+
19+
27, Sep 2018, 3.0.2
20+
Security Improvements:
21+
- OpenSSL is now a requirement rather than suggestion. (Slaven Bacelic)
22+
- Filter input to avoid XPath injection. (Jaime Pérez)
23+
24+
Bug Fixes:
25+
- Fix missing parentheses (Tim van Dijen)
26+
27+
Improvements:
28+
- Use strict comparison operator to compare digest values. (Jaime Pérez)
29+
- Remove call to file_get_contents that doesn't even work. (Jaime Pérez)
30+
- Document potentially dangerous return value behaviour. (Thijs Kinkhorst)
31+
32+
31, Aug 2017, 3.0.1
33+
Bug Fixes:
34+
- Fixed missing () in function call. (Dennis Væversted)
35+
36+
Improvements:
37+
- Add OneLogin to supported software.
38+
- Add .gitattributes to remove unneeded files. (Filippo Tessarotto)
39+
- Fix bug in example code. (Dan Church)
40+
- Travis: add PHP 7.1, move hhvm to allowed failures. (Thijs Kinkhorst)
41+
- Drop failing extract-win-cert test (Thijs Kinkhorst). (Thijs Kinkhorst)
42+
- Add comments to warn about return values of verify(). (Thijs Kinkhorst)
43+
- Fix tests to properly check return code of verify(). (Thijs Kinkhorst)
44+
- Restore support for PHP >= 5.4. (Jaime Pérez)
45+
46+
25, May 2017, 3.0.0
47+
Improvements:
48+
- Remove use of mcrypt (skymeyer)
49+
50+
08, Sep 2016, 2.0.1
51+
Bug Fixes:
52+
- Strip whitespace characters when parsing X509Certificate. fixes #84
53+
(klemen.bratec)
54+
- Certificate 'subject' values can be arrays. fixes #80 (Andreas Stangl)
55+
- HHVM signing node with ID attribute w/out namespace regenerates ID value.
56+
fixes #88 (Milos Tomic)
57+
58+
Improvements:
59+
- Fix typos and add some PHPDoc Blocks. (gfaust-qb)
60+
- Update lightSAML link. (Milos Tomic)
61+
- Update copyright dates.
662

763
23, Jun 2015, 1.4.0
864
Features:

extlib/xmlseclibs/LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Copyright (c) 2007-2013, Robert Richards <[email protected]>.
1+
Copyright (c) 2007-2019, Robert Richards <[email protected]>.
22
All rights reserved.
33

44
Redistribution and use in source and binary forms, with or without

extlib/xmlseclibs/xmlseclibs.php

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
/**
33
* xmlseclibs.php
44
*
5-
* Copyright (c) 2007-2015, Robert Richards <[email protected]>.
5+
* Copyright (c) 2007-2019, Robert Richards <[email protected]>.
66
* All rights reserved.
77
*
88
* Redistribution and use in source and binary forms, with or without
@@ -35,9 +35,9 @@
3535
* POSSIBILITY OF SUCH DAMAGE.
3636
*
3737
* @author Robert Richards <[email protected]>
38-
* @copyright 2007-2015 Robert Richards <[email protected]>
38+
* @copyright 2007-2019 Robert Richards <[email protected]>
3939
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
40-
* @version 2.0.0 modified
40+
* @version 3.0.4 modified
4141
*/
4242

4343
class XMLSecurityKey {
@@ -589,6 +589,11 @@ public function locateSignature($objDoc, $pos=0) {
589589
$query = ".//secdsig:Signature";
590590
$nodeset = $xpath->query($query, $objDoc);
591591
$this->sigNode = $nodeset->item($pos);
592+
$query = "./secdsig:SignedInfo";
593+
$nodeset = $xpath->query($query, $this->sigNode);
594+
if ($nodeset->length > 1) {
595+
throw new Exception("Invalid structure - Too many SignedInfo elements found");
596+
}
592597
return $this->sigNode;
593598
}
594599
return null;
@@ -675,6 +680,9 @@ public function canonicalizeSignedInfo() {
675680
$xpath = $this->getXPathObj();
676681
$query = "./secdsig:SignedInfo";
677682
$nodeset = $xpath->query($query, $this->sigNode);
683+
if ($nodeset->length > 1) {
684+
throw new Exception("Invalid structure - Too many SignedInfo elements found");
685+
}
678686
if ($signInfoNode = $nodeset->item(0)) {
679687
$query = "./secdsig:CanonicalizationMethod";
680688
$nodeset = $xpath->query($query, $signInfoNode);
@@ -790,7 +798,7 @@ public function processTransforms($refNode, $objData, $includeCommentNodes = tru
790798
if ($node->localName == 'XPath') {
791799
$arXPath = array();
792800
$arXPath['query'] = '(.//. | .//@* | .//namespace::*)['.$node->nodeValue.']';
793-
$arXpath['namespaces'] = array();
801+
$arXPath['namespaces'] = array();
794802
$nslist = $xpath->query('./namespace::*', $node);
795803
foreach ($nslist AS $nsnode) {
796804
if ($nsnode->localName != "xml") {
@@ -888,7 +896,7 @@ public function getRefIDs() {
888896
$refids = array();
889897

890898
$xpath = $this->getXPathObj();
891-
$query = "./secdsig:SignedInfo/secdsig:Reference";
899+
$query = "./secdsig:SignedInfo[1]/secdsig:Reference";
892900
$nodeset = $xpath->query($query, $this->sigNode);
893901
if ($nodeset->length == 0) {
894902
throw new Exception("Reference nodes not found");
@@ -905,7 +913,7 @@ public function validateReference() {
905913
$this->sigNode->parentNode->removeChild($this->sigNode);
906914
}
907915
$xpath = $this->getXPathObj();
908-
$query = "./secdsig:SignedInfo/secdsig:Reference";
916+
$query = "./secdsig:SignedInfo[1]/secdsig:Reference";
909917
$nodeset = $xpath->query($query, $this->sigNode);
910918
if ($nodeset->length == 0) {
911919
throw new Exception("Reference nodes not found");

lib/Saml2/AuthnRequest.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,15 +111,20 @@ public function __construct(OneLogin_Saml2_Settings $settings, $forceAuthn = fal
111111
$authnComparison = $security['requestedAuthnContextComparison'];
112112
}
113113

114+
$authnComparisonAttr = '';
115+
if (!empty($authnComparison)) {
116+
$authnComparisonAttr = sprintf('Comparison="%s"', $authnComparison);
117+
}
118+
114119
if ($security['requestedAuthnContext'] === true) {
115120
$requestedAuthnStr = <<<REQUESTEDAUTHN
116121
117-
<samlp:RequestedAuthnContext Comparison="$authnComparison">
122+
<samlp:RequestedAuthnContext $authnComparisonAttr>
118123
<saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml:AuthnContextClassRef>
119124
</samlp:RequestedAuthnContext>
120125
REQUESTEDAUTHN;
121126
} else {
122-
$requestedAuthnStr .= " <samlp:RequestedAuthnContext Comparison=\"$authnComparison\">\n";
127+
$requestedAuthnStr .= " <samlp:RequestedAuthnContext $authnComparisonAttr>\n";
123128
foreach ($security['requestedAuthnContext'] as $contextValue) {
124129
$requestedAuthnStr .= " <saml:AuthnContextClassRef>".$contextValue."</saml:AuthnContextClassRef>\n";
125130
}

lib/Saml2/IdPMetadataParser.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,9 +142,12 @@ public static function parseXML($xml, $entityId = null, $desiredNameIdFormat = n
142142
if ($sloNodes->length > 0) {
143143
$metadataInfo['idp']['singleLogoutService'] = array(
144144
'url' => $sloNodes->item(0)->getAttribute('Location'),
145-
'responseUrl' => $sloNodes->item(0)->getAttribute('ResponseLocation'),
146145
'binding' => $sloNodes->item(0)->getAttribute('Binding')
147146
);
147+
148+
if ($sloNodes->item(0)->hasAttribute('ResponseLocation')) {
149+
$metadataInfo['idp']['singleLogoutService']['responseUrl'] = $sloNodes->item(0)->getAttribute('ResponseLocation');
150+
}
148151
}
149152

150153
$keyDescriptorCertSigningNodes = OneLogin_Saml2_Utils::query($dom, './md:KeyDescriptor[not(contains(@use, "encryption"))]/ds:KeyInfo/ds:X509Data/ds:X509Certificate', $idpDescriptor);

lib/Saml2/LogoutRequest.php

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,7 @@ public function isValid($retrieveParametersFromServer = false)
340340
$security = $this->_settings->getSecurityData();
341341

342342
if ($security['wantXMLValidation']) {
343-
$res = OneLogin_Saml2_Utils::validateXML($dom, 'saml-schema-protocol-2.0.xsd', $this->_settings->isDebugActive());
343+
$res = OneLogin_Saml2_Utils::validateXML($dom, 'saml-schema-protocol-2.0.xsd', $this->_settings->isDebugActive(), $this->_settings->getSchemasPath());
344344
if (!$res instanceof DOMDocument) {
345345
throw new OneLogin_Saml2_ValidationError(
346346
"Invalid SAML Logout Request. Not match the saml-schema-protocol-2.0.xsd",
@@ -365,11 +365,15 @@ public function isValid($retrieveParametersFromServer = false)
365365
// Check destination
366366
if ($dom->documentElement->hasAttribute('Destination')) {
367367
$destination = $dom->documentElement->getAttribute('Destination');
368-
if (!empty($destination) && strpos($destination, $currentURL) === false) {
369-
throw new OneLogin_Saml2_ValidationError(
370-
"The LogoutRequest was received at $currentURL instead of $destination",
371-
OneLogin_Saml2_ValidationError::WRONG_DESTINATION
372-
);
368+
if (!empty($destination) && strpos($destination, $currentURL) !== 0) {
369+
$currentURLNoRouted = OneLogin_Saml2_Utils::getSelfURLNoQuery();
370+
371+
if (strpos($destination, $currentURLNoRouted) !== 0) {
372+
throw new OneLogin_Saml2_ValidationError(
373+
"The LogoutRequest was received at $currentURL instead of $destination",
374+
OneLogin_Saml2_ValidationError::WRONG_DESTINATION
375+
);
376+
}
373377
}
374378
}
375379

lib/Saml2/LogoutResponse.php

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ public function isValid($requestId = null, $retrieveParametersFromServer = false
127127
$security = $this->_settings->getSecurityData();
128128

129129
if ($security['wantXMLValidation']) {
130-
$res = OneLogin_Saml2_Utils::validateXML($this->document, 'saml-schema-protocol-2.0.xsd', $this->_settings->isDebugActive());
130+
$res = OneLogin_Saml2_Utils::validateXML($this->document, 'saml-schema-protocol-2.0.xsd', $this->_settings->isDebugActive(), $this->_settings->getSchemasPath());
131131
if (!$res instanceof DOMDocument) {
132132
throw new OneLogin_Saml2_ValidationError(
133133
"Invalid SAML Logout Response. Not match the saml-schema-protocol-2.0.xsd",
@@ -161,11 +161,15 @@ public function isValid($requestId = null, $retrieveParametersFromServer = false
161161
// Check destination
162162
if ($this->document->documentElement->hasAttribute('Destination')) {
163163
$destination = $this->document->documentElement->getAttribute('Destination');
164-
if (!empty($destination) && strpos($destination, $currentURL) === false) {
165-
throw new OneLogin_Saml2_ValidationError(
166-
"The LogoutResponse was received at $currentURL instead of $destination",
167-
OneLogin_Saml2_ValidationError::WRONG_DESTINATION
168-
);
164+
if (!empty($destination) && strpos($destination, $currentURL) !== 0) {
165+
$currentURLNoRouted = OneLogin_Saml2_Utils::getSelfURLNoQuery();
166+
167+
if (strpos($destination, $currentURLNoRouted) !== 0) {
168+
throw new OneLogin_Saml2_ValidationError(
169+
"The LogoutResponse was received at $currentURL instead of $destination",
170+
OneLogin_Saml2_ValidationError::WRONG_DESTINATION
171+
);
172+
}
169173
}
170174
}
171175

0 commit comments

Comments
 (0)