Welcome back, my aspiring cyberwarriors!
In the digital battleground of cybersecurity, web application fuzzing stands as a critical technique for uncovering vulnerabilities and developing exploits. This practical guide equips aspiring cyber warriors with the knowledge to wield BASH scripting as a powerful weapon in creating custom fuzzing tools.
Fuzzing is a dynamic analysis technique used in software testing and security assessments. It involves providing invalid, unexpected, or random data as inputs to a web application to uncover vulnerabilities, bugs, or unexpected behavior.
The concept of fuzzing originated in 1988 when Professor Barton Miller at the University of Wisconsin-Madison observed system crashes during a thunderstorm. This observation led to the development of the first fuzzing tools. Since then, fuzzing has evolved into a sophisticated and essential technique in modern cybersecurity.
At its heart, fuzzing explores the vast input space of a program. However, for complex applications, this space is astronomically large, making exhaustive testing an impossible mission. This limitation ties into the halting problem in computer science, proving we can never guarantee we've uncovered all bugs through fuzzing alone. As a result, our fuzzing operations rely on probabilistic methods, aiming to generate inputs with a high likelihood of triggering bugs or vulnerabilities within a reasonable time frame.
Types of Fuzzing
Fuzzing can be categorized into several types based on the knowledge and approach used:
Black-box:
No knowledge of the application's internals.
Inputs generated without considering the application's structure or logic.
Can uncover unexpected vulnerabilities but may be less efficient.
White-box:
Uses knowledge of the program's internals to guide input generation.
Can include source code analysis, control flow graphs, and symbolic execution.
Achieves higher code coverage but requires more resources and expertise.
Grey-box:
A hybrid approach using some, but not complete, knowledge of the system.
Often involves instrumenting the target program to gather runtime information.
Balances efficiency and depth of testing.
Generation-based:
Creates test cases from scratch based on input specifications.
Effective for complex input formats but requires a deep understanding of the input structure .
Mutation-based:
Starts with valid inputs and applies various transformations.
Practical and can quickly generate a large number of test cases.
Evolutionary:
Uses concepts from genetic algorithms to evolve test cases over time.
Can be particularly effective for finding deep, hard-to-reach bugs.
Web fuzzing with BASH offers several compelling advantages. One of the primary benefits is its simplicity - BASH scripts are relatively easy to write and understand, making them accessible to aspiring cyber warriors of varying skill levels.
Another significant advantage of using BASH for web fuzzing is its seamless system integration. BASH scripts can easily interact with other command-line tools and system utilities.
However, it's important to consider the limitations of using BASH for web fuzzing:
It can be slow on large-scale projects.
Implementing advanced fuzzing techniques can be challenging.
But in general, building a web fuzzer with BASH is perfect for getting your feet wet in cyber ops.
Get Started With Writing Code
Now that we understand the theoretical foundations and the pros and cons of BASH-based fuzzing, let's dive into creating our own web application fuzzer. We'll begin with a shebang to designate our script as a BASH executable, followed by a short mission briefing. Then, we'll create an interactive prompt to acquire our target domain.
I used 'read -p' to show the prompt and get input together. I also added a line to visually separate this block of the program.
The heart of our fuzzer is the payload generator. It creates various test cases to probe the application. So let's start with it, create a dedicated function for this purpose and write base payloads for different types of vulnerabilities (SQL Injection, XSS, Command Injection, etc.).
Next, create a “mutate_payload” function that takes a payload as an argument and prints a random version of mutated versions of it. The mutations include appending characters (', <script>, /, \n), and performing ROT13 encoding on the payload.
${#mutations[@]} - gives the length of the array “mutations”.
RANDOM % ${#mutations[@]} -computes a random index within the range of indices of the “mutations” array. The % (modulo) operator ensures that the generated random number is within valid bounds (from 0 up to “mutations” array length – 1).
For generating mutated payloads we need that each payload from “base_payloads” is passed to “mutate_payload”.
${base_payloads[@]}" - is used to access all elements of an array at once.
After generating base and mutated payloads, they can be combined into the payloads array. To check if everything is working correctly, I will also add another loop to display all payloads.
Request Handling
After creating payloads, we can proceed to writing a function for sending requests.
Here's what it does:
It takes four things: where we're hitting (URL), what we're sending (payload), how we're sending it (method), and any special instructions (headers).
Depending on the method (GET, POST, PUT, DELETE), it uses a different curl command to send our request.
-s - silent mode.
-w "%{http_code}" - we're asking curl to send the HTTP status code back to us.
Here are used “case” and “esac” to create a multi-way branch statement, similar to a switch statement in Python or other programming languages. “Esac” is simply “case” spelled backward and is used to terminate the case statement.
3. It grabs the response from the website and tries to separate the status code from the actual message.
if [[ ${#response} -ge 3 ]]; then - this condition checks if the length of the response is 3 or more characters.
http_code - assigns these last 3 characters (presumably the HTTP status code like 200, 404, etc.) to the variable.
body=${response:0:${#response}-3} - assigns the substring (everything except the last 3 characters of response) to the variable.
4. If the response is too short, it sets a default code and warns us.
5. Finally, it passes everything it learned to another function to figure out what it all means.
Response Analysis
The response analyzer examines the server's response for potential vulnerabilities.
At first, we will analyze the status codes:
It scans the response for words like "error" or "exception". If it finds them, it alerts us and shows a snippet. Then it looks for specific signs of vulnerabilities:
Next, we will create a function that will call all the necessary previous ones. The main point here is that we first generate the payloads, and then make a request for each method and for each payload.
After that, I'll add an input to get the required methods and write them to an array. I'll also add a general header.
Summary
Fuzzing is often the first step in exploit development. By fuzzing the application, we can where and how it breaks. The "break" is often a place where we can exploit.
In this tutorial, we introduce you to web application fuzzing using Bash, tailored for aspiring cyber warriors. It covers the basics of what fuzzing is, why Bash can be a good tool for learning, and provides a step-by-step explanation of building a simple fuzzer.