Practical Tips for OWASP Top 10 2017 #7: Insufficient Attack Protection

May 20, 2017

Contents

  1. Introduction
  2. Attack Detection using Honeytraps
    1. Fake form fields
    2. Fake cookies
    3. Fake HTML comments
    4. Fake robots.txt entries
  3. Attack Response
    1. Active Response
    2. Passive Response
  4. Going Further: Honeytokens

1. Introduction

The preliminary release of the OWASP Top 10 - 2017 in April 2017 has stirred up quite a bit of controversy over the inclusion of a new entry titled "A7 - Insufficient Attack Protection".

Aside from taxonomical problems (a lack of protection is not a vulnerability in itself), the description for the entry explicitly recommends solutions such as Web Application Firewalls (WAFs) and Runtime Application Self-Protection (RASP) products. The likely result is that many decision makers will take the shortcut of buying a WAF and putting a checkmark next to A7 on the Top 10 list.

Even worse, as Timothy Morgan uncovered on the OWASP Top 10 Mailing List and as further detailed in James Kettle's blog post, "Insufficient Attack Protection" seems to have been unilaterally added by Contrast Security, a RASP solution vendor with a conflict of interest. Jeff Williams, CTO of Contrast Security has since responded to the accusations in a blog post.

There are many advantages to having a custom-configured WAF used as a defense-in-depth measure, but a recommendation should point out it's not a silver bullet and that there are potential pitfalls. Adding an additional component such as a WAF or RASP to your system architecture also increases your attack surface. WAFs and RASPs filter all your web application traffic and look for potential attack patterns, usually with the help of regular expressions (since commercial offerings are black boxes, there's no way to be sure how they work precisely). Regular expressions can be vulnerable to Denial of Service attacks. The WAF or RASP software itself can also have vulnerabilities, sometimes resulting from complex interactions between components. For a recent example, take a look at Cloudflare's "Cloudbleed" vulnerability. WAFs certainly can also be bypassed - we've had some interesting results with HTTP multipart requests, but that is a topic for another blog post. Recommending RASP as a solution fails to mention that it only works for Java and .NET web apps.

It is worth taking a look at the raw data from the Top 10 2017 data call. (As an aside, Brian Glas did an excellent analysis on the data, demonstrating that automated scanners and humans find different types of vulnerabilities and a combination of both is indispensable.)

The statistics not only identify XXE as a highly prevalent vulnerability that would have deserved a spot on the Top 10, they also mention "Insufficient Anti-Automation" much more frequently than "Insufficient Attack Protection". This points us in the direction to the solution I believe we should be recommending developers to implement.

2. Attack Detection using Honeytraps

Much like we already detect bruteforce attacks against logins with a simple counter and use little Turing Tests called CAPTCHAs to prevent spamming of a form, we can perform effective attack detection and response with just a few lines of extra code. We can detect both automated attacks from web vulnerability scanning tools such as PortSwigger Burp Suite or OWASP ZAP as well as manual attacks right within our web application. In fact, it is the perfect place for it! Unlike a WAF or IDS which is not aware of application logic and will sometimes block legitimate users, detecting attacks in our application itself is free of false positives.

All the methods for attack detection described below have been covered extensively in chapter 3 of Ryan Barnett and Jeremiah Grossman's book "Web Application Defender's Cookbook: Battling Hackers and Protecting Users" which I highly recommend. While the book solves attack detection and response using the mod_security Web Application Firewall, you do not need a WAF. Instead, we'll consider how to do it from within our web app.

The idea is simple: We lay down honeytraps in our application such as a fake parameter with no actual functionality. If the parameter value is manipulated, we can be certain this is an attack. We can proceed to the response stage and choose how to deal with the attack.

The honeytrap will automatically be picked up by web vulnerability scanners which try to modify every parameter. In order to further attract human attackers, we can give the parameter an enticing name such as "isAdmin=0". Don't you just feel the urge to find out what happens if you change that to a isAdmin=1?

Unlike a WAF/RASP, we don't need to identify the type of attack (Is it SQL injection? Is it Cross-Site Scripting?). It's enough to know with certainty that there is an attack and then block it. We don't have to interpret the parameter value or run regular expressions on it. We just check if it has been changed: if($isAdmin != 0). This simple approach strips away most of the complexity of attack protection. Still, be sure to perform a code review on your attack protection code after you have implemented it.

Having active attack protection means you should run penetration tests against a specially deployed test server with the protection turned off. You don't want to be spending all your money for PenTesters to try to circumvent your protections, you want them to focus on finding the actual vulnerabilities behind the protections. If you are running a bug bounty, do not turn off your attack protection.

Let's go over some suitable locations for honeytraps:

2.1 Fake form fields

Hidden form fields are the perfect place for a honeytrap. They are explicitly not meant to be altered by a user, so any modification indicates a manipulation. The name for the honeytrap form field should be chosen to blend in with the form's functionality. Alternatively, a plausible generic name such as "debug", "context" or "resource" can be used.

<input type="hidden" name="debug" value="0"/>

Any POST request with a non-zero value for the debug parameter can be assumed to be malicious and should be dealt with one or more of the response actions outlined in the "Attack Response" chapter below.

For Single-Page Applications and Web APIs you can similarly add a non-functional parameter/value combination. Be careful not to disclose the true honeytrap functionality of the parameter in publicly available API documentation.

2.2 Fake cookies

Cookies are another highly effective place for a honeytrap. Many web applications use tracking cookies with cryptic values, base64-encoded strings or hash values. Hiding a fake cookie among those is easy. Set the honeytrap cookie the same time you set the session cookie or any other valid cookie.

Burp Suite Professional and OWASP ZAP will automatically try to manipulate cookie parameter values. To further attract human attackers, use something like env=prod (suggesting a production environment setting that could be changed to staging or dev) or debug=false:

Set-Cookie: env=prod; path=/; domain=yoursite.com; httponly

Any incoming requests with a cookie value other than prod can be considered an attack.

2.3 Fake HTML comments

Commenting out old HTML code is a bad development practice that has not quite died out yet. Both Burp's and OWASP ZAP's Spider Modules will pick up links in HTML comments and follow them (as long as they match the current project scope). Choose a link on your page and next to it include an HTML comment linking to a link_old or link.bak page:

<!-- old link: <a href="page1_old">page1</a> -->

Any visits to the page can be assumed to be from automated web vulnerability scanners or human attackers.

2.4 Fake robots.txt entries

One of the first things a PenTester checks during the Enumeration phase of a Web Application Test is the robots.txt file. All too often, admins follow the rationale "we don't want internal parts of the app to show up on google, so we'll block them using robots.txt". At the same time, the exact path is disclosed to anyone who looks at the file. We've seen Disallow: entries in robots.txt leading us to sessions directories, old backup versions of apps, directories with internal API documentation and much more.

Add a seemingly legitimate entry to your robots.txt such as: Disallow: /appname.bak/

Anyone trying to access this path on the web server will be at least suspicious, although not all hits for this honeytrap will be targeted attacks. Still, you can probably afford to block scrapers and rogue indexing bots that ignore the robots.txt. Before implementing a fake robots.txt entry, consider the risk of locking out legitimate users if the link in the robots.txt is used in a phishing email.

3. Attack Response

Responding to an attack generally falls into one of two categories: a passive response, invisible to the attacker and an active response. In most cases, you will want to simply block & log the attack.

Be aware that any response functionality you decide to add needs to be implemented securely. Try to keep it as simple as possible. If your response action requires you to include additional libraries, consider a simpler response action or perform a security review on the libraries. Before implementing response measures that permanently block offenders, perform a risk analysis on the impact of accidentally blocking legitimate users and have a plan how to handle unblocking.

Ideas for response measures are inspired by OWASP's AppSensor Project, a Java-based framework for web intrusion detection and response. AppSensor even offers functionality for an intrusive response which will not be covered here. Response actions such as turning off a functionality are not recommended since they are just a Denial of Service attack waiting to happen.

3.1 Active Response

3.1.1 Block Attack

Usually you will want to block attacks directly by discarding the request and doing one or more of the following:

  • Terminate the current business process (e.g. cancel order process)
  • Log out the user
  • Redirect to error page
  • Redirect to home page

3.1.2 Rate Limit Attack

Introduce artificially extended response times for requests. As commonly done with failed log in attempts, you can keep increasing the delay with each detected attack request.

3.1.3 Account Lockout

For a more permanent measure, the user account can be deactivated. This can be done permanently or temporarily for a first offence. Make sure to also terminate all sessions associated with the account.

If desired, the user's IP can be blocked for a period of time. This should be done by passing the information on to a firewall or fail2ban. A common fail2ban setup is to return a specially configured HTTP error code in your web app such as 432 and have fail2ban watch your webserver logs for that code.

3.2 Passive Response

3.2.1 Admin Notification

The most common passive response is to send an alert to an administrator or incident response team via email, SMS, Slack or Instant Messaging. Be careful what kind of details you include in the alert depending on how secure the communication channel is.

3.2.2 System Notification

Send an alert to your other security systems such as a SIEM (Security Information and Event Management), IDS/IPS, firewall, WAF, load balancer, log management system such as splunk or ELK. IPS and firewalls can use the alert to take active response measures such as blocking the offending IP.

3.2.3 Logging Change

If you decide to continue allowing the attacker access to the application, an increased, focused logging of their activity would be a highly advisable additional response measure. For example, you could start logging the actual content of their POST requests in a special incident log. As with all logging, double-check that log data is properly sanitized to prevent attacks against the log viewer.

3.2.4 Limit Account Functionality

In the same manner, if you allow the attack to continue using the application, you could limit their account functionality. File uploads can be turned off or severely limited in size, CAPTCHAs can be turned on for submission forms, actions such as orders can be flagged as likely fraudulent etc.

3.2.5 Redirect To Honeypot/Tarpit

Redirect all attacker requests to a specially prepared honeypot system which mimics the real web application and monitor their behaviour to learn more about their attack vectors. This would be an ideally suited response action if human attackers are identified such as through parameter values that a human would likely supply (our "env=prod" example).

The honeypot could also trap automated scanning tools with endless link/redirect chains using a web tarpit such as TarPyt or WebLabyrinth.

4. Going Further: Honeytokens

All done with adding honeytraps to your web app? The next step in detection would be to be able to actively detect a successfull attacker taking off with your stolen assets.

We can roll our own Data Loss Prevention (DLP) using so-called honeytokens. For every set of sensitive data records, we add one fake entry. For example, add an additional row in the users table with a fake user and a very specific username or email. If this table entry is ever accessed in the database or if someone tries to log in using that username/email, we can be certain that the users table has been compromised.

Likewise, we can add a fake file in a file store, a fake invisible product in the products table etc. Detection can be done in a WAF or IDS. It's a concept dating back to before the digital age when encyclopedias and maps used fictitious entries or fake streets to be able to detect would-be copycats.

I hope this blog post has highlighted how you can perform attack detection and response in your web application with just a few lines of code before you spend a lot of money on WAFs and RASPs. Interpreted this way, an OWASP Top 10 recommendation for developers to implement attack protection in their apps would be a valueable addition.

Read about other interesting topics on our blog.