본문 바로가기
Bug Bounty/PoC 분석

[CVE Study]Ultimate Member 권한 상승 취약점 분석(Exploit for CVE-2020-36155, CVE-2023-3460)

by m_.9m 2024. 1. 21.

Ultimate Member에서 발생한 권한 상승

Ultimate Member는 활성 설치수가 200,000이 넘는 플러그인으로 사용자 등록, 멤버십 기능을 제공합니다. 2020년 11월 wp_capabilities의 기능을 악용한 권한 상승 취약점(CVE-2020-36155)이 2.1.11 이하 버전에서 발견됐습니다.

 

CVE-2020-36155은 사용자 등록 기능에서 발생합니다. 가입하는 과정에서 임의의 데이터를 추가해 권한 상승이 가능했습니다. 간단하게 설명해 가입 시 '권한=관리자'라는 값을 추가하면 관리자로 권한이 설정되는 취약점입니다. 취약점은 사용자의 입력 값을 필터링하지 않고 그대로 데이터베이스에 업데이트하기 때문에 발생합니다.

 

이후 이 취약점은  2.1.12 버전에서 패치되었습니다. Ultimate Member는 블랙리스트 기반 필터링을 사용합니다. 허용되지 않은 메타 데이터 키를 설정하고 if 문을 통해 필터링을 합니다. 이로 인해 사용자는 임의의 값(예를 들어, '권한=관리자' )을 입력할 수 없었습니다. 하지만 2023년에 이 필터링을 우회한 권한 상승 취약점(CVE-2023-3460)이 2.6.7 이하의 버전에서 다시 발생하였습니다.

 

CVE-2023-3460은 구현된 필터링을 악센트 문자( à, è, ì, ò, ù )를 통해 우회합니다. 워드프레스는 악센트 문자를 일반 문자처럼 받아들여 데이터베이스에 저장합니다. 하지만, 코드로 구현된 필터링은 이 문자를 잡아내지 못했으며, 이를 통해 권한 상승이 가능했습니다. 이후 화이트리스트 기반으로 필터링을 구현해 취약점을 패치했습니다.

 

아래에서 코드와 실습을 통해 살펴보겠습니다.

 

wp_capability 란?

Wordpress는 wp_capabilities로 사용자의 역할과 권한을 관리합니다.

 

워드프레스는 사용자의 기본 값(아이디, 비밀번호, 이메일 등)을 wp_user 테이블,  기타 값(권한, 닉네임 등)을 wp_usermeta 테이블에 저장합니다. wp_capabilities는 wp_usermeta 테이블에서 사용자 역할과 권한 데이터를 저장합니다.

 

아래 예시 데이터를 보면 사용자의 권한이 administrator 저장된 것을 확인할 수 있습니다. 

 

* wp_capabilities 및 워드프레스 테이블에 대한 자세한 설명은 아래에서 확인하실 수 있습니다.

2024.02.15 - [Bug Bounty/PoC 분석] - ProfilePress 권한 상승 취약점 분석(Exploit for CVE-2021-34621)

 

CVE-2020-36155에 대한 이해

2020년에 먼저 발생한 CVE-2020-36155를 먼저 살펴보겠습니다.
 
플러그인은 register 페이지에서 입력된 데이터로 데이터베이스의 값을 업데이트 합니다. 이 과정에서 별도의 필터링을 하지 않아 공격자가 임의의 메타 키를 삽입해 관리자 권한을 얻을 수 있습니다. 

do_action( 'um_before_save_registration_details', $this->id, $submitted );

    update_user_meta( $this->id, 'submitted', $submitted );

    $this->update_profile( $submitted );

function update_profile( $changes ) {

    $args['ID'] = $this->id;

$changes = apply_filters( 'um_before_update_profile', $changes, $args['ID'] );

    foreach ( $changes as $key => $value ) {
        if ( ! in_array( $key, $this->update_user_keys ) ) {
            if ( $value === 0 ) {
                update_user_meta( $this->id, $key, '0' );
            } else {
                update_user_meta( $this->id, $key, $value );
            }
        } else {
            $args[ $key ] = esc_attr( $changes[ $key ] );
        }
    }

 
위는 user_meta를 업데이트하는 부분의 코드입니다. 데이터를 받아오는 과정부터 업데이트 하는 과정까지 필터링 로직이 구현되지 않았습니다. 공격자는 register 프로세스에서 wp_capabilities[administrator] 값을 추가하면  관리자 권한을 얻을 수 있습니다. 아래 실습을 통해 취약점을 더 이해해보도록 하겠습니다.
 

CVE-2020-36155 PoC

취약점 정보

Vulnerability type: Privilege Escalation
CVSS Severity Score: 10
Affected Versions: < 2.1.12
Patched Available: YES
PoC Link:
Ultimate Member < 2.1.12 - Unauthenticated Privilege Escalation via User Meta
취약한 버전 파일:

ultimate-member.2
2.16MB

 
 

실습

1. PoC 테스트를 위해 Ultimate Member 2.6.6 버전으로 테스트를 진행합니다.

 
2. 플러그인이 활성화되면 register 페이지에 데이터를 입력하고 등록합니다.

 
3. Burp Suite를 통해 요청을 가로챈 후 기존의 요청에서 페이로드 wp_capabilities[administrator]=0를 추가해 전송합니다.

 
4. WordPress 대시보드에서 사용자 권한이 관리자로 설정된 것을 확인합니다.

 
 

취약점 패치와 CVE-2023-3460에 대한 이해

CVE-2020-36155 취약점 이후 Ultimate Member는 register 과정에 필터링 로직을 추가했습니다. 아래 is_metakey_banned()를 통해 허용되지 않은 입력을 차단합니다. 필터링은 금지된 메타데이터 목록을 사용하기 때문에 블랙리스트 기반 방식으로 구현되었습니다.

 

public function update_profile( $changes ) {
    $this->updating_process = true;
    $args['ID']             = $this->id;

$changes = apply_filters( 'um_before_update_profile', $changes, $args['ID'] );

//사용자 메타 데이터 키 목록 사용
    foreach ( $changes as $key => $value ) {
        if ( $this->is_metakey_banned( $key ) ) {
            continue;
        }

        if ( ! in_array( $key, $this->update_user_keys, true ) ) {
            if ( $value === 0 ) {
                update_user_meta( $this->id, $key, '0' );
            } else {
                update_user_meta( $this->id, $key, $value );
            }
        } else {
            $args[ $key ] = $value;
        }
    }

public function is_metakey_banned( $meta_key ) {
    $is_banned = false;
    //제출된 메타데이터가 금지된 메타데이터 목록에 있으면 ture를 반환해 break.
    foreach ( $this->banned_keys as $ban ) {
        if ( is_numeric( $meta_key ) || false !== stripos( $meta_key, $ban ) ) {
            $is_banned = true;
            break;
        }
    }

    //필터링에 걸리지 않으면 false를 반환하고 사용자 등록을 허용.
    return $is_banned;
}

 

 

 

CVE-2023-3460 필터링은 악센트  문자 (à) 를 통해 우회되었습니다.

 

WordPress는 일부 악센트(강세표시) 문자를 기본 문자로 수용합니다. 사용자가 악센트 문자와 함께 메타데이터를 제출하면 is_metakey_banned()는 이를 감지하지 못해 사용자 등록을 허용하고 공격자는 관리자 권한을 얻을 수 있습니다. 따라서 wp_càpabilities[administrator]를 통해 사용자 권한 상승 취약점이 발생합니다.

 data["wp_c𝙖pabilities[administrator]"] = "0"
    #data["wp_càpàbilities[administrator]"] = ""

 

CVE-2023-3460 PoC

취약점 정보

Vulnerability type: Privilege Escalation
CVSS Severity Score: 9.8
Affected Versions: =< 2.6.7
Patched Available: YES
PoC Link:
Analyzing the Ultimate Member Plugin Vulnerability - CVE-2023-3460 - CYFIRMA
취약한 버전 파일:

ultimate-member.2
1.97MB

 

실습

1. PoC 테스트를 위해 Ultimate Member 2.6.6 버전으로 테스트를 진행합니다.

 
2. 플러그인이 활성화되면 register 페이지에 데이터를 입력하고 등록 요청을 보냅니다.

 
3. Burp Suite를 통해 요청을 가로챈 후 기존의 요청에서 페이로드 wp_càpabilities[administrator]=1를 추가해 전송합니다.

 
4. WordPress 대시보드에서 사용자 권한이 관리자로 설정된 것을 확인합니다.

 

취약점 패치

Ultimate Member는 취약점을 2.6.7 버전에서 수정했습니다. 수정된 내용은 아래와 같습니다.

ultimate-member.2
1.97MB

 
 
 

public function is_metakey_banned( $meta_key, $context = '' ) {
    $is_banned = false;
    foreach ( $this->banned_keys as $ban ) {
        if ( is_numeric( $meta_key ) || false !== stripos( $meta_key, $ban ) || false !== stripos( remove_accents( $meta_key ), $ban ) ) {
            $is_banned = true;
            break;
        }
    }

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

    return $is_banned;
}

취약점이 발생했던  is_metakey_banned()가 수정되었습니다. 해당 함수는 in_array( $meta_key, UM()->form()->usermeta_whitelist로 화이트 리스트 검증을 수행합니다.

화이트 리스트의 필터는 0: user_login, 1: form_id, 2: timestap 세개의 필드로만 구성됩니다. 따라서 공격자는 강조표시 문자를 통해 권한 우회 취약점을 악용할 수 없습니다.

참고 블로그
https://wordpress.stackexchange.com/questions/103492/whats-the-meaning-of-the-field-wp-capabilities-in-table-wp-usermeta
https://sploitus.com/exploit?id=5434DDF9-58E8-5271-BBBC-66EED3F5A6C8