Showing posts with label brute force. Show all posts
Showing posts with label brute force. Show all posts

Tuesday, 26 August 2014

Pagely Brute Force Mitigation Bypass

A while back I was looking at one of Facebook's acquisitions, Onavo, and came across their blog which was using a Wordpress install managed by Pagely. While testing for ways to brute force the login page I discovered a brute force mitigation bypass that not only affected Onavo but also every other Pagely protected site :)


Detect Wordpress? Look for wp-login.php

Wordpress is pretty common and actually pretty secure these days. One area that still needs some work though is protection for the default login page wp-login.php. Most installations leave this page publicly exposed and a lot do not implement the recommended brute force mitigations here:

http://codex.wordpress.org/Brute_Force_Attacks

Onavo took the easy approach and used Pagely. Pagely offer managed security which in theory should mean you are more secure...


Testing for bruteforce

So let's try and brute force Onavo's wp-login page.


You can see after only a few requests we start getting redirected (302). This redirection actually takes you to a Pagely captcha page.



The magical "pagelyvalid" cookie

I was curious how they implemented the verification once past the captcha so took a look at the response and saw that the captcha check just set a cookie called "pagelyvalid" to true. Hmmm. Lets try our brute force attack again but this time including the magical pagelyvalid cookie.



Lots of 200's. So simply including the pagelyvalid true cookie we can bypass the Pagely brute force mitigation and guess passwords night and day. And like I said at the start this didn't just affect Onavo but every site that used the Pagely service. Yikes!


Final Thoughts

A lot of sites miss brute force mitigations and rate limiting in general. Third parties can offer a quick fix but it's important to remember you are trusting your security to that third party and assuming they will do a good job (which isn't always the case!).

Both Facebook and Pagely responded reasonably quickly (the Pagely CEO even sent me a message!) and a fix has now been deployed. Hope you guys found this interesting, as usual if you have questions or suggestions just drop me a comment below.

Pwndizzle out

Friday, 7 February 2014

Brute Forcing Your Facebook Email and Phone Number

Today I'm going to talk about the Facebook password reset page and a series of flaws that allowed anyone to brute force a user's primary email or mobile phone number.

TL;DR Iterate over phone numbers/emails, dump valid but anonymous data, use manual/automated enumeration to find specific owners.


Forgot my password...

To perform a password reset on Facebook you first have to find your account. You can conveniently search by either your email, phone, id, username or full name.



If the account has used your ip range before, you will be shown the username, picture of the user, obfuscated email and obfuscated phone number and from here you can choose how you want to reset your password.

Once you press continue Facebook will send you a one time password reset link/code that can be used to change your password. 


Under the hood

When you press that first "Search" button, two requests are sent.

- Request #1 (POST /ajax/login/help/identify.php?ctx=recover) seems to be an initial check to verify if the data you are requesting actually exists. If it does, a cookie is set and you are redirected (Request #2). If it doesn't exist you are given an error message.

- Request #2 (GET /recover/initiate) if you are redirected, the request passes the cookie from step one and the server will give you the password reset info, name/image/email/phone.

So where are the flaws?


Issue #1 Verify information through look-up


Did you notice how we were able to search for an arbitrary user/email/phone number and obtain the username/image/obfuscated data? The lookup feature
fundamentally contains and operates using an information disclosure vulnerability. We're able to gain limited information about specific users we're not friends with and even evade privacy settings.

Using Request #1 we can effectively ask the Facebook server does this email/phone number exist in your database? And the server will reply yes or no. It won't however tell us who the owner is. This kind of information disclosure is present in a number of features on Facebook.

Using Request #2 we can ask the server who the specific owner of a particular phone/email is and the server will tell us. Awesome, but there are some server-side checks which mean this information is only disclosed (i think) if you have a specific cookie, user-agent or if the request is coming an ip range the account has used before. So user lookups are still possible with Request #2 but you'll only be able to find users who've used your ip range. Example below.

Invalid IP - Searching by email, our email is echo'ed back but username is not given as the account has never logged in from my network.


Valid IP - After logging in, again searching by email we see the email, but this time we are also given the username and image.



Issue #2 No throttling of requests

For Request #1 no throttling mechanism was used. This meant it was possible to repeatedly query the Facebook server, effectively allowing mass collection of valid users/emails/phone numbers (a spammers dream come true).

If you send Request #2 too often you'll hit a captcha, but not a hard cap. So for a determined attacker they could just repeatedly enter the captcha.


Issue #3 Obfuscation fail


Although it may seem trivial, by giving away two characters plus the domain for email addresses and four out of eleven characters for phone numbers Facebook had made these parameters significantly easier to brute force.

Take my phone number for example. My number is 11 digits long. The first four digits are from the carrier and for most countries there will be a small number of possibilities (50 in my case). Facebook have told us the last four digits. So my 11 digit number (99,999,999,999 possible combinations) has been reduced to 11 - 4 (FB) - 4 (Carrier) = 3 digits (1000 possible combinations per carrier range!).

The same applies to email addresses although they are harder to guess because of the larger search space.


Putting it all together...

Taking advantage of the issues above it is possible to effectively brute force a specific user's phone number or email. For a phone number the attack goes like this:
  1. Get on an ip range that your target has recently used
  2. Search for the user by id, username or email
  3. Obtain the last four digits of the phone number
  4. Search the entire number space (with Request #1) and build a list of possible numbers
  5. Re-submit numbers one by one (Request #1 and Request #2), manually entering the captcha
  6. Eventually one of the numbers will show you the reset page for your target, which tells us that number is the targets number!



So lets see some of this stuff in action...


Enumerating everything!

The simplest attack is just to enumerate everyone/everything. You won't know the owners of the emails/phone numbers but you'll still know they are valid and are being used by a Facebook user.

All we need to do for enumeration is send the following POST request containing our guess, which can be a user/email/phone number.


Using Burp Intruder I performed two tests, one where I found valid phone numbers, another where I found valid emails. The first payload I used looked like this <carrier><payload><3362>. Responses of 809 indicate invalid numbers while 1081/1102 indicate valid numbers.


For email testing I submitted the payload johnsmith<number>@gmail.com. Same as before, 809 indicates invalid emails where as 1102/1123 indicates valid emails.


And because there is no captcha or throttling we can just keep going and going until we've found every email/phone number registered with Facebook and spam/spear phish them all :)


Targeted Pwnage

Although a targeted attack is harder, it's still possible with a little preparation. To demonstrate, I'll attempt to find the phone number for my target user mark.zockerberg.54.

First up, to evade the Facebook checks we'll need to attack from an ip in a range that our target has recently used. Next we'll need some way to identify our user - id, name, username and email/phone number are all options. I start off by searching for the username in the request below:



The response from this request will redirect us to the page with basic user data: 


Using the 4 digits from Facebook and mobile carrier ranges obtained from Google I now start searching for potential numbers that our user could be using:


Scanning every carrier range (changing 0926 for 0927, 0928 etc.) we will get a reasonably small list of potential numbers.


Because of the captcha on Request #2 we can't automate number to name enumeration, so the only way to convert all of our numbers to users is by manually searching and completing the captcha. Assuming you have 300 numbers and it takes you 15 seconds to enter the captcha for each number, it will take just over an hour to check them all. Eventually one of the numbers you enter will lead you back to the password reset page for your target, effectively confirming that the number belongs to that user!

If there was no captcha or you had a bypass you'd be able to automate username lookups something like the following:


Here I converted the sfiu cookie direct to user and you can see we get our user Mark Zockerberg (the captcha kicks in right after)

The techniques I used above could also have been used to find a user's email address. Although with emails containing both letters and numbers the search space is a lot larger, e.g. email with 8 characters = 36^8 combinations! With that said, a lot of users will use emails that contain dictionary words or their names, so it may not actually be that hard. Also for an attacker targeting a specific company he could dump emails from their website/google and run those addresses through the password reset to locate and then target their employees, could provide some interesting results.


Final Thoughts


The classic email password reset can and is often implemented completely securely with no information disclosure. Both Google and Facebook however have created multi-step resets that involve information disclosure. For me it just doesn't sit well and I suspect we might see changes in the future.

To mitigate the attacks discussed above Facebook reduced the phone number digits disclosed from four to two and implemented a captcha check for Request #1. The fundamental issue of providing a look-up feature though has not been modified. So if you have a botnet or captcha bypass (watch this space!) you can still dump valid numbers and emails.

I hope you guys have enjoyed this post, questions, comments, are always appreciated.

Pwndizzle over and out

Saturday, 12 January 2013

Etsy Brute Force Counter Reset Flaw

Continuing my work with Etsy today I'm going to be talking about their login page and a brute force protection gone wrong.


Got brute force?

Everyone knows what brute force is so I'll keep this bit brief. In the context of credential brute forcing, the basic idea is to find valid username/password combinations by sending multiple requests to a login page and examining the responses. This is easy enough to perform by loading the login POST request into Burp Intruder, choosing variables, selecting your word lists and pressing start.

But what about mitigations? These days most web developers are wise to this type of attack and implement measures such as lock-outs, captchas and rate limiting to prevent brute force.


Getting around mitigations

There's always a way around mitigations and brute force is no exception. Spreading the attack across multiple accounts, using multiple ip addresses or rate limiting your requests can avoid lock outs and captcha's can be solved in an automated way with something like Tesseract.

And for all of the above subtle differences in responses from the server can sometimes offer important clues. Things like:
  • Size of reponse
  • HTTP response codes
  • How long it takes to receive response
  • Content of response
While tackling mitigations head on is possible often a little thinking outside the box can go a long way. Given that we can control the speed, order and content of our messages to the server is there some way to perform brute force and not trigger the mitigations?


A Case Study: Etsy.com

Etsy uses two mitigations to stop automated brute force. First up a throttling mechanism that kicks in after 20 incorrect logins. This is performed on a per ip basis and starts off using a 10 second delay (maybe increasing later). Although not as secure as a lock out/captcha, it still does a good job of slowing our brute force attack significantly.

 As we hit 20 requests we see the 10 second delay start.


The second mitigation is the use of a captcha after 20 failed logins.



As blocking is performed on a per ip basis, we could try a distributed attack. For example by using a hundred different addresses we could increase our maximum 20 requests to 2000 requests before being throttled/captcha-ed.

Realistically though 2000 requests isn't enough and although possible, getting hold of a hundred addresses (or a botnet) wouldn't be easy, not to mention having to deal with the captcha! Perhaps we can find another technique?


Breaking the lockout

Something I haven't mentioned is what happens when you login successfully.

To test the effect of a successful login I sent a series of incorrect logins (which triggered the throttling) followed by a correct login request and then more incorrect logins. Looking over the results I was surprised to see that as soon as the legitimate request was received by the server my requests were no longer being throttled and I wasn't required to enter captcha!

Below is the output from Burp:

Sending 20 incorrect logins causes the throttling to kick in (first red circle). I sent a legit request in my browser and the throttling was removed (second red circle). Also 2-3 second delays were caused by the free version of Burp Intruder :)


So it turns out Etsy used a server-side failed login counter that was reset any time you logged in successfully. All an attacker would need to do is send 19 bad requests followed by one good request and they would never have to deal with the throttling or captcha. Job done.


Final Thoughts

Brute force is an age old attack vector that often works just as well today as it did 20 years ago simply because authentication techniques have not moved with the times.

In this instance we've seen how just one logic flaw allowed us to side step all of the mitigations. A lack of defense in depth meant that once we had bypassed the failed login counter we were free to brute force to our hearts content.

Thanks again to Etsy for their swift response and fix!

PwnDizzle over and out.


P.S. I've got a new twitter account! Add me as a friend, follow me, tweet me, etc. @pwndizzle

Thursday, 15 November 2012

Back to Basics: CSRF

I've recently been playing with client-side CSRF token brute forcing. It's cool stuff but for folks who aren't so hot on CSRF (or just need a refresher!) I thought I'd do a quick CSRF back to basics. As CSRF has been talked about a lot before I'm going to try and keep it brief covering some simple attacks and mitigations.

For a basic introduction the best place to start is OWASP:


In a nut shell, we are tricking a user into sending our malicious request to a remote server, using their already established session. This is usually possible because the structure and contents of a vulnerable request is known ahead of time and it's just a matter of creating the request and convincing a user to send it. Awesome, so we can perform actions as another user? Yep!


How do you actually launch a CSRF attack?

If the target site has a vulnerable page that is accessed using a GET request, all we need to do is create a webpage or email containing either a malicious link or image and trick the user into accessing it. The user will run the code and unknowingly send a malicious request to a third party site. From OWASP:

<a href="http://bank.com/transfer.do?acct=MARIA&amount=100000">View my Pictures!</a>

Or:

<img src="http://bank.com/transfer.do?acct=MARIA&amount=100000" width="1" height="1" border="0">

For a vulnerable page that uses a POST request we can create a webpage with a form and some javascript to auto-submit it. When the user visits the page it will submit the request using their session cookie. The form "action" should link to the target site and the parameters should be identical to a legitimate request. 

<html>
<body>
    <form action="http://bank.com/Home/Transfer" method="post" name="badform">
        <input name="accountId" type="hidden" value="1234" />
        <input name="amount" type="hidden" value="1000" />
    </form>
<script type="text/javascript">
        document.badform.submit();
    </script>
</body>
</html>

The above examples can also be created using jquery or pure XHR, for example:

<script>
function xhrcsrf(){
var http = new XMLHttpRequest();
http.open(POST, "http://bank.com/transfer.php" , true);
http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
http.withCredentials = "true";
http.onreadystatechange = function() {
 if(http.readyState == 4 && http.status == 200) {
  alert(http.responseText);
 }
}
http.send("accountID=1234&amount=1000");}
xhrcsrf();
</script>

To test these examples you probably want to install xampp on Windows or apache on Linux. And for a vulnerable page I used Debasish's simple profile.php and submit.php script here:



How to protect against CSRF?

CSRF relies on the static nature of requests and the ability to send cross domain requests. By making requests unique and checking where they originate from you can easily prevent CSRF.

To make requests unique commonly a random value, or token, is included as a parameter. An attacker will not know this value ahead of time and will be unable to craft a static malicious page that can send a valid request.

For example a unique token could be generated server-side using the current time, a secret key value and a complex math function. This value is returned when the user loads a page on a site and is submitted with all requests back to the server. Assuming everything else is secure, there is no way for the attacker to know this token without knowing the underlying token generation algorithm.

Below is a status update to Facebook. I've circled the token they use to prevent CSRF.


The other protection mechanism I mentioned was sender verification. To verify the source of the request the receiving page can inspect the Referrer or Origin header of the request. A simple check would verify that the request came from your legitimate domain and not from another site (cross-domain). 

There's a great article about CSRF protections that is far more in-depth here:



How to get around CSRF protections?

This is where things get a bit tricky. If a site is checking the Origin or Referrer header of your requests you're stuck. Browsers set these headers and unless you can modify the traffic leaving the browser (malicious extension?) or on the wire (mitm), then there is no way to tackle this.

EDIT: I was actually wrong about this. Kotowicz has some work arounds here: http://blog.kotowicz.net/2011/10/stripping-referrer-for-fun-and-profit.html


Chrome added these headers.

One exception is if you can include your code somewhere on the target site, e.g. XSS, which can be leveraged for CSRF.

So what about tokens? If implemented correctly they work perfectly well and will prevent CSRF attacks. However, quite often tokens are not implemented correctly allowing us to bypass the token check or possibly brute force the token. For example:


One missed token check and you have a serious CSRF vulnerable (as well as a $5000 payout :D).


Can you brute force the token?

It depends on the entropy (complexity) of the token. You need to analyse it's length, character set, does it repeat, are there any static characters, are there relationships between characters, all of these factors determine it's entropy (Burp Sequencer can help with analysis). If a token has a high level of entropy there will be too many possible combinations and it will take too long to brute force. You also need to think about other more practical issues such as latency, which could make the attack unfeasible, or server-side lock outs. Five failed attempts and you get locked out? Brute force ain't gonna work but denial of service will :)

One of the best tools for brute forcing tokens is Burp Suite Repeater as it allows you to send a large number of requests iterating through token values until you find the correct one. Its quick and easy but requires you to have a valid cookie.

What if you don't have the target user's cookie? That's where client-side brute forcing comes in! :)


**********************

In my next post I'm going to continue with the CSRF theme and look at some interesting client-side CSRF token brute forcing examples.

Feedback and comments are always appreciated, feel free to leave a message below.

Cheers,

PwnDizzzzzle