What is it and why should I care?
Reducing the attack surface of an application or system means reducing the ways that you can interact with the application, and may involve reducing the functionality the application provides.
To most business folks, this sounds very, very bad. However, at its’ core, it’s really just a matter of simplifying the system. This is a really *good* thing to the business. Rarely do you find anything that people genuinely enjoy using that is complex. The best designs are simple, and that benefits us in this case from a security perspective.
What does this simplification look like? My favorite example is the difference between Google’s standard and advanced searches. It’s likely that 99.9% of people don’t need the advanced search features. Imagine if google removed that page – that greatly simplifies the “search” application they build. It reduces the application footprint, saves them money (dev, support, etc) and gives their customers a better experience – what could be better? (Note: I’m simplifying this case as google’s standard search does allow advanced operators, but you get the idea.)
Most developers I’ve worked with (myself included) have the tendency to a) want to build lots of cool stuff, and b) be poor designers. This results in designs that are larger than necessary in that they encompass more code than planned (feature creep). It also results in an often unpleasant user experience. By being ruthless in removing non-required functionality, and simplifying what is required, the user experience is enhanced along with security, not to mention the bottom line – time and money.
What should I do about it?
Saying you should remove features/functionality and simplify is a bit vague, I realize. I’d like to offer a few examples of common situations where you might be able to have some impact on your applications for the better.
1. Dead Code
Every modern IDE has a “dead code” detector. If you don’t use an IDE, tons of open source “code quality” tools have this feature as well. Use it. If you’re not using code, remove it. If you comment out code, but keep it in the code-base, stop. Remove it. Heck, you can get it back through your version control if you ever really need it.
As much as you can you should also remove code that is “dead” because it’s not enabled via configuration. This may not always hold depending on the specific circumstance, but if you don’t have a need for a feature, don’t have it in your code base.
Dead code doesn’t get looked at or dealt with as closely as “live” code, so that makes it even worse from a security perspective, as there are likely to be lingering issues that aren’t dealt with because “no one is using that”.
2. Copied code
Everybody’s done it. You’ve taken code from an old project and used it in a new one. You’ve taken an example from the web and plugged it into your app. It may have done more than you needed, even way more. What have you done? You’ve added extra code that has be maintained, debugged, supported, tuned, secured, etc. This is a bad idea. It’s fine to use others’ (assuming they’re ok with it) code, but don’t add a bunch of stuff you don’t need.
3. Extra features
It’s undoubtedly great to wow your customer. In my opinion, adding unplanned features is usually not the best way to do that. Usually, giving them the absolute best version of what they need is much better for both you and them. It’s the idea of doing a few things well as opposed to lots of things just OK. Adding in extra features is a common thing for developers to do, often because they saw some cool thing somewhere and thought “hey – that’d be cool here”. Again, adding extra features means extra code, and that’s more to do, and takes away from the quality of what you actually need to do.
4. Extra code – 3rd party libraries
3rd party libraries are great. They are core to most any development done today. They enable us to create more functional apps quicker. However, they also put into your application TONS of functionality and features you may not have planned on being there, and that you probably don’t know exist. I would venture a guess that most J2EE apps I see probably include hundreds, if not thousands, of times more code in 3rd party libraries than in the code written for the application. That’s great from the perspective of “I didn’t have to write this”, but could mean danger when it comes to securing your application with those frameworks. From a security perspective, it doesn’t help that most of these libraries are there to have things just work instead of having secure defaults. I’m not saying frameworks are bad; I’m saying you need to know their capabilities well, and have a plan for dealing with them from the security perspective.
5. Extra services enabled
This is particularly common with 3rd party applications, but can be true for custom apps as well. What happens is an application is built in a generic way, and then sold/used by several groups or companies to solve different problems or similar problems for different users, etc. The functionality in the app is the sum total of what all the customers need. You as an individual customer might only need 30% of the overall functionality, but you have 100% enabled. That’s a problem. The better apps give you a simple way to disable features you’re not using, and a simple way to verify it’s actually turned off. Use these features. It’s always better to have to do an update to enable a feature than to have to tell your boss you were hacked using a feature that wasn’t even needed.
The above represents just a handful of ideas on how to reduce attack surface in your application. They all really boil down to simplify, simplify, simplify. It helps your application be better, and thankfully helps your security be better as well. Next time you have a bug-hunting session, try some of these ideas out. Also add comments if you have more/better ideas.