What is fuzz testing? A plain-English explanation

What is fuzz testing? A plain-English explanation

Every piece of software has been tested. The engineers who wrote it checked that it handles the inputs it was designed for. They tested the correct paths, the error conditions they anticipated, the edge cases they thought to write down.

Attackers do not read the test plan. They send inputs the engineers never anticipated: malformed, unexpected, out of specification, structurally wrong but superficially plausible. And that is precisely where the exploitable vulnerabilities tend to live.

Fuzz testing is the discipline of discovering those vulnerabilities systematically, before attackers find them. This guide explains what fuzz testing is, how it works, what it finds, and where it belongs in a modern security programme.

What Is Fuzz Testing?

Fuzz testing, also called fuzzing, is a software testing technique that involves sending malformed, unexpected or edge-case inputs to a system and observing what happens.

The technique does not check that the system handles correct inputs correctly. That is what functional testing is for. Fuzz testing checks what happens when the system receives inputs it was not designed to handle. Does it crash? Does it hang? Does it expose sensitive data? Does it enter a state that an attacker could exploit?

The name comes from an early experiment at the University of Wisconsin in 1988, where Barton Miller connected a noisy phone line to a UNIX terminal and noticed that the random characters produced by the line noise caused utilities to crash. The insight was simple: programs that crashed on random input had bugs. A systematic way of generating that random input could find those bugs reliably.

Modern fuzz testing is considerably more sophisticated than random noise. Protocol-aware fuzzers understand the structure of the inputs they generate. They produce test cases that are close enough to valid to get past basic parsing, but different enough in specific ways to expose handling bugs in the application logic behind it. That combination, structural plausibility with targeted malformation, is what makes fuzz testing effective at finding real vulnerabilities rather than just triggering obvious syntax rejections.


What Fuzz Testing Finds That Other Methods Miss

Most security testing methods are hypothesis-driven. A penetration tester looks for vulnerability classes they know exist. A static analyser checks for coding patterns associated with known bugs. Both are valuable and both share the same limitation: they find what the tester thought to look for.

Fuzz testing is not hypothesis-driven. It does not start with a theory about what might be wrong. It generates large numbers of varied inputs and watches for anything the system was not designed to produce in response. The findings it surfaces are, by definition, things the development team did not anticipate.

In practice, fuzz testing is particularly effective at finding the following vulnerability types.

Buffer overflows occur when a program writes more data to a buffer than it was allocated, overwriting adjacent memory. They remain one of the most exploited vulnerability classes in protocol implementations and are reliably surfaced by fuzz testing with unexpectedly long field values.

Input validation failures occur when malformed data reaches application logic that assumes the input has already been validated. Fuzz testing finds these by generating inputs that are syntactically plausible but contain invalid field combinations, out-of-range values, or sequences the specification forbids.

Protocol parsing errors occur at the boundary between message structure and application behaviour. A message that is structurally almost valid but contains a specific flaw can cause undefined behaviour in the parser, producing crashes or incorrect state transitions that a correctly-formed message would never trigger.

State machine bugs occur when an unexpected sequence of messages puts a system into an unintended state. Protocol fuzzers that model the target protocol’s state machine can generate message sequences that explore these transitions systematically, finding states the developer never tested.

Denial of service conditions arise when certain inputs cause the target to consume excessive resources, hang indefinitely, or crash entirely. In operational technology environments, where availability is a safety-critical requirement, these findings can be as significant as remote code execution vulnerabilities.

Authentication bypasses occasionally surface when the specific combination of malformed inputs required to trigger them would never appear in a human-written test case. Fuzz testing, operating at scale across the input space, finds these combinations where manual testing never would.


How Fuzz Testing Works

A fuzz test has three components: a fuzzer that generates inputs, a target that receives them, and a monitoring layer that observes the target’s response. Each component matters, and the quality of the output depends on how well each is implemented.

Input generation

This is where fuzzers differ most substantially from one another. The simplest approach is mutation-based: take a valid input and modify it randomly. This is straightforward to implement and requires no knowledge of the target protocol or format. The limitation is that most mutated inputs are rejected at the parsing stage before reaching any interesting application logic, which limits the depth of coverage.

Generation-based fuzzers build inputs from a formal model of the target protocol. They understand the structure of a valid message and produce inputs that are structurally plausible but contain deliberate flaws: invalid field values, unexpected lengths, illegal sequences, or value combinations the specification prohibits. These inputs are far more likely to reach deep application logic and expose real vulnerabilities.

Coverage-guided fuzzers instrument the target application and track which code paths each input exercises. Inputs that reach previously unexplored code are retained and mutated further. This approach is highly efficient at mapping the state space of a complex application, but it requires source code access or binary instrumentation, which is not always possible with commercial devices or proprietary systems.

Execution

The fuzzer sends its generated inputs to the target. For protocol testing, this means establishing a connection and sending traffic that conforms to the protocol’s framing while containing deliberate flaws in the payload. The target processes the input and returns a response, or fails to respond at all.

Speed is a practical constraint. Effective fuzz testing runs thousands or millions of test cases. The execution layer needs to manage connection state across a large number of iterations, handle targets that crash or hang, and maintain a consistent testing pace without overwhelming the target or introducing artificial timing artefacts.

Monitoring

Monitoring determines what the fuzz test actually finds. Without it, only outright crashes are detected. With good monitoring, the scope extends to unexpected error responses, timing anomalies, protocol state violations, memory growth, and behavioural deviations that indicate a problem even when the system does not crash.

For protocol testing in OT and embedded environments, monitoring the response to each input is as important as the input itself. A device that silently discards a malformed packet tells a different security story from one that crashes, one that returns an error message containing internal state information, and one that accepts the malformed input and processes it as though it were valid.


Types of Fuzz Testing

Not all fuzzers work the same way. Understanding the main approaches clarifies where each is useful and where its limitations lie.

Mutation-based fuzzing takes valid, known-good inputs and applies random modifications. It requires no protocol knowledge and is simple to configure. The limitation is shallow coverage: most mutated inputs are rejected at the parsing stage before reaching the application logic where vulnerabilities live.

Generation-based fuzzing constructs inputs from a formal model of the target protocol. It requires protocol knowledge upfront but produces inputs that exercise much deeper logic. This is the appropriate approach for testing structured binary protocols, industrial formats, and telecom signalling where the interesting vulnerabilities are buried in implementation detail.

Coverage-guided fuzzing uses instrumentation feedback from the target to steer input generation toward unexplored code paths. It is highly efficient for complex applications with source code access but is impractical for black-box testing of commercial devices or proprietary systems.

Black-box fuzzing tests the target with no knowledge of its internals, monitoring only external behaviour. This is the most practical approach for commercial off-the-shelf devices, third-party components, and systems where source code is unavailable.

Protocol-aware fuzzing is a specialised form of generation-based, black-box fuzzing designed specifically for communication protocols. It understands protocol structure, models valid message formats, and generates inputs that are syntactically plausible but semantically flawed. This is the approach ProtoCrawler uses.


Fuzz Testing for Protocols and Embedded Systems

Most publicly available fuzzing tools were built for web applications and file format parsers. They generate HTTP requests, HTML documents, or image files. This is appropriate for that environment, but it leaves a significant gap when the target is an industrial protocol, a telecom signalling stack, or firmware in an embedded device.

These environments communicate over structured binary protocols: Modbus, DNP3, IEC 61850, IEC 60870-5-104, GTP, DLMS COSEM, MQTT, and many others. A generic fuzzer that sends random bytes will be rejected immediately by the protocol stack’s framing layer, before any interesting application logic is reached. To test what matters, the fuzzer needs to understand the protocol structure.

Protocol-aware fuzz testing generates inputs that respect the framing of the target protocol but introduce specific flaws in the payload: invalid field values, malformed authentication sequences, unexpected message lengths, or illegal state transitions. These inputs are structurally plausible enough to pass the framing checks and reach the application code that handles them, which is where the security-relevant behaviour lives.

The consequences of finding vulnerabilities in these environments differ from those in web applications. A buffer overflow in a web application is serious. A buffer overflow in a SCADA protocol implementation or a smart meter can affect physical infrastructure, disrupt energy distribution, or create a denial of service condition in safety-critical equipment. The stakes make thorough testing more important, not less.


Where Fuzz Testing Sits in the Security Process

Fuzz testing is not a replacement for other forms of security assurance. It is a complement. Understanding the relationship between methods helps organisations allocate effort appropriately.

Static analysis examines source code without executing it. It finds coding errors and known bad patterns quickly and early in the development lifecycle. It cannot find vulnerabilities that only emerge from specific runtime behaviour or protocol interaction.

Penetration testing is hypothesis-driven: a skilled tester investigates vulnerability classes they know or suspect are present, explores the system intelligently, and assesses exploitability. It produces high-quality, contextualised findings but covers a small fraction of the possible input space.

Fuzz testing is wide, automated, and input-space-oriented. It does not reason about vulnerabilities the way a human tester does, but it exercises an enormous number of input combinations that no human tester would generate manually. The two approaches complement each other directly: fuzz testing finds the bugs, penetration testing assesses whether and how they can be exploited.

For organisations operating under compliance frameworks such as IEC 62443, fuzz testing is not optional at higher security levels. IEC 62443-4-1 Practice 6 places explicit security testing obligations on product vendors, including vulnerability testing, fuzz testing, and penetration testing, with defined tester independence requirements at SL 3 and SL 4. For a full explanation of how IEC 62443 testing requirements are structured, see the IEC 62443 compliance hub.


What Good Fuzz Testing Output Looks Like

A fuzz test run that produces no findings is not automatically a success. It may mean the fuzzer reached the interesting code and the implementation is genuinely robust. It may also mean the fuzzer never reached the interesting code, that the monitoring was too coarse to catch subtle failures, or that the input generation was not sophisticated enough to produce the inputs needed. Understanding what good output looks like helps teams interpret results correctly.

Each finding should include the specific input that triggered it so it can be reproduced exactly. The observed behaviour needs to be recorded precisely: crash with address, hang at a specific operation, unexpected response content, error message with internal state information, or protocol state violation. Severity classification based on the nature of the finding and its potential for exploitation gives the security team a prioritised list to work from.

Coverage metrics show which parts of the protocol or device were exercised, giving confidence that the test reached the code that matters and not just the surface layer. A reproducible test corpus can be re-run after code changes to confirm that fixes hold and that new changes have not introduced regressions.

For organisations with compliance obligations, the output also needs to serve as audit evidence. Reports that identify the protocol tested, the test methodology used, the scope of the test, the findings with severity classifications, and the remediation status satisfy the audit evidence requirements of IEC 62443-4-1 Practice 6 and support the documentation framework that compliance programmes depend on.


How ProtoCrawler Approaches Fuzz Testing

ProtoCrawler is CyTAL’s automated protocol fuzz testing platform, built specifically for OT, IoT, telecoms and embedded environments. It ships with protocol models covering more than 100 protocols including Modbus, DNP3, IEC 61850, IEC 60870-5-104, GTP-C, GTP-U, DLMS COSEM, MQTT, SS7, Diameter, and the GBCS protocols used in UK smart metering.

Each test uses generation-based, protocol-aware fuzzing to produce inputs that are structurally plausible but contain targeted flaws chosen to exercise the application logic most likely to contain security-relevant behaviour. The monitoring layer tracks crashes, unexpected responses, protocol state deviations, timing anomalies, and error output that reveals internal state.

Because ProtoCrawler operates as a black-box test against a running target, it does not require source code access or binary instrumentation. It tests commercial devices, third-party components, and systems where source code is unavailable, which covers most real-world OT and IoT environments.

The reporting output is structured to support compliance use cases. For IEC 62443-4-1 and 4-2, ProtoCrawler produces test evidence that maps findings to specific standard requirements, including the SVV-3 vulnerability testing evidence that Practice 6 requires. Reports include scope documentation, test configurations, scored findings, and coverage traceability.

To explore the full list of supported protocols, see the protocol models page. For the full set of IEC 62443 guides, visit the IEC 62443 compliance hub.


Common Questions About Fuzz Testing

Is fuzz testing safe to run against production systems?

It depends on the fuzzer and how it is configured. Generic fuzzers can cause crashes, hangs and unexpected state changes that disrupt live systems. Protocol-aware fuzzers include configurable traffic rates and safe test modes designed for test environments or controlled production windows. The default recommendation is to run fuzz testing in a staging environment that mirrors production, then use the specific test cases that found vulnerabilities for targeted verification in production if needed.

How long does a fuzz testing run take?

A focused test against a single protocol can complete in hours. A full assessment covering multiple protocols and device states typically takes several days. Continuous integration use cases run targeted fuzz tests against specific changed components and complete in minutes. The right scope depends on the security level target, the compliance requirements in play, and how frequently the product changes.

Does fuzz testing require specialist expertise to configure?

Traditional fuzzing tools required deep expertise to configure test cases, interpret results, and distinguish meaningful findings from noise. ProtoCrawler is designed to be used by security engineers who understand the target protocols but do not need fuzzing expertise. Test generation, execution scheduling, and result classification are handled by the platform. The engineer’s job is to define scope, review findings, and drive remediation.

What happens when a vulnerability is found?

Each finding is logged with the reproducing input, the observed behaviour, and a severity classification. The security team reviews findings, confirms which represent genuine vulnerabilities rather than benign anomalies, and tracks them through to remediation. ProtoCrawler’s reports provide the traceability needed for both internal defect tracking and external audit evidence requirements.


Ready to find the vulnerabilities your existing tests are missing? Book a demo to see how ProtoCrawler applies fuzz testing to the protocols your systems depend on.

Book a demo

This field is for validation purposes and should be left unchanged.

Book Your Free Demo

Complete the form and we will confirm your slot within 1 business day.

By submitting, you agree to Cytal storing your information to arrange this demo. We will never share your details with third parties. Privacy Policy. Unsubscribe at any time.