Hacker News new | past | comments | ask | show | jobs | submit login
You need multiple SAML IDP signing keys (stackallocated.com)
64 points by hansnielsen 3 months ago | hide | past | favorite | 45 comments

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.

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.

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.

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

Since the encryption is typically asymmetric, you do have per-SP encryption keys, since you encrypt using the key specified in the metadata provided by the SP. On the other hand, the SP verifies the signature using the public key specified in the metadata of the IdP. So, to have per-SP signing key, you need per-SP metadata, which is an additional complication.

It sounds like it would be really useful to have a public IdP that does this, kind of like badssl.com is a demo site for showing how various misconfigurations present in browsers.

>I even scared one vendor so badly just explaining that I was going to do this that we never heard from them again.

You can't drop that and walk away without naming them.

Reading this article tonight then BC I wanted to know how to size up such integrations at very early stage. Thanks for the pro-tip!

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.

> 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.

It's not a scenario you're likely to see in the case of corporate SAML use, where people generally don't care about anonymity to SPs, but it happens fairly routinely in Shibboleth environments with multilateral federation. In that scenario, you often want proof of the user's membership of the organization (or their role within it) and the ability to track a specific user of the service, without being able to expose who the user is. In that case, your user identifier attribute ends up being an opaque ID, which is either random or a hash of username+SP-entity-ID+salt. Using that approach, there's no way to tell if user X at journal site A is the same as user Y at journal site B without the assistance of the IdP owner.

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?

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.

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?

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".

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.)

More to the point - while signing certs are part of the SAML spec (and your IdP can choose to use a different one for each SP), looking at attributes in the Assertion and making decisions based off of them is one-off for every SP - a few do this, but they each do it differently than the last.

Use a custom scheme because odds are if you're doing things right you'll need a good revocation story which SAML doesn't provide.

The use case in the article is enterprise login to a bunch of services. It's hard enough to get them to do SSO, you can't seriously suggest you're going to get them to implement bespoke schemes?

I don't disagree with you that it's a crappy situation. A lot of SaaS providers ldap/AD sync so you can authz off of groups and do automatic revocation. Enterprise integrations suck exactly because of these kinds of things. while adding a key per SP may get you further down the authz path, it doesn't solve the revocation part and also doesn't provide a way to do more advanced authz -- The natural evolution of an app that will authorize access to a subset of users will be to add roles for users, giving them different privileges, and then you're back to a custom authz protocol.

It is common for an IdP to apply specific policies and controls dependent on which service provider the user is authenticating to. The IdP is specifically saying "user X has access to application Y." That is why the Audience is a (required) component of a SAML Response.

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

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.

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.

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.

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

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.

Is there a way to audit that kind of misconfiguration?

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

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.

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 :)

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?

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 :))

It's a theoretical yes but a practical no, because the amount of people on this planet who understand SAML enough and want to work on it and are available for auditing, is damn close to zero, if not zero.

This is not an outlandish thing to ask of your security auditor _for your own app_. (It's something we do for clients.)

The challenging part is doing it for vendorsec, when you are vetting _other apps_. The timelines that stakeholders (other people in the company who want to use the app) are willing to accept are like, a week, and even if you somehow had a SAML testing praxis at the ready that enumerates all of the problems SAML has historically had, there's a lot more to test than just the SAML bits.

So: in summary: I don't think that number is anywhere near zero, though sure, it's not huge. The hard part is failures being silent and being in parties you don't control.

Okta has a single signing key with no ability to set per-provider keys, only Azure AD does the right thing out of the box per the article.

I believe the article is wrong, eg, see: https://developer.okta.com/docs/guides/updating-saml-cert/ge...

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

I replied on Twitter, but I'll include it here as well:

> Correction: SimpleSAMLphp easily allows for per-SP signing certs/keys. See https://simplesamlphp.org/docs/stable/simplesamlphp-referenc... (signature.certificate and signature.privatekey)

According to the article there is currently nothing that can be done for simplesamlphp. You could open an issue on Github for it.

> SimpleSAMLphp’s IDP supports key rollover but no way to specify unique keys for individual service providers. There might be a way to configure it but if so, it’s not mentioned in the documention and I’m not excited to try it myself.

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.

It's been great for us. Run fine for years, I have docker set to build a new image anytime there's a security issue. Still... I've looked hard at keycloak, but it misses a key feature for us, that you can't store an TOTP secret in LDAP. That's important for us so we just have one code to use, that gets us into SAML, Radius or some of the other stuff we have.

> 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 ?

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.

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 :)

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.

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact