Preventing Brute Force Password Guessing Attacks with APM - Part 2
F5er and DevCentral community member ystephie is back with another great solution (check out her first solution here: BIG-IP APM Customized Logon Page), this time tackling brute force attacks utilizing customizations with the BIG-IP Access Policy Manager. This solution requires BIG-IP 10.2.2 Hotfix 1 or later.
Exposing applications or services to the Internet opens inherent security risks. BIG-IP Access Policy Manager (APM) provides edge authentication and access control services for applications, BIG-IP Edge Gateway provides secure SSL VPN services, and BIG-IP Application Security Manager (ASM) provides protection against a variety of attacks. In this series of APM deployment examples, we cover a couple techniques for protecting against brute force password-guessing attacks.
In our first example (Part 1), we walked through the process of including a CAPTCHA on the APM logon page via a web service (Google reCAPTCHA project), to provide some protection against script based or other automated attacks. In this second example (Part 2), we’ll be a bit more selective around when to display the CAPTCHA challenge (no point inconveniencing valid users) by displaying a CAPTCHA only after the user has failed full authentication. This is done using an AD Query for the user’s bad password count attribute. The selective CAPTCHA challenge provides the same benefits as with Part 1 (always on CAPTCHA) by blocking automated password-guessing attacks as well as DOS attacks against Active Directory. In this case a user’s internal corporate AD account may be locked after a number of sequential failed authentication failures in an external DOS attack – a serious inconvenience to the user affected as well as his IT department! In this example we’ll be using a two page configuration. If a user fails authentication, the next time they sign on, they’ll be prompted for a CAPTCHA challenge after entering their login credentials (via a separate page).
Visual Policy Editor – Macros
Start with a new access policy (you can use a wizard to do this – See Part 1 of this series). Create a Macro; I called mine Plain Captcha. This will just be a page with a CAPTCHA. We’re using a macro because we’ll be using this Plain Captcha many times in this policy so it’s easier than creating a new logon page each time we need it. See Figure 1.
Configure the Logon Page as in Part 1 with the extra post variables. Then go into Advanced Customization as discussed in Part 1. Remove the same PHP code and add the following:
<tr><td colspan=2 class="credentials_table_unified_cell">
<iframe src="https://www.google.com/recaptcha/api/noscript?k=replace_with_your_public_key"height="300" width="500" frameborder="0"></iframe><br><textarea name="recaptcha_challenge_field" rows="3" cols="40"></textarea><input type="hidden" name="recaptcha_response_field"
Don’t forget to do all the necessary steps for advanced customization. See Part 1 - Advanced Customization Checklist for directions.
Next, let’s add another macro that does the authentication and resource assignment. We don’t need to build this macro ourselves; we can simply select the macro template AD auth and resources (you may use your choice of auth factors but my examples will be using AD auth). Remove the Logon Page from the macro after saving. Configure the AD Auth with your AD server and change Max Logon Attempts Allowed to one.
Once you add a Webtop to Resource Assign, your macro should look like Figure 2.
Now that we have finished building the macros, we can start with our access policy. The general flow of the policy should be that we only directly authenticate a user if we know they exist in Active Directory (a valid username) and they have not previously failed authentication. We can determine this through use an AD Query. If the user is invalid, we stop them here. If the user is valid, but has previously failed authentication, we will give them a CAPTCHA challenge. The policy is quite simple. Create a Logon Page followed by AD Query, and based on the following branch rules we can determine which leg to take.
- If we have a valid user and they have not previously failed authentication (badPwdCount is zero), we can authenticate them directly with our AD auth and resources macro. If the user passes, then he is allowed to access the VPN.
- If we have a valid user and they have not previously failed authentication but the user fails the auth agent for the first time, we still need to show the CAPTCHA at the end just to ensure that the behavior follows all the other cases.
- If we had a valid user and they previously failed authentication (badPwdCount is one or higher), we can display the CAPTCHA challenge and authenticate the response against Google’s reCAPTCHA web service using HTTP Auth. If the user was able to enter the CAPTCHA correctly, the user is then allowed to authenticate.
- If we find that this is an invalid user, we don’t have to authenticate them (as they are going to fail authentication anyway). However, since we don’t want to give a hacker any hints about who’s a valid user and who’s not (allow for a username guessing attack), we must present the same end user behavior as if someone had entered incorrect credentials.
See Figure 3 for the complete VPE.
The HTTP Auth should be set up exactly as described in Part 1. If you wanted to configure a new HTTP Auth without having to go through the device wizard, you can go to AAA Servers under Access Policy. Now the user will encounter a CAPTCHA if they ever fail authentication. The Deny provides gives a lot of information but we can edit it to make it more readable and helpful to our users. To accomplish this, click on Edit Endings and under Deny, and then the plus sign next to Customization.
This solution is a great example where we used AD Query to selectively determine when to show our CAPTCHA challenge, in order to reduce the inconvenience of typing CAPTCHA challenges. But, this solution is not perfect. We’re limited to only allowing one bad authentication before showing the CAPTCHA. This is because AD Query only knows about users who exist in its database (valid users). If you’re trying to use the badPwdCount attribute to track more than one authentication failure, it is possible for a hacker to figure out if they have guessed a valid username (CAPTCHA challenge shown after a single failure for unknown usernames, but after two or more failures for legitimate usernames). In our next example (Part 3), we’ll build on this work and demonstrate a new technique for safely tracking multiple authentication failures. We’ll also remove the dependency on Active Directory for the authentication failure tracking.