Over the years, our team has performed thousands of penetrations tests. In the first 15 minutes of a pen test there are a handful of issues that we often discover. These issues are simple to understand and they're easy to correct, but they're almost always there. They don’t require authentication, need minimal expertise to find, and aren't the focus of the OWASP Top 10.
HTTP Server Configuration
The findings that are easiest to correct exist within web server configurations, usually in the form of missing or incomplete header directives.
Everyone already knows that Transport Layer Security (TLS) encryption of sensitive services is a must, but the use of the HTTP Strict Transport Security (HSTS) header is widely overlooked. HSTS tells a browser that all future communication with a given domain must use TLS. With HSTS in place, a man-in-the-middle attacker cannot trick browsers into establishing unencrypted connections with your server. The use of HSTS only on select subdomains is often not as effective, so we recommend enforcing HTTPS across the entire domain. In order to further decrease the likelihood of man-in-the-middle attacks, especially during the first connection to a site, you should include your website in the list of HSTS-enabled sites preloaded with many browsers.
Encrypting the communications to and from the server is only the first step. Content from your server will pass through many other devices before reaching its destination. Some of these devices cache content to decrease network load and transit time. In order to prevent these devices from storing sensitive data, include cache-control header directives.
Login forms usually have input fields for both email addresses and passwords. It should be impossible to distinguish between an incorrect email and an incorrect password as the cause of a login failure.
If the login form reveals the reason for the credential failure, an attacker can use this to determine if an email address is registered with the site. This is useful if the attacker wishes to perform a social engineering attack, such as a phishing campaign, targeting a site's users. Attackers can purchase large lists of email addresses from information brokers, and they can then filter those lists through login forms that confirm if an address is registered. The process of filtering emails through login forms permits more targeted phishing campaigns. People are more receptive to emails from services they use, as opposed to emails from services they do not.
When a candidate’s registered email address is identified, account lockouts can be tested. After one to five failed login attempts for a single email address, there should be a change in the system's behavior. The system should either require human interaction in the form of solving a CAPTCHA*, to prevent automated attacks, or the system should lock the account out. In the absence of both behaviors, the system is vulnerable to brute force attacks.
*CAPTCHA: completely automated public Turing test to tell computers and humans apart
Password Reset Forms
Similar to login forms, you have to consider what information password reset forms expose. If the password reset form indicates that a given email address is registered in your system, it can be used by attackers to filter email addresses as well.
Two other common issues associated with password-reset forms are using the password-reset form to flood the inboxes of users, and prediction attacks on the password-reset system itself.
Password reset forms commonly send an email to the user's email address. Ideally, there is throttling built into the system that limits the number of password reset emails sent to the same address in a day. Unfortunately, that’s not the norm. During penetration tests, we frequently send ourselves thousands of password reset emails within minutes. Attackers know that this can lead to spam filters blacklisting the target site, blocking legitimate messages.
When a password reset email is sent, it should contain a link to a form on the website that can be used to reset the user's password. This link should contain some sort of token unique to the reset request, which links the request to the email address. Think of this like the classic game Battleship, except the attacker is trying to hit your ships by firing millions of times each second. How can we make the game harder for the attacker? We can make the board bigger, keep our ships from staying on the board very long, and not have more ships on the board than we can get away with. In technical terms, these three approaches are, respectively:
Unpredictability: The number and variety of characters that comprise the token determine how many tokens can be generated.
Lifetime: The time during which a token is valid determines the window of opportunity for an attacker to guess the token.
Overlap: If multiple password reset tokens can simultaneously exist for a user, an attacker has far more targets to find at any moment. For example, if an attacker can generate a hundred thousand password reset emails for a user, each one containing a unique and valid token, then it becomes much, much easier to power through the possible password reset tokens to find one belonging to the target user. We have also encountered tokens generated based on the email address, the time at which the reset request was generated, and both. Ideally, tokens should be entirely random, derived in no way from any user or system information.
We should also note that if the password reset email contains the user's original password, then the passwords are being incorrectly stored in a recoverable format. This indicates to an attacker that—if they can steal the site’s database—it will contain very valuable information.
In a perfect world, we would never have to report these issues during a penetration test. It takes us longer to grab a screenshot and customize remediation advice for any of these findings than for operations and development personnel to check an application before deploying it to production. Two great tools that can help check for some of these issues are SecurityHeaders.io and SSL Labs' Server Test. We will check for them too, but everybody will be happier if we are not the ones to find them. :-)