
Elementor Pro 表单的文件上传字段在验证和文件处理两个独立的循环中进行,并且对空上传条目(UPLOAD_ERR_NO_FILE)的处理方式不同。未经身份验证的攻击者可以提交一个 multipart 请求,其中第一个文件部分为空,随后为同一字段附带一个 PHP 载荷,从而使 validation() 提前返回,而 process_field() 仍会将 PHP 文件移动到公共目录:wp-content/uploads/elementor/forms/.php
自动从目标页面获取 post_id、form_id 和 field_id:
python poc.py -t http://localhost/wp --page-url "http://localhost/wp/?page_id=16" -c "whoami"
或者:
python poc.py -t http://localhost/wp --page-id 16 -c "whoami"
启动交互式会话:
python poc.py -t http://localhost/wp --page-id 16 -i
该漏洞的核心在于绕过文件上传机制本身。无论您是在本地实验室还是针对真实服务器进行测试,这部分都没有区别:上传字段中第一个空文件部分 + PHP 载荷绕过了扩展名验证,但该文件仍会被 process_field() 处理。我们已演示文件被成功写入,这正是它所描述的情况。
关于硬编码的 Laragon 路径:
那只是为了方便本地验证。
在真实目标上,目录模式是已知且固定的:
/wp-content/uploads/elementor/forms/
不固定的是最终文件名。
Elementor 不会保留原始文件名。在 process_field() 中,存储的文件名按如下方式生成:
因此,如果您上传 shell.php,文件名可能会变成类似:
66f3a1c2e9b47.php
位于:
/wp-content/uploads/elementor/forms/
uniqid() 基于时间生成,并非强随机值;它大致基于时间戳 + 微秒。因此,在远程恢复该文件就变成了一个文件名发现(filename discovery)问题,而非上传问题。
例如,您可以根据服务器的 Date 响应头和请求时序构造时间窗口,在上传时间附近的狭窄范围内进行搜索;或者,如果表单发送的电子邮件中包含 [all-fields],也可以直接恢复出确切的 URL。
我将此 PoC 聚焦于清晰、直接地证明核心问题本身——未授权文件上传。完整讲解 uniqid() 值的远程恢复会使演示变得冗长,远超验证该漏洞本身所需。