Sunday, October 27, 2013

Solving Pentester Academy Web Application Challenge -1 in both Python and Ruby using IronWASP

Unless you have been living under a rock you would have heard about Pentester Academy, a SecurityTube initiative that promises to bring good quality and affordable online security training to everyone.

As part of their Web Application Security course, Vivek has put out a bunch of challenges where you can test your security and scripting skills.
Solving some of the challenges requires writing your own scripts and what better tool for scripting than IronWASP. So based on popular demand I am going to be making a series of blog posts where I will show how you can solve these challenges by writing Python or Ruby scripts.

There is also a video that briefly explains some of the things covered in this post.
 


Challenge -1:



 

Take a moment to check out this video containing challenge description.

The challenge itself is available here - http://pentesteracademylab.appspot.com/lab/webapp/1
 
Difficulty Level: Beginner
Objective: Find out a valid username and password for the login page.
 
Clues:
  1. The usernames could be jack@pentesteracademy.com or admin@pentesteracademy.com
  2. The password is 5 characters long and only consists of the characters x, y and z
Approach:

To solve this challenge we have to do password cracking. We already know that the username can be either jack@pentesteracademy.com or admin@pentesteracademy.com.
 
The password is some word between xxxxx and zzzzz. To find out which one it is we have to try logging in with every 5 letter combination between xxxxx and zzzzz and see which one succeeds. The password only consists of three different characters x,y,z and the password length is 5 characters so the total number of combinations is 3^5 = 243.


The flowchart for the approach is below:

First we try all password combinations for the username jack@pentesteracademy.com. If that doesn't work then we redo the password cracking for the username admin@pentesteracademy.com.
Now that we know what to do, let's create the script. When trying to create this script we are faced with three important questions.
 
  1. How to perform the login from the script with a specified username and password?
  2. How to come up with all combinations of password from xxxxx to zzzzz?
  3. After the login response is received, how to determine if the login was successful?
I will answer all three questions below and you will see how IronWASP makes this whole process so simple.

To test out some of the commands and API calls you can make use of the 'Interactive Shell' of IronWASP. Make sure you pick the language of your choice - Python or Ruby and you will get a Python or IRB shell.
 

How to perform the login from the script with a specified username and password?

Before we can do the login in the script first let us see how the browser performs the login. Open Google Chrome browser and visit http://pentesteracademylab.appspot.com/lab/webapp/1
 
Now open IronWASP, go to the 'Proxy' section click on the checkbox named 'Set as System Proxy'.




Now IronWASP can capture all traffic from the opened Google Chrome browser. In your browser enter some value for username and password in to the login page and click on 'Sign in', you must see the invalid login message from the server. That's ok, we are only interested in knowing how the login request looks. If you go to the 'Log' section in IronWASP you must be able to identify the login request in there, it will have the value of the username and password you entered. Make a note of the ID number of that particular log.


 
To send this request from our script we can simply pick it from the logs using IronWASP's API by providing the corresponding log ID.
 
Python:
r = Request.FromProxyLog(1)
 
Ruby:
r = Request.from_proxy_log(1)
 
In my case the ID of the login request in the logs was 1, it could be something else in your case, use the corresponding value.

Once we create the request we must set the username and password values as per our requirement. Before we do that we must find out where the username and password values are stored in the Request. If you look closely you will find that the query part of the request has these values. The name of the query parameter carrying the username is 'email' and the name of the query parameter carrying the password is 'password'.
 

Now that we know this we can easily update these values from within our script.
 
Python:
r.Query.Set("email", jack@pentesteracademy.com)
r.Query.Set("password", "xxxxx")
 
Ruby:
r.query.set("email", jack@pentesteracademy.com)
r.query.set("password", "xxxxx")
 
 
After creating and modifying the request we now have to send this request and get the response. We do this like this:
 
Python:
res = r.Send()
 
Ruby:
res = r.send_req
 

How to come up with all combinations of password from xxxxx to zzzzz?

The latest version of IronWASP makes this step extremely easy, a new class called BruteForcer has been added to the API which can create the password combinations for you.
 
All that you have to do is mention what characters the password can contain, the minimum length the password can have and the maximum length. With this information BruteForcer will automatically generate all combinations for the given input.
 
If you wanted to get all the 4-8 letter lower-case alphabet based password combinations then this is how you do it.
 
Python:
br = BruteForcer("abcdefghijklmnopqrstuvwxyz", 4, 8)
print "Total combinations count is " + str(br.TotalCount)
while br.HasMore():
  print br.GetNext()
 
Ruby:
br = BruteForcer.new("abcdefghijklmnopqrstuvwxyz", 4, 8)
puts "Total combinations count is " + br.total_count.to_s
while br.has_more
  puts br.get_next
end
 
 
In this case our character set would be x, y and z and both the minimum and maximum length will be 5. So the input we would provide would be:
 
Python:
BruteForcer("xyz", 5, 5)
 
Ruby:
BruteForcer.new("xyz", 5, 5)
 

After the login response is received, how to determine if the login was successful?

This one is a little tricky, we don't know how the response would look if the login was successful but we do know how the response looks for an invalid login. The important glaring part of this the error message 'Failed! Please try again!'. If this error message does not appear in the response then it would be safe to assume that the login was successful.
 
 
So we have to look for this message in the body of the response that we get. Let's first check how this message appears in the source code of the page, we have to look for it in the exact same form.
 
 
And this is how this check can be done from the script.
 
Python:
if res.BodyString.count("Failed! Please try again!") == 0:
  print "Login is successful!!!"
 
Ruby:
if not res.body_string.include? "Failed! Please try again!"
  puts "Login is successful!!!"
end
 
 
 
Now that we have all the important parts covered let's put it all together and create the script.
 
Below you can see the complete Python and Ruby scripts for this challenge.

 


 Use the Multi-line Shell of IronWASP to execute these scripts. Make sure you have selected the appropriate language then paste or type your script in the text area and hit the 'Execute Multiline Script' button.
 
 
 
Once the script starts executing you must see the list of each password being tried, printed out in the console output area. 
 
 
 
If the script manages to crack the password then you will see the value of the password printed out like this.
 
 
 
If the password cracking does not succeed for jack@pentesteracademy.com then update the script to try password cracking for admin@pentesteracademy.com. Let's see if you can find out the valid username and password.
 
Good luck!! If you have any questions then you can send me an email or catch me on twitter.

7 comments:

  1. Great tutorial, is this tool gonna be put on Kali?

    ReplyDelete
  2. Thanks Michael! Currently IronWASP requires .NET so it cannot be added to Kali until a Mono compatible version is made. It's planned in the near future.

    ReplyDelete
  3. nice tutorial.. I still remember while showing us scripting engine in Null Bangalore meet, you created fuzzer on the fly.. good going

    ReplyDelete
    Replies
    1. Thanks Lokesh, you still remember that session, that's great. Will cover the Fuzzer creation in one of the future posts as well.

      Delete
  4. I am totally using IronWASP. This is 2014 btw and the dev is slow. I would love to see this in *nix distributions.

    ReplyDelete
    Replies
    1. Hi Shritam, great to hear that you are using IronWASP. New releases have slowed down because we are doing a complete rewrite and this should allow us to add support for *nix as well.

      Stay tuned for further updates :)

      Delete