In general, fuzzing means to try many inputs, well-formed or otherwise, in an application, protocol or other interaction with a computer, that it might trigger an unexpected behavior. Web fuzzing in particular is an automated, computerized technique to find bugs and vulnerabilities within a computer system. If you think protecting your site is a matter of simply blocking the most common types of malicious requests, think again. Read on for more.
A fairly common situation is a website providing the ability to search, add, and remove information from a database. But introducing this kind of feature demands great care in how you set up and access that database.
Let’s look at
has a movie database, and
allows us to search for a given title:
It looks like the site takes the user’s input
POST request, then
searches the database for that request,
and finally prints back the result in table form.
We can tell it’s a
since there is nothing in the
URL that hints
(consider that the huge
wouldn’t be there in a real app).
Let’s check that using the
OWASP ZAP proxy.
Indeed, we can see and confirm that the request is
POSTrequest when you search for a movie
POST /sqli_6.php HTTP/1.1 Host: localhost User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.9) Gecko/20100101 Goanna/3.4 Firefox/52.9 PaleMoon/27.7.2 ... Content-Length: 24 title=the&action=search
Now we can intercept this request using
title=the bit above,
the by some
For example, if we change it to:
Iron Man' OR 1=1;
1=1 is always true,
making the overall condition true,
we should get all entries in the table.
But it doesn’t happen. We get an error:
Error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '%'' at line 1
Well, at least now we know for sure
they are using
because we can see it in the error message.
There are infinitely many strings
(sequences of characters)
we could try to use
in order to complete the unknown
the server is asking from the database.
What if we could try a bunch of them, at the same time, automatically?
Well, that’s what ``fuzzing'' is all about.
There are other kinds of fuzzing: desktop application fuzzing using command-line or graphical interfaces (testing combinations of buttons, inputs, etc.), protocol fuzzing, file format fuzzing, and more.
In this article
we will focus only on web application fuzzing which is
the semi-automated, pseudo-random manipulation
URLs, forms, user-generated content, requests, etc.
We may tackle other kinds of fuzzing in future articles.
For a given fuzzing attack,
the most comprehensive and sure-fire way to succeed
would be to try every possible input.
if we’re fuzzing an input string,
we should try every possible string,
beginning with the empty string.
This is due to the fact
that sometimes programs have unexpected reactions
to odd input,
like the bug found in
Mac OS last year,
where you could log in as root
by pressing the login button enough times
(see CVE-2017-13872 for more info).
`try everything'' approach is not really feasible or practical:
the space complexity of such an attempt
would be enormous.
Thus we must bound the so-called
'explorable solutions space'.
This is usually achieved by limiting
the input attempts to values
that have a statistically higher probability
of triggering a bug.
These are known as 'fuzz vectors'.
In our case,
they would be `SQL queries.
Some examples from
' OR 1=1;-- ' OR 'a'='a %22`OR`isnull%281%2F0%29+%2F* Admin' OR ' '%20SELECT%20*%20FROM%20INFORMATION_SCHEMA.TABLES-- HAVING 1=1-- ' OR username LIKE char(37); ' ; DROP TABLE temp -- GRANT CONNECT TO name; GRANT RESOURCE TO name;
Your fuzzer of choice will probably provide
a healthy dose of fuzz vectors,
as does ours,
OWASP ZAP Fuzzer.
All we need to do is
select the string we want to fuzz,
invoke the fuzzer,
select the 'payloads', i.e. the fuzz vectors, and
run the fuzzer.
ZAP includes several of those by default;
we will use the
SQL injection vector
are marked with the state ``reflected'' in the list:
SQLinjections in fuzz attacks
Here we see a fuzz attack is only as good as its payloads or fuzz vectors. Only the most trivial injections succeeded, i.e. the ones of the form
whatever' OR (something truthy)
which simply show all entries in the table
When fuzzing, this is both
a blessing and a curse.
Usually, they don’t, but occasionally
the simplest injections
reveal unexpected outcomes,
and when they do,
they are real surprises
such as the
Apple bug mentioned above.
With information about the app
and the database structure,
we can inject more effective queries.
For example, suppose
you’ve found out that
there is another table called
and we want to see what’s in there.
If we try to inject the following query:
%'; SELECT * FROM users;
we get an error, because the database management system does not allow query concatenation.
If we try with
%' UNION SELECT * FROM users;#
we still get an error, because the tables don’t match in size.
Suppose, for the sake of the example, that we also know (or guess) the names of the columns and select the most interesting ones:
%' UNION SELECT id, login, password, email, secret, activated, admin FROM users;#
Then we get the most of the users' info (passwords are hashed, but can be recovered).
By itself fuzz testing
cannot replace human expertise in the equation but
it adds an important additional point of view.
As seen in the
Mac OS example,
its greatest weakness can be
a potential source of great surprises.
We have merely glimpsed the
tip of the iceberg here,
but hope you find
this short introduction helpful.