vrijdag 23 november 2012

Cracking Redmine passwords

As I am running Redmine on my server and I wanted to test security I wanted to see if I could crack some passwords of my users.

Redmine uses sha1 to store passwords, salted with a random uhm.. salt.

In pseudo code the algorithm to create a password hash would look like this:
sha1(salt + sha1(password))

I made a dump of the users table in the format "login:password_hash:salt" and wrote a small Python based cracker that could parse this and iterate through a dictionary file.

Out of the 16 users in the table 2 of them used their login as their password.. 1 used his first name and 1 used a password that was cracked within seconds.
Needless to say, I locked their accounts [insert evil laugh] and I'm going to do this more often. (Maybe automated, with email notifications or something.)

O, and for those who want to do this sort of unethical thing too, here's the script:
#!/usr/bin/env python

from optparse import OptionParser
import hashlib

parser = OptionParser(usage="usage: %prog [options] userfile wordlist")
(options, args) = parser.parse_args()

if len(args) != 2:
    parser.error("Incorrect number of arguments")

def import_users():
    user_file = open(args[0], 'r')
    users = [] # format: (login, password_hash, salt)
    for line in user_file.readlines():
        if not line.startswith('#'):
            users.append(line.strip().split(':'))
    user_file.close()
    return users

def calculate_hash(password, salt):
    hashed_password = hashlib.sha1(password).hexdigest()
    hash = hashlib.sha1(salt+hashed_password).hexdigest()
    return hash


users = import_users()

# Try username as password
cracked = []
for user in users:
    word = user[0].strip()
    if user[1] == calculate_hash(word, user[2]):
        print "Password of user '%s' is '%s'" % (user[0], word)
        cracked.append(user)
for user in cracked:
    users.remove(user)

wordlist = open(args[1], 'r')
for word in wordlist:
    cracked = []
    for user in users:
        if user[1] == calculate_hash(word, user[2]):
            print "Password of user '%s' is '%s'" % (user[0], word)
            cracked.append(user)
    for user in cracked:
        users.remove(user)
wordlist.close()

Linux shorthand for rename/move/copy

As a Linux user you frequently use the terminal as it is powerful as [insert sentence enhancer].
A frequent thing you do in a terminal is copy or move/rename a file. When you do frequent things you'll get frequent annoyances (should sound familiar).

Example:
When you want to copy a file from "some/subdir/of/the/current/working/dir/file.ext" to "some/subdir/of/the/current/working/dir/file.ext.bak" you have to type the entire path twice. Even with tab completion it gets annoying.

Solution:
Use them fancy curly bracket things!
Instead of this:
 cp some/subdir/of/the/current/working/dir/file.ext some/subdir/of/the/current/working/dir/file.ext.bak  
Do this:
 cp some/subdir/of/the/current/working/dir/file.ext{,.bak}  

The curly brackets are interpreted to multiply the string it is in and make all combinations. So the latter is transformed to the first.
You can also embed them:
 echo a{,b{,c}}  
That's translated to:
 echo a ab abc