
Mautic < 5.2.3 认证远程代码执行
对上传文件的内容、类型和扩展名的清理不当,允许经过身份验证的攻击者在 Web 目录中写入任意 PHP 代码,并定位该文件的写入位置。这导致远程代码执行。
路径遍历还允许利用此功能递归删除 Web 用户有权修改的文件系统上的任何目录。

当通过路由 /assets/view/{assetID} 编辑资产时,可以更改资产的文件。
上传新文件最终会调用 app/Bundles/AssetBundle/Controller/AssetController.php 中的以下函数:
public function editAction(Request $request, UploaderHelper $uploaderHelper, AssetModel $model, $objectId, $ignorePost = false)
上传逻辑如下:
if (!$ignorePost && 'POST' == $method) {
$valid = false;
if (!$cancelled = $this->isFormCancelled($form)) {
if ($valid = $this->isFormValid($form)) {
$entity->setUploadDir($this->coreParametersHelper->get('upload_dir'));
$entity->preUpload();
$entity->upload();
更具体地说,我们关注的是 preUpload() 和 upload() 方法,因为它们处理实际的文件写入磁盘操作。
第一个缺陷位于 app/Bundles/AssetBundle/Entity/Asset.php 中的 preUpload() 方法,因为其实现允许我们指定任意文件扩展名(从而绕过了 allowed_extensions 数组通常提供的保护):
$filename = sha1(uniqid(mt_rand(), true));
$extension = $this->getFile()->guessExtension();
if (empty($extension)) {
// get it from the original name
$extension = pathinfo($this->originalFileName, PATHINFO_EXTENSION);
}
$this->path = $filename.'.'.$extension;
如果提供的文件名以 .php 结尾且内容以 <?php 标记开头,则 $extension = $this->getFile()->guessExtension(); 这一行将返回 NULL。
因此,empty($extension) 检查将评估为 true,文件扩展名将通过 pathinfo() 调用提取,从而允许我们上传具有任意内容和扩展名的临时文件。我们无法控制文件的实际名称,因为它是通过 sha1() 生成的。
然后,在后续的 upload() 方法中,文件将通过以下调用实际写入 Web 目录中的磁盘:
$this->getFile()->move($this->getUploadDir(), $this->path);
它使用的是我们的任意扩展名(包含在 $this->path 变量中)。
然后可以通过刷新资产详情页面(/assets/view/{assetId})在“本地文件名”表条目下检索文件名。
注意:通过修改创建新资产时发送的请求也可以实现此操作。这将调用 newAction() 函数,但逻辑相同,缺陷仍然存在于 preUpload() 和 upload() 方法中。
PoC 将在大约一个月后发布。
这是为了让依赖此软件的组织有时间进行修补,而无需担心脚本小子破坏他们的系统。
之后,此仓库将更新完整的利用脚本和证据。此页面上的信息已经足够。
当验证临时上传(通过 /s/assets/new 或 /s/assets/edit/{assetId})时,存储临时文件的目录在请求结束时被递归删除。
负责保存临时目录名称的参数容易受到路径遍历攻击,允许经过身份验证的攻击者删除系统上 Web 用户有权删除的任何目录。
这可能导致数据丢失,甚至如果服务器恰好以 root 用户身份运行,则可能导致整个文件系统的破坏。
通过下面使用的端点指定系统中存在的任何文件。如果文件存在,服务器将尝试删除它所在的目录。

服务器接管 拒绝服务 数据丢失