
You need multiple SAML IDP signing keys - hansnielsen
https://www.stackallocated.com/blog/2020/saml-idp-no-shared-keys/
======
lr
Two ways I deal with this:

1) Insist on encryption of the SAMLResponse (that way, the SP has to do it
correctly, or they'll have no idea who is accessing the app) 2) If they won't
do encryption, I test exactly what they are talking about in this article

To test, I have my own IdP set up, and I either do IdP-initiated sign-on or
spoof the IdP URL using /etc/hosts on my localhost and try to log into the app
with a signed SAMLResponse using a key the SP doesn't know about. If it works,
I immediately tell our CISO. I even scared one vendor so badly just explaining
that I was going to do this that we never heard from them again.

~~~
johnmaguire2013
Encrypting the Response only ensures that the SP knows how to decrypt it - not
that they are verifying other fields, like the Audience field.

If you use a separate encryption key for each SP, then great - but you could
just as easily use a separate signing key, as the article suggests, and far
more SPs support this.

Of course, it is still possible the SP does not validate the signature at all,
or does so erroneously.

~~~
lvh
SAML typically uses RSA-OAEP or RSA-PKCSv15 for KEM. You usually get the cert
from that from the SP (since otherwise you hold the private key), so I'm not
sure how that goes sideways. The SP might still use the same encryption keys
for each peer, but that should be fine.

You're right that per-SP pairs are still the right answer and for the reason
you point out: much wider support.

~~~
johnmaguire2013
Duh - of course. Good point. As long as each SP has its own encryption key,
this would be a valid solution assuming SP support.

------
matthewaveryusa
If your IDP is providing identity, does it matter who the audience is?
presumably the contract is "if this blob is signed with this certificate, then
the identity encoded in the blob is the user's identity" because the SP was
configured to only trust a certain certificate for identity.

What the article is saying is a bit nuanced in that the IDP can theoretically
provide a different user identity for each service, but in reality, does that
really happen? Seems like if you're doing that you're starting to mix
authentication with authorization.

The picture in the article that says that the idp provides the answer to
"login to cat", "log in to to payroll" is wrong imho. the IDP is providing the
answer "username is X", and that's it.

~~~
lvh
The article provides examples of the IDP providing using different _IDP
identities_ but I couldn't find an example of it suggesting different _user
identities_.

The problem is the SAML assertion is effectively a bearer token, which is fine
if it's specific to a service, and not fine if it can be replayed. If you want
to unmix "authentication and authorization" as you put it, you're going to
need a way to bind that credential further. You can either do that with some
unspecified scheme that nobody implements, or you can do that by just using
per-SP keys as the article suggests.

What do you propose we do instead?

~~~
NovemberWhiskey
If your SP supports it, you use SAML attribute assertions to model group/role
memberships and only grant access to users in the appropriate groups.

Or you have your IDP (say ADFS) only permit issuance for authorization
requests which are appropriate, again by reference to (say) AD group
memberships.

If your SP doesn't even validate the audience for the assertions, then you're
definitely going to be in a bad place - but the question there is "how do I
limit the damage this braindead SAML implementation can do to my enterprise
and how do I make sure I never buy software broken like this again?" rather
than a screed suggesting authentication and authorization are the same thing.

~~~
lvh
Are you suggesting that there are "levels of broken" here, where an
application that doesn't do audience validation will almost certainly screw up
group membership assertion?

~~~
NovemberWhiskey
My experience is that many vendors will happily say "SAML 2.0 integration for
SSO" when they mean only that they can pick a username out of an identity
assertion. I personally haven't seen one which mismanages audience validation.

Above and beyond that, support is tremendously variable. Ability to do JIT
provisioning/re-provisioning with user roles etc mapped to attribute
assertions is something like nirvana and about as commonly realized.

"SSO once you have pre-provisioned the user out-of-band via our application-
specific API" is more common (bonus marks for SCIM). Also "SSO assuming you
can provide access to an LDAP server where we can look the user up".

~~~
lvh
OK, but my question was specific. You appeared to hint that anything that
doesn't do audience validation is so horribly broken that it's unusable.
That's not only very different from my experience (audience confusion, and
particularly domain confusion bugs are super common), and I think there's a
good reason for that. If your integration claims to be able to consume group
assertions but it doesn't, that will be immediately visible to anyone trying
the integration. If you screw up audience validation, no-one will notice until
they perform a very specific test that the vast majority of vendorsec programs
will never test for, and a good chunk of the ones that do will have signed a
contract that prevents them from testing or at least publishing findings.

(Completely agreed that the vast majority of SSO integrations only let the IdP
assert identities, not group memberships.)

------
okabat
As a SAML service provider, what's the easiest way to tell if my
implementation has this problem?

I'm guessing I should: 1) Go into my Okta dev account, create a 2nd "okta app"
(SP instance) pointing at my hosted application, which should create a new
entity ID 2) Start an IDP-initiated login attempt from this 2nd okta app, and
verify I get an audience mismatch error

~~~
johnmaguire2013
This should work as long as your chosen Entity ID for your second Okta app
doesn't match the actual Entity ID of your SP.

------
recursive
I don't understand why all security assertions must always be provided to each
service provider.

This is probably something fundamental I'm misunderstanding about SAML, but
when you authenticate for a particular SP, why does the response automatically
include every assertion? It seems too obvious to just configure which claims
are issued for each service provider. That wouldn't require any special crypto
stuff.

~~~
tptacek
It doesn't. The concern is that all of these assertions are captured by the
browsers, who are given custody of the signed assertion as part of the SAML
POST flow. The attack being contemplated here is that you have a SAML IDP
configured for Cat Sharing Application and for Internal Admin Application; a
attacker's browser holds onto the Cat Sharing Application assertion and feeds
it to the Internal Admin Application, and, because SP SAML libraries are
terrible, the Internal Admin Application honors it.

~~~
mc32
One hopes the Oktas of the world had this figured out and this is more a
problem when you host your own IDP.

~~~
someone13
This is part of what makes this class of bug so bad; it's not something you
can "fix" at the IDP without doing exactly this. The issue occurs when a
Service Provider (SP) is misconfigured, and in many cases the IDP doesn't
actually get any sort of feedback that would let them detect the issue.

~~~
mc32
Is there a way to audit that kind of misconfiguration?

~~~
tptacek
Yes, tediously, with auditors who understand SAML and the (very informal)
literature on SAML attacks. Hence, the concern.

~~~
wutwutwutwut
Wouldn't it be enough to enter an invalid audience when configuring the IDP?
If the audience is ignored the sign-in flow still allows you to log on and you
know the SP is broken.

~~~
lvh
Sure, but two reasons that's not quite optimal and you might not want to do
that in practice:

1\. This tells you the SP is broken; just using individual keys means that
doesn't matter anymore if the SP is broken or not. Individual keys is in your
control, fixing the SP much less likely so. And you can just set up a practice
of doing it for everything and now it's one less thing to test for.

2\. That still requires a bit of testing that's somewhat annoying to set up,
which most vendorsec practices don't have time for. It's also only one of
dozens of things you need to test for. Ignoring audiences is super common, but
a more subtle problem is that you can sign a valid SAML assertion _for the
wrong domain_, and now you can sign in as a competitor's staff.

As you hint at, having an SP that'll just self-service accept any random
metadata.xml at least gives you a fighting chance :)

~~~
wutwutwutwut
My question was more related to it being tedious. And now you say it requires
a bit of testing which is annoying to set up. Isn't testing this just a matter
of changing the audience field to something incorrect and try to sign on? This
should take like 2 minutes?

~~~
lvh
If you just change the audience field, the signature will be invalid, so it
might tell you the SP won't accept a bad signature, but it doesn't tell you
that the SP would accept a correct-signature-for-wrong-audience assertion. And
now we've explored two states in that very big tedium space I mentioned; it
still doesn't tell you anything about e.g. canonicalization bugs or cross-
domain bugs. Those are much harder to test, because they require your IdP to
sign specifically crafted assertions malicious, so you can't test them with
your standard Okta install or whatever.

So, sure: you can test this one specific bug by replaying an assertion for a
different SP. Or you can make your IdP use new key pairs every time and then
you're definitionally immune to the entire bug class forever with every SP.
Even if replaying the SP takes 2 minutes, getting the tester to a place where
they can exploit it takes way longer for most companies, so it's much more
effective to just eliminate entire classes of bugs via policy.

TL;DR: you're right (modulo the amount of time) for this particular bug, but
why bother? And if you're going to bother testing, why test for this one
specific bug that's cheaper to avoid a different way? (I can think of a reason
to test; but then the tedium comes in :))

------
amaccuish
Hmm. I use simplesamlphp. What would be the easiest thing to change to?

~~~
cosarara
I implemented simplesamlphp idp two weeks ago, seeing we are a PHP shop it was
the obvious choice. Somewhat rethinking that decision now, wondering the same
thing.

~~~
porjo
> seeing we are a PHP shop it was the obvious choice

A Google search for 'php saml' has php-saml as the top result. I'm curious to
know why you chose simplesamlphp over php-saml ?

~~~
johnmaguire2013
php-saml is a toolkit for making your application a service provider (i.e.
able to accept Responses/Assertions from IdPs) so that users can single sign-
on to your application.

SimpleSAMLphp is a framework/application for creating your own SAMl IdP (i.e.
able to send Responses/Assertions to service providers) so that your users
(e.g. in an enterprise) can login once and then single sign-on to the rest of
your applications.

------
trhway
sounds like an idea of a mix of the better parts of SAML and Kerberos (with
the result being kind of fixed Kerberos where SP would store a public key to
trust instead of its own private). Of course one may end up with the result
being the mix of the worst parts ("Twins" movie comes to mind by association
:)

~~~
barryrandall
SAML is close to what you’d get if you tried to port Kerberos to web
technologies. Unfortunately, there are more shitty SAML implementations than
Kerberos ones.

