Understanding Attack Surface
Introduction
Attack Surface is one of those terms that is often used, often defined, but rarely well understood. Rather than reinventing the wheel, let’s start by finding a reasonably authoritative definition of the term “Attack Surface”:
"The set of points on the boundary of a system, a system component, or an environment where an attacker can try to enter, cause an effect on, or extract data from, that system, component, or environment."
NIST Special Publication 800-53 Revision 5:
"Security and Privacy Controls for Information Systems and Organizations"
https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-53r5.pdf
While this is reasonably precise, it is one of those definitions that seems to raise more questions that it answers; it doesn’t paint a very clear conceptual picture of exactly what an attack surface is.
Let’s go back to some fundamentals and see if we can shed a bit of light on what this is actually trying to say.
Back to Basics
If you look through the multitude of layers of abstraction, and past the mountains of obscure terminology, computers are fundamentally very simple things: they execute a series of instructions that operate on data.
As an attacker, my goal is equally simple: find a way to feed data into the computer that will result in those instructions doing what I want them to do, rather than doing what they are supposed to do. This fundamentally captures the way in which an attacker is able to interact with, and try to manipulate, a computer system.
This also gives us a neat, concise and accurate definition of an attack surface:
"The aggregate set of all the instructions in a system that an attacker is able to feed data in to"
As a definition this is fine. As an explanation it is just as bad as the previous NIST definition of attack surface. In general, most people don't see a computer system as a set of instructions operating on data flows so using this language still doesn't effectively convey the concept we are trying to get across.
Lost in Abstraction
Computer scientists, systems architects and software engineers all live in a world full of abstractions. We like to split things into neat little boxes with well defined names and join boxes together using well defined lines. These abstractions are deliberately chosen to enable us to deconstruct complex systems so we can hide complexity inside little named boxes. We don't talk about sets of instructions, we talk about processes, hosts, ports, components and APIs.
It seems natural therefore, to try and define a system's attack surface in terms of the abstractions that everybody knows and understands, this is where things tend to go wrong. The problem is that those abstractions were designed precisely to break down complexity into neat layers. Where as, almost by definition, our attack surface passes straight through those layers of abstraction. Entities like ports and APIs are closer to conduits through which data can be sent and counting conduits gives no sense of the real attack surface that can be reached through those conduits.
Worse yet, using those abstractions will tend to give a misleading impression about the 'shape' of an attack surface. Abstractions tend to be neat little boxes where as most real-world systems have a relatively high level of data permeability, i.e. attacker data can flow through multiple layers of multiple systems.
Our fundamental problem is that the real shape of an attack surface just doesn't align very well with the language and terminology used by the people who need to understand it, this creates something of a communications barrier between security engineers and the rest of the world.
Lovely Crinkly Edges
To really understand attack surface, think about it as being at the edge of all attacker controlled data that flows into, and through, your organisation.
This is not a simple straight line, it is conceptually much closer to a complex river system with multiple forks and tributaries and a multitude of ways of interacting with the 'land' that surrounds it.
This data-centric way of looking at attack surface works well in almost any context. If you are looking at user-mode data flows passing through a kernel driver, tracing data flows through a web app looking for XSS issues, or trying to understand the highest areas of exposure for a multinational company, the same basic mind set and approach to attack surface analysis will help to guide you in the right direction.
Vulnerabilities such as Log4j (https://nvd.nist.gov/vuln/detail/CVE-2021-44228) highlight the importance of understanding the true extent of potentially malicious data flows; even a vulnerability that is nominally a long way from your Internet perimeter can form a critical part of your real Internet attack surface.
So, the next time you hear the term “attack surface”, instead of thinking about a simple conceptual boundary; think of data flowing from an attacker and passing through, and interacting with, the various components in your system.
If you look at attack surface in this way you will have a much better grasp of your real attack surface, and you will be in a better position to make informed choices when it comes to managing and reducing risk across your organisation.