The vulnerabilities you hear about aren’t really the problem much of the time.
I don’t want to dismiss the OWASP Top 10, because that’s what started the focus on Application Security. And that’s important - it really is. That said, we are kinda past that now, and while there are applications that harbor the flaws described in the Top 10, and many of the vulnerabilities described in the Top 10 that matter, the way that list is derived is not relevant to the way the world works anymore. If you dig into the data that makes up the list, you’ll find that 98% of it is unexploited static analysis findings. Anyone who has spent time with static analysis will assure you that the only way static analysis if workable in a development environment is with triage. And I’m sure you have guessed by now how much application owner triage goes into these results: 0%. These findings might be legit, but they are probably not exploitable.
What’s number one on the top ten? Injection. I agree, injection sucks. Anytime you can make an application run some code that the developer didn’t intend to run, you gonna have a bad day.
In reality? It’s a unicorn these days. SQL injection, command injection, browser injection (which is explicitly a separate entry in the Top 10), doesn’t matter, vulnerability analysts just don’t find exploitable versions that much. 99.4% of the injections vulnerabilities cited in the data that makes up the Top 10 are from static analysis. Did they break in? No, it was just possible. Was there a mitigating factor - the fabled Security Onion? We’ll never know.
“OK, Bill, what ARE the Top 10 then?”
I don’t know. I’m an N=1 case, so I can just speak for me, and what I read. That said, seems like a lot of people are using social engineering to get access to things.
“But Bill, that’s not an application security problem!”
Actually, it is. About a third of common application security vulnerabilities can be exploited with a social networking attack, and yet that’s the third we most frequently dismiss because it’s hard to demo during a BlackHat demonstration. And guess what? Those are the vulnerabilities I see most frequently.
But it isn’t vulnerabilities that are the problem. It is the bugs. Let’s look at the bugs. We are always talking about the outcomes, not the causes, but here I want to talk about causes. We can talk about the outcomes later. Let’s look at a breakdown:
- Out of date components: By far the biggest one I see is jQuery, which is arguably a big deal. Mostly that is a DOM XSS problem, or info disclosure, and often the application isn’t using the feature that is exposed. That said, there are a lot of holes here. It is VERY hard to test all of the DOM XSS possibilities. It’s far easier to just get rid of the sources and sinks.
- Cross Site Request Forgery: CSRF is a very complicated vulnerability with a very complicated exploit that has the simplest fix ever, and I have no idea why the fix isn’t part of every framework on the planet. We have a session cookie already. This is the problem. If we also have a session variable in the form post, the session can’t be forged (unless there is XSS). Bang. Done. Why don’t we all do this? Well, multihoming makes it hard, that’s for sure for starters, but I’ll have more on this later.
- Vertical privilege escalation: The problem with VPE is that it requires some existing knowledge of the application. In a 100% custom written application, that isn’t likely, aside from an insider attack. The thing is, there aren’t that many 100% custom written applications. Most projects start SOMEWHERE that is known. The authorization system is understood (along with weaknesses) or the framework has known page URLs (like WordPress) or something of the sort. If the attacker knows where they are going and the authorization isn’t perfect, people can get to the administrator pages.
- Unpatched servers: So I probably don’t need to say Equifax but … Equifax. Seriously, if the Struts flaw doesn’t convince you that actively exploited flaws in your framework aren’t a risk, then nothing will. When your vendor - open source or otherwise - tells you that you need to patch right now, you need to patch right now. Not after your test cycle. Not when management gives the OK. Right now. I’m a dev, I know it doesn’t work like that, but it has to, and soon. This is getting bad.
- Horizontal privilege escalation: When a developer keeps important account information somewhere that an attacker can edit it, and that information is used to decide what an attacker is looking at, they might be able to look at things they shouldn’t see. Appropriate authorization solves this problem but it is very hard to do right, It’s a lot better to not give the user a chance to change this value at all. Insecure Direct Object Reference is the flaw in question, and it’s still out there.
- Lack of Input Validation: A positive security model is a requirement for every application that faces the internet (and really internal ones as well, but that’s another topic). Every time you can, you should be checking the input against all of the possible inputs. Can it not be negative? Is it? Reject it. Is there a list? Is the input on it? No? Reject it. Is it a free text field? Fine. Use the HTMLEncoder by OWASP. Everyone (myself included) needed to do a better job looking for flaws in the validation of inputs, and removing them.
- Weird stuff: There is so much weird stuff. I got an application to give me account details because of a malformed USER AGENT. Found the user’s role tacked onto the session ID in Base 64. Discovered an application that parsed a word document - including a call the the template at a random IP on the internet - in order to allow editing. From there to here, from here to there, funny things are everywhere. If you find yourself thinking “Hey, that’s a weird neat compelling way to solve that problem” look for something simpler. Complexity is the enemy of security.
I should probably talk about mobile. The biggest thing that developers need to understand about mobile is that the compiled app is not invulnerable to being analyzed. Don’t put anything in there that you wouldn’t want the user to have. API keys, private encryption keys, and paths to functions the user shouldn’t have are three of the most common. Just the other night someone stole the keys to send alerts from an app and sent random messages to all 100,000 users. At 3AM. I was not amused.
Anyway, this is just my take. Again, I am not ripping on the Top 10, I love the Top 10. It’s just useful to get the perspective from other-than-static-analysis companies. Manual dynamic analysis has its place. So in that spirit, I’d like to take you on a tour of how I go about performing vulnerability analysis - looking for the bugs that I have listed here. I’m no expert BUT I do it every day, so you might be able to glean something interesting out of my stories.