内容简介:作者:看到了国外有大佬发了关于WordPress的一个非常有名的插件,contact form 7的漏洞,之前见到过很多WordPress站点使用这个插件,大佬写的比较笼统,一些详细的利用方式没有说的太明白.这个漏洞是由于插件开发者对WordPress的使用不当造成的,其实跟WordPress的逻辑有一定的关系,导致了可以发布普通文章的用户,可以绕过权限认证,进行发表原本插件作者只允许管理员创建和修改的自定义类型的"post"。
作者: i9n0re
简介
看到了国外有大佬发了关于WordPress的一个非常有名的插件,contact form 7的漏洞,之前见到过很多WordPress站点使用这个插件,大佬写的比较笼统,一些详细的利用方式没有说的太明白.
漏洞成因
这个漏洞是由于插件开发者对WordPress的使用不当造成的,其实跟WordPress的逻辑有一定的关系,导致了可以发布普通文章的用户,可以绕过权限认证,进行发表原本插件作者只允许管理员创建和修改的自定义类型的"post"。
漏洞作者发现了contact from 7插件存在这样的缺陷,导致了任意一个可以发表普通文章的用户,可以新建一个contact,而且在5.0.3版本下,附件可以跨目录进行添加文件,进而可以读取网站的 wp-config.php 。
相关的技术点
nonce
首先我们了解下什么是nonce?nonce相当于 csrf token 是WordPress用来防御csrf问题的,并进行了相关的权限验证。
post_type
post_type 是插件作者注册的自定义 post 类型,与WordPress的文章类似,插件作者要实现一个页面来进行管理文章类型。只有在后台的新建或者编辑页面当中可以获取到 nonce 随机数,提交的时候只有代入了nonce才能进行相应的操作。
漏洞详情
以contact form 7 v5.0.3为例。
插件作者只允许WordPress的 editor 才能新建和编辑contact。
如果是文章的发布者,就没有修改和创建权限,会显示下面的页面。
contact form 7也是一种自定义类型的 post ,数据里面都是存在了 wp_posts 表当中,通过 post_type 进行区分。
正常情况,插件作者是通过 current_user_can('publish_pages') 进行权限的判定,也就是说editor以上的权限可以编辑,防止普通用户打开新建和修改文章的页面。
但是用户仍可以操作普通的文档,通过请求接口 wp-admin/post.php 的方式进行新建和编辑文章,只不过 post_type 变为了 post 等普通文档类型。由于插件作者在 register_post_type 的时候没有进行相关权限的配置,仅仅依靠了 current_user_can('publish_pages') 验证用户编辑权限,出现了安全问题。
接下来我们来看看普通文档的新建、编辑流程。
正常流程上,普通文档上传接口是请求 post-new.php后先生成一个 post ,然后再进行编辑,请求post.php,设置参数 action 为 editpost 。
// wp-admin/post.php
case 'editpost':
check_admin_referer('update-post_' . $post_id);
$post_id = edit_post();
// Session cookie flag that the post was saved
if ( isset( $_COOKIE['wp-saving-post'] ) && $_COOKIE['wp-saving-post'] === $post_id . '-check' ) {
setcookie( 'wp-saving-post', $post_id . '-saved', time() + DAY_IN_SECONDS, ADMIN_COOKIE_PATH, COOKIE_DOMAIN, is_ssl() );
}
redirect_post($post_id); // Send user on their way while we keep working
exit();
通过函数 check_admin_referer 检测nonce是否合法。
// wp-includes/pluggable.php
// Nonce generated 0-12 hours ago
$expected = substr( wp_hash( $i . '|' . $action . '|' . $uid . '|' . $token, 'nonce'), -12, 10 );
if ( hash_equals( $expected, $nonce ) ) {
return 1;
}
// Nonce generated 12-24 hours ago
$expected = substr( wp_hash( ( $i - 1 ) . '|' . $action . '|' . $uid . '|' . $token, 'nonce' ), -12, 10 );
if ( hash_equals( $expected, $nonce ) ) {
return 2;
}
漏洞利用的地方是通过传入action为 post ,调用下面这个逻辑。
// wp-admin/post.php
case 'post':
check_admin_referer( 'add-' . $post_type );
$post_id = 'postajaxpost' == $action ? edit_post() : write_post();
redirect_post( $post_id );
exit();
其中 post_type 是通过传入的 post_id 去数据库里面查询得到。
// wp-admin/post.php
if ( $post_id )
$post = get_post( $post_id );
if ( $post ) {
$post_type = $post->post_type;
$post_type_object = get_post_type_object( $post_type );
}
可以看到,如果传入的 post_id 为正常帖子创建请求,这个地方的 nonce 普通用户就可以通过页面进行获取了。
绕过nonce检测
可以看到 post_id 是通过 $_GET['post'] 或者 $_POST['post_ID'] 两种方式获取。
// wp-admin/post.php
if ( isset( $_GET['post'] ) )
$post_id = $post_ID = (int) $_GET['post'];
elseif ( isset( $_POST['post_ID'] ) )
$post_id = $post_ID = (int) $_POST['post_ID'];
else
$post_id = $post_ID = 0;
所以如果我们构建一个存在的并且 post_type 为 post 的帖子ID作为参数传入的话, check_admin_referer 的参数变为了固定值 add-post 这样的话,如果我们拿到了nonce就可以绕过了检测。有同学会问,怎么得到这个nonce呢?通过跟代码,我发现在 dashboard 页面当中,下面这个功能里面就有我们需要的nonce,通过查看源代码,获取这个表单的input这样就绕过了检测。
<input type="hidden" id="_wpnonce" name="_wpnonce" value="xxx" />
创建自定义类型的post
绕过了nonce检测后,我们来看 post 那个case,流程会进入到 write_post 函数,然后我们看到这个逻辑。
// wp-includes/post.php
if ( !current_user_can( $ptype->cap->edit_posts ) ) {
if ( 'page' == $ptype->name )
return new WP_Error( 'edit_pages', __( 'Sorry, you are not allowed to create pages on this site.' ) );
else
return new WP_Error( 'edit_posts', __( 'Sorry, you are not allowed to create posts or drafts on this site.' ) );
}
问题就出现在这,因为作者在注册post_type的时候没有进行权限限制,导致了权限提升。
v5.0.3 的插件配置:
//wp-content/plugins/contact-form-7/includes/contact-form.php
public static function register_post_type() {
register_post_type( self::post_type, array(
'labels' => array(
'name' => __( 'Contact Forms', 'contact-form-7' ),
'singular_name' => __( 'Contact Form', 'contact-form-7' ),
),
'rewrite' => false,
'query_var' => false,
) );
}
就导致了如果绕过了nonce检测,普通用户也就可以成功的创建只有editer权限才可以创建的 contact form 7了。
进一步利用
权限提升已经完成,下面就是利用了contact from 7 v5.0.3的一个问题。
当发送邮件的时候,可以携带附件,但是这个附件可以跨目录读取,导致了用户可以直接携带 wp-config.php 进行发送,实现敏感信息的泄露。
漏洞利用
理清了漏洞触发逻辑,利用方式就简单了,在后台登录页面,直接引用 poc.js 。
注意修改几个参数
meta_input[_mail][recipient] meta_input[_mail][attachments]
然后可以在控制台里面引用,会发现新建了一个表单,然后在帖子里面正常引用这个表单,再页面中使用,并点击发送后,在自己的收件箱当中收到 wp-config.php 的附件。
漏洞修复
在注册 post_type 的时候,配置权限。
//wp-content/plugins/contact-form-7/includes/contact-form.php
public static function register_post_type() {
register_post_type( self::post_type, array(
'labels' => array(
'name' => __( 'Contact Forms', 'contact-form-7' ),
'singular_name' => __( 'Contact Form', 'contact-form-7' ),
),
'rewrite' => false,
'query_var' => false,
'capability_type' => 'page'
) );
}
如果进行了这样的配置的话,在进行 write_post 这个函数逻辑的时候
// wp-includes/post.php
if ( !current_user_can( $ptype->cap->edit_posts ) ) {
if ( 'page' == $ptype->name )
return new WP_Error( 'edit_pages', __( 'Sorry, you are not allowed to create pages on this site.' ) );
else
return new WP_Error( 'edit_posts', __( 'Sorry, you are not allowed to create posts or drafts on this site.' ) );
}
这个判断才会生效,导致权限认证失败。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Beginning ASP.NET 4 in C# and Vb
Imar Spaanjaars / Wrox / 2010-3-19 / GBP 29.99
This book is for anyone who wants to learn how to build rich and interactive web sites that run on the Microsoft platform. With the knowledge you gain from this book, you create a great foundation to ......一起来看看 《Beginning ASP.NET 4 in C# and Vb》 这本书的介绍吧!