Minimal Changes Vulnerability Testing: Why Less is More in Security

Published: 27 Jan 2025

A lot of people, when testing for security issues, jump right into "full exploitation" mode. They might flip multiple parameters in a JWT token, change the username, and add a different algorithm—all in a single shot. While this feels powerful, it often creates unnecessary confusion and can lead to missed vulnerabilities or misleading results.

Instead, the principle of minimal changes is about only modifying the parameters that are absolutely necessary to test a specific idea. When everything else stays the same, you reduce the chance of something unrelated interfering with your test. This article explores why this methodical approach is so effective, using JWT manipulation and file path traversal as illustrations.

The Problem with "Full Exploitation"

When you decide to test multiple aspects of a vulnerability at once—like changing a username, an algorithm, and a signature in a JWT—you end up not knowing which change triggered the outcome. If the test fails, was it because the username doesn’t exist? Or did the application detect the suspicious algorithm? Or maybe the removed signature was the issue. Conversely, if it succeeds, you won’t know exactly which change made it possible.

Worse yet, external factors often come into play. Maybe that new username you tried is deactivated or protected by two-factor authentication. You could easily dismiss a valid bug simply because the external system behavior overshadowed your actual test. This risk of false negatives (thinking a bug doesn’t exist when it actually does) is one of the biggest downsides to the "full exploitation" approach.

The Case for Minimal, Incremental Changes

By focusing on the smallest possible alteration, you can zero in on the vulnerability itself without risking side effects from unrelated features or validation checks. This approach also helps you learn how the application behaves in response to incremental, low-risk modifications before escalating to more invasive payloads.

When each step is small, you have a clear link between action and result. You make a simple change, observe how the application responds, and draw a direct conclusion about whether you might be onto something. If you get a clue that the application is tolerating your small tweak, you can then push further—still one step at a time.

Example: JWT None Algorithm
Full Exploitation Gone Wrong

A common mistake when testing for the infamous None algorithm vulnerability in JWTs is to change everything at once. You might switch the username from test to admin, change the algorithm to None, and remove the signature in a single request. If it fails, was it because admin doesn’t exist? Because the system rejected the None algorithm? Or maybe there was another security control interfering.

Minimal Change in Action

Instead, focus on the parts tied directly to the vulnerability you want to test. Keep the username as test—something that already works. Then change the algorithm to None and remove the signature, and see if the application accepts the token. If it does, you’ve confirmed the vulnerability without worrying about any user-specific complications.

Example: File Path Traversal
Jumping to /etc/passwd

When you suspect a file path traversal flaw, it’s tempting to go straight for ../../../../etc/passwd. But this giant leap can trigger alarms, get blocked by intrusion detection systems, or fail due to path normalization you don’t fully understand yet. It might cause you to believe the vulnerability doesn’t exist, when in fact it’s just being thwarted by a security filter or extra validation.

Starting Small

A better approach is to try something like test/../test/1234 if you have access to /test/1234. This might not confirm a full traversal bug, but if it isn’t rejected, you learn that path components like ../ aren’t fully blocked. You can then build from there, maybe moving to another_directory/../test/1234 next. Each step tells you more about how the application handles paths, giving you a clearer idea of whether a more serious exploit will eventually work.

Conclusion

Whenever you’re testing for a particular vulnerability, ask yourself: "What’s the least amount of change I can make that would either prove or disprove this bug?" By taking small, deliberate steps, you reduce false negatives, keep your tests focused, and gather more precise information about how the application handles your input.

This technique not only boosts your efficiency but also eliminates the confusion caused by full-blown exploitation attempts. By taking small, deliberate steps, you build a deeper understanding of the application's behavior, resulting in more accurate results, uncovering vulnerabilities more reliably, and minimizing the risk of missing critical issues.

Photo of Louis Nyffenegger
Written by Louis Nyffenegger
Founder and CEO @PentesterLab