was not the problem. Instead, the problem was that the authorization and access controls were lacking. User Biff should not have been able to view or edit user Abe’s private
posts, no matter how he arrived at the particular URL.
This is a real issue that resurfaces occasionally with all sorts of document management
software, of which blogs are only a small example. Private data stored on a publicly
accessible service needs to be well-protected.
While blogging may appear a trivial example, it is common for systems to assign sequential IDs, yet not explicitly verify the permissions for a particular document or record. Often developers will assume that if no link is presented to a user, then the user
cannot find a particular protected record. Finding these protected or confidential records can be as simple as incrementing IDs repeatedly. Private blog posts may seem
low risk, but this vulnerability has led to leaked internal memos and other corporate
information. Often, IDs will be encoded so that they might appear random. They are
not usually truly random; see the recipes in Chapter 4 for details on deciphering unrecognized identifiers.
This WordPress example was a real bug. We are grateful to the folks at WordPress who
see the benefit of publishing bugs to the public. You can check this bug report yourself
This technique might seem trivial, too. Surely the expensive, professional, automated
web testing software would check something like this, right? Again, the answer may
surprise you. Straightforward testing like incrementing identifiers is trivial to do with
a tool like cURL, but is not done routinely by the automated scanners. Adding it to
your manual or automated tests will improve your security coverage, even if you routinely use a commercial security scanner.
9.5 Predicting Credentials
Many systems assign user credentials, such as usernames, passwords, or status, rather
than allowing the user to specify their own. While this is often a security measure to
ensure the strength of user credentials, it can backfire if those credentials are easily
predictable. Learn how to avoid predictable credentials so that your software does not
fall prey to the same trap.
This recipe only applies if your application automatically assigns initial passwords or
contains batch scripts to do so during initial deployment.
184 | Chapter 9: Seeking Design Flaws
Identify how usernames, passwords, or other credentials will be established. Will usernames be publicly displayed? If so, is it at the discretion of the user or via a directory?
If usernames are generally accessible, understand that they may be harvested via a
script. An attacker will be able to attain a partial or complete list of users if the usernames are displayed at the user’s discretion or in a directory, respectively.
Are passwords assigned in bulk? How are they generated?
If passwords are assigned by incrementing a value or are generated using the username
itself, there is a high chance that the password will be easily guessable. If passwords are
assigned randomly, see Recipe 9.6 to learn more about tests related to randomness.
Table 9-1 shows credentials being issued in bulk. Each email address and password is
generated and sent to the corresponding user.
Table 9-1. Default passwords based on email
Although Table 9-1 shows that distinct passwords are assigned to each user, anyone
who has been issued a password can see the implicit pattern. If George could infer
Alice’s email address and if he knew she had not changed her password yet, he could
easily take over her account.
While the example given seems rather basic, it is vitally important not to fall prey to
this vulnerability. Predictable user IDs allow attackers to gain a foothold on your application. Even though the administrator’s account may not be at risk this way, gaining
any legitimate account is often a very significant first step for an attacker.
Another important point is to consider how easily a person can request and receive
multiple accounts. Many web applications require a distinct email address for each
account. A user who owns her own domain, however, can typically have an infinite
number of email addresses in her domain. Thus, she could request many different
accounts and receive many different initial passwords, in order to infer the pattern.
One thing we’ve learned is that every time you assume a bug or vulnerability is just
common sense or that nobody would make that mistake, it will pop up again. So while
the above example might seem like a trivial test, be sure to double-check. For instance,
a company we worked with was celebrating a successful merger. They modified a
shopping cart system to allow each and every employee to select one of many free gifts.
9.5 Predicting Credentials | 185
To ensure that each employee only signed up for one free gift, accounts were created
and assigned in bulk. Every single account was created and mailed out with “password”
as the password.
9.6 Finding Random Numbers in Your Application
Many aspects of an application’s security will depend on the fact that an adversary
cannot reasonably guess certain values in the system. You probably depend on encryption keys, session IDs, and possibly nonces. In this recipe we just try to identify
where random values are being used in your application. In Recipe 9.7 we will try to
determine how fit they are for our purpose.
What Is Randomness?
A full, mathematical definition of randomness is beyond the scope of this book, but we
need a brief definition suitable for our purposes. A series of statistically random numbers has the property that there are no recognizable patterns or regularities in it. Frequently we are looking for things to be unpredictable in our application, and we turn
to random numbers to achieve that unpredictability.
There are times when we need an aspect of our application to be unpredictable in a
way that is supported by mathematics. That is,we want it to be so statistically improbable for an attacker to guess some aspect of the system that we consider it impossible
for all practical purposes. Session IDs are the most obvious part of our system that
ought to be random (i.e., unrelated to anything) and unguessable.
There are other things that might need to be unguessable, but are not necessarily random at all. Think about passwords: we frequently obscure them in ways that need to
be repeatable, but not guessable. We use hashes on a password (e.g., MD5, SHA-1) to
turn it predictably from something that must be secret into something unrecognizable,
but uniquely and undeniably related to the original secret.
Some aspects of our system can be predictable without compromising our security.
Generally speaking, you should favor strong randomness and unpredictability in all
aspects that are exposed to would-be attackers.
If you have surveyed your application by spidering it (e.g., Recipe 6.1), then you have
a starting inventory of pages to look at. Rather than examine those pages one by one,
you should also consider which actions in your application are most important to perform correctly (e.g., those involving money, data access, system integrity). Look at the
parameters exposed in the body of the page, in the cookie, and in the URL. In particular,
186 | Chapter 9: Seeking Design Flaws
In the body of the page
• Session state like ASP.NET’s __VIEWSTATE in hidden form fields (e.g., type="hidden" name="__VIEWSTATE" value="AAA...">).
• Unique identifiers, like customer IDs, guest IDs, etc., also in hidden form fields.
In the cookie
• Session IDs. They almost always have some variation or abbreviation of the
• Unique identifiers for the visitor, their account, or other resources.
• Representations of things like roles, groups, or privileges (e.g., groupid=8).
• Indicators of workflow. Things like status=5 or state=6 or next=225.
In the URL
• Session IDs, as in the cookie.
• Unique identifiers, also as you might find in the cookie.
• Representations of things like resources (e.g., msgid=83342).
• Indicators of workflow. Things like authorized=1.
Remember that many of these things will be encoded with Base 64, URL encoding, or
both. See the recipes in Chapter 4 to learn about recognizing and deciphering encoded
Many applications that use randomness don’t really rely on the unpredictability of that
randomness. Most uses of randomness do not have the same impact as they might in
an online poker game, for instance. If your online chat program randomly picks an
avatar for participants, does it really matter that a certain avatar is chosen with a little
more likelihood than another?
Once you have found the random numbers in your application, you need to ask questions to help you determine whether the randomness and unpredictability is vital to
your application. You might ask:
• How much damage could a user do if he knew how to predict this random
• How upset would one user be if she found out that someone could predict the next
• How bad would it be if two documents (users, resources, links, etc.) were assigned
the same value?
9.6 Finding Random Numbers in Your Application | 187