Skip Menu |

This queue is for tickets about the Net-SAML2 CPAN distribution.

Report information
The Basics
Id: 98837
Status: resolved
Priority: 0/
Queue: Net-SAML2

People
Owner: TIMLEGGE [...] cpan.org
Requestors: ysth [...] shiftboard.com
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: (no value)
Fixed in: 0.20



Subject: POST binding verifies using cert in response
Date: Fri, 12 Sep 2014 10:20:23 -0700
To: bug-Net-SAML2 [...] rt.cpan.org
From: Yitzchak Scott-Thoennes <ysth [...] shiftboard.com>
The Net::SAML2 synopsis says: my $post = Net::SAML2::Binding::POST->new; my $ret = $post->handle_response( $saml_response ); This works for me, except that it is using the X509 cert embedded in the response to verify the response signature, not the X509 cert I have from the IdP metadata. And there doesn't seem to be a way to provide the metadata cert. Trusting the response's cert makes verifying the signature meaningless from a security standpoint.
It's true that we verify the Assertion using the embedded certificate, but there's also a check in there for a trust path from that certificate back to the configured CA certificate. This means that only Assertions from IdPs which have certificates signed by the CA are accepted.
Just wanted to +1 the need for verifying the Response against the IDP cert metadata. handle_response does two things. 1. verify the SignedInfo XML data against the signature 2. verify that the certificate used to sign the assertion was issued by the cacert you know and trust. The problem is with #2. SAML doesn't require X509Data. In fact it doesn't require KeyInfo. This particular IDP i'm working with provides KeyInfo with the signature etc, but no X509Data, therefore no signing certificate. Without being able to verify the XML against the IDP certificate we received from the metadata, the module die's with the following: Crypt::OpenSSL::VerifyX509::verify: x509 is not of type Crypt::OpenSSL::X509 at This is because of the following: In handle_response (paraphrasing): my $x = Net::SAML2::XML::Sig->new({ x509 => 1 }) is called. Here we would want to pass in cert => from the idp to verify. Lacking that we call $x->verify... If your Response does not have X509Data provided, the subsequent validation attempt of signer_cert fails (signer_cert will be undef). - Mike On Fri Sep 12 13:26:49 2014, CHRISA wrote: Show quoted text
> It's true that we verify the Assertion using the embedded certificate, > but there's also a check in there for a trust path from that > certificate back to the configured CA certificate. > > This means that only Assertions from IdPs which have certificates > signed by the CA are accepted.
Ugh sorry end of the day: Here is handle_response (trimmed) sub handle_response { ... my $x = Net::SAML2::XML::Sig->new({ x509 => 1 }); my $ret = $x->verify($xml); die "signature check failed" unless $ret; # verify the signing certificate my $cert = $x->signer_cert; my $ca = Crypt::OpenSSL::VerifyX509->new($self->cacert); $ret = $ca->verify($cert); ... } $x->verify clears signer_cert. It only sets it after a successful verification of X509Data. Since no X509Data exists in the XML, $x->verify uses rsa to verify the signature (which works, but does not set signer_cert, it cant!) The next $ca->verify($cert) fails. ($cert is undef). On Tue Jan 06 17:40:15 2015, xmikew wrote: Show quoted text
> Just wanted to +1 the need for verifying the Response against the IDP > cert metadata. > > handle_response does two things. > > 1. verify the SignedInfo XML data against the signature > 2. verify that the certificate used to sign the assertion was issued > by the cacert you know and trust. > > The problem is with #2. > > SAML doesn't require X509Data. In fact it doesn't require KeyInfo. > This particular IDP i'm working with provides KeyInfo with the > signature etc, but no X509Data, therefore no signing certificate. > > Without being able to verify the XML against the IDP certificate we > received from the metadata, the module die's with the following: > > Crypt::OpenSSL::VerifyX509::verify: x509 is not of type > Crypt::OpenSSL::X509 at > > This is because of the following: > > In handle_response (paraphrasing): > my $x = Net::SAML2::XML::Sig->new({ x509 => 1 }) is called. Here we > would want to pass in cert => from the idp to verify. Lacking that we > call > > $x->verify... > > If your Response does not have X509Data provided, the subsequent > validation attempt of signer_cert fails (signer_cert will be undef). > > - Mike > > > On Fri Sep 12 13:26:49 2014, CHRISA wrote:
> > It's true that we verify the Assertion using the embedded > > certificate, > > but there's also a check in there for a trust path from that > > certificate back to the configured CA certificate. > > > > This means that only Assertions from IdPs which have certificates > > signed by the CA are accepted.
My Quick fix is for the POST.pm module to accept a cert option that I can provide the IDP cert to. If this exists, we verify it against our cacert. Otherwise, we see if signer_cert is there, and then use that. If neither exist, die with useful error. I'll send a pull request along to github for your review. Thanks, - Mike On Tue Jan 06 17:45:19 2015, xmikew wrote: Show quoted text
> Ugh sorry end of the day: > > Here is handle_response (trimmed) > > sub handle_response { > ... > my $x = Net::SAML2::XML::Sig->new({ x509 => 1 }); > my $ret = $x->verify($xml); > die "signature check failed" unless $ret; > > # verify the signing certificate > my $cert = $x->signer_cert; > my $ca = Crypt::OpenSSL::VerifyX509->new($self->cacert); > $ret = $ca->verify($cert); > ... > } > > $x->verify clears signer_cert. It only sets it after a successful > verification of X509Data. Since no X509Data exists in the XML, $x-
> >verify uses rsa to verify the signature (which works, but does not
> set signer_cert, it cant!) > > The next $ca->verify($cert) fails. ($cert is undef). > > On Tue Jan 06 17:40:15 2015, xmikew wrote:
> > Just wanted to +1 the need for verifying the Response against the IDP > > cert metadata. > > > > handle_response does two things. > > > > 1. verify the SignedInfo XML data against the signature > > 2. verify that the certificate used to sign the assertion was issued > > by the cacert you know and trust. > > > > The problem is with #2. > > > > SAML doesn't require X509Data. In fact it doesn't require KeyInfo. > > This particular IDP i'm working with provides KeyInfo with the > > signature etc, but no X509Data, therefore no signing certificate. > > > > Without being able to verify the XML against the IDP certificate we > > received from the metadata, the module die's with the following: > > > > Crypt::OpenSSL::VerifyX509::verify: x509 is not of type > > Crypt::OpenSSL::X509 at > > > > This is because of the following: > > > > In handle_response (paraphrasing): > > my $x = Net::SAML2::XML::Sig->new({ x509 => 1 }) is called. Here we > > would want to pass in cert => from the idp to verify. Lacking that we > > call > > > > $x->verify... > > > > If your Response does not have X509Data provided, the subsequent > > validation attempt of signer_cert fails (signer_cert will be undef). > > > > - Mike > > > > > > On Fri Sep 12 13:26:49 2014, CHRISA wrote:
> > > It's true that we verify the Assertion using the embedded > > > certificate, > > > but there's also a check in there for a trust path from that > > > certificate back to the configured CA certificate. > > > > > > This means that only Assertions from IdPs which have certificates > > > signed by the CA are accepted.
On Tue Jan 06 18:04:52 2015, xmikew wrote: Show quoted text
> My Quick fix is for the POST.pm module to accept a cert option that I > can provide the IDP cert to. If this exists, we verify it against our > cacert. Otherwise, we see if signer_cert is there, and then use that. > If neither exist, die with useful error. I'll send a pull request > along to github for your review. > > Thanks, > > - Mike > > On Tue Jan 06 17:45:19 2015, xmikew wrote:
> > Ugh sorry end of the day: > > > > Here is handle_response (trimmed) > > > > sub handle_response { > > ... > > my $x = Net::SAML2::XML::Sig->new({ x509 => 1 }); > > my $ret = $x->verify($xml); > > die "signature check failed" unless $ret; > > > > # verify the signing certificate > > my $cert = $x->signer_cert; > > my $ca = Crypt::OpenSSL::VerifyX509->new($self->cacert); > > $ret = $ca->verify($cert); > > ... > > } > > > > $x->verify clears signer_cert. It only sets it after a successful > > verification of X509Data. Since no X509Data exists in the XML, $x-
> > > verify uses rsa to verify the signature (which works, but does not
> > set signer_cert, it cant!) > > > > The next $ca->verify($cert) fails. ($cert is undef). > > > > On Tue Jan 06 17:40:15 2015, xmikew wrote:
> > > Just wanted to +1 the need for verifying the Response against the > > > IDP > > > cert metadata. > > > > > > handle_response does two things. > > > > > > 1. verify the SignedInfo XML data against the signature > > > 2. verify that the certificate used to sign the assertion was > > > issued > > > by the cacert you know and trust. > > > > > > The problem is with #2. > > > > > > SAML doesn't require X509Data. In fact it doesn't require KeyInfo. > > > This particular IDP i'm working with provides KeyInfo with the > > > signature etc, but no X509Data, therefore no signing certificate. > > > > > > Without being able to verify the XML against the IDP certificate we > > > received from the metadata, the module die's with the following: > > > > > > Crypt::OpenSSL::VerifyX509::verify: x509 is not of type > > > Crypt::OpenSSL::X509 at > > > > > > This is because of the following: > > > > > > In handle_response (paraphrasing): > > > my $x = Net::SAML2::XML::Sig->new({ x509 => 1 }) is called. Here we > > > would want to pass in cert => from the idp to verify. Lacking that > > > we > > > call > > > > > > $x->verify... > > > > > > If your Response does not have X509Data provided, the subsequent > > > validation attempt of signer_cert fails (signer_cert will be > > > undef). > > > > > > - Mike > > > > > > > > > On Fri Sep 12 13:26:49 2014, CHRISA wrote:
> > > > It's true that we verify the Assertion using the embedded > > > > certificate, > > > > but there's also a check in there for a trust path from that > > > > certificate back to the configured CA certificate. > > > > > > > > This means that only Assertions from IdPs which have certificates > > > > signed by the CA are accepted.
Logged at https://github.com/timlegge/perl-Net-SAML2/issues/11 so it is noted in the next release. That is a fork of xmikew repo that includes the fix