The other day we were giving developers security training around server side request forgery (SSRF). We see this all of the time now (see this great and detailed post by our team on SSRF in Real Life). It can be shockingly damaging. In any case, during the training the developers brought up a very interesting area where it was obvious that Zero Trust had provided a false sense of security so we wanted to write about that here. We'll start with some background, then get to the story and our conclusion.
As a quick aside, when I was at Trustwave (2008-2012) prior to founding Jemurai, someone came up with the catchy slogan that makes for the play on words (and company name) in this section:
Security begins with trustLeader
Let's start by trying to talk about Zero Trust in a simplified way. Beyond being a marketing term that gets used in some places that it shouldn't (just search for Zero Trust and see which security companies AREN'T talking about it!), it generally seems to apply to a few things working together:
The result is that at a network level, I can control at a very fine grained level, the things that can connect to each other. I can allow Matt to connect to this server but not that one. I can allow this server to connect to that one. Part of the idea is that you no longer have these subnets where everything within can talk to everything else within, on the contrary every single connection is specifically managed and allowed or disallowed. It can all be managed via an API and at a network layer it is very difficult to compromise. Cool tools we've used that relate to Zero Trust include CloudFlare (cloudflared), Tailscale, Teleport, StrongDM, etc. (We are not intending to endorse a tool here, just giving some examples)
We should probably start by saying, these tools are cool and the idea behind all of this is solid.
The problem is, they are network tools, not AppSec tools. Let's talk about that more.
Well, it does when the network flow doesn't follow the path created with the Zero Trust tools. But a ton of application security vulnerabilities piggy back on existing connections to existing servers that are allowed and expected.
Let's look at a few common specific examples:
Now, Server Side Request Forgery (SSRF) is an interesting hybrid example because whether Zero Trust helps us or not depends on where we're forging the request to go to.
To put this another way, if we are forging a request to the AWS MetaData Service (eg. http://169.254.169.254/latest/meta-data/) and the Zero Trust setup of our environment doesn't allow the intermediate EC2 Instance to talk to this service, then Zero Trust has effectively prevented this SSRF attack.
However, if we use SSRF to attack something else that the application is already using, say a credential store or another micro-service, then the connection is generally allowed by Zero Trust and there is no reason that we are more secure from this attack based on our use of Zero Trust.
Getting back to the narrative part of this post, the inspiration for the whole thing was a moment when developers at the client asked us during training: "wait, could you use SSRF to attack CredHub or the Service Registry"?
If you're not familiar with CredHub (as we weren't) you might have had to do some digging to find the answer. CredHub is basically a Spring ecosystem centralized credential storage service. It offers API's for storing, finding and retrieving credentials. Kind of like an App level HashiCorp Vault or AWS Secrets Manager. Literally at least some of the keys to the kingdom.
OK, that sounds like an interesting service to attack with SSRF.
Can I retrieve keys through the application via an SSRF vulnerability? We weren't sure so we looked into the documentation. Turns out CredHub offers two options for authenticating requests:
From reading the docs, it seems like as long as the intermediate server we're jumping through with our SSRF attack regularly uses CredHub and can EVER ask CredHub questions, then our SSRF attack can also ask those same questions. The two servers will confirm they trust each other. But in this case, their trust will be misplaced.
Which is why I would amend our fearless slogan creator's words to:
Security begins and ends with trustKonda
If you trust someone you shouldn't, you've lost your security! This is part of why I dislike the term Zero Trust. Because you really can't actually create Zero Trust, you can only create Network Zero Trust. Well and not even that, because what you're going to do is start building trust relationships anyway because a network with actual zero trust isn't a network!
The key takeaway from this story is that Zero Trust may not be an effective mitigation for SSRF.
We absolutely like the direction Zero Trust has been going and recommend solutions that simplify the Tunnel, ACL and AuthC approach we talked about above.
However, we need to be very aware of the places where SSRF happens. These seem to often include:
We also need to understand the boundaries of Zero Trust and application security. Rarely has Zero Trust played a significant role in mitigating the results of what we could do in a penetration test. We need to architect systems well and write secure code to do that.
Maybe the simplest way of all to explain this is that if you have code running in systems within the boundaries of a Zero Trust network, that code also has to be trusted to maintain its integrity in its interactions with the other resources in the network. Otherwise, your awesome Zero Trust network could be spilling data.