02-02-2016 / Vulnerabilities

Profile Builder 2.2.4 Reflected XSS

$_GET['loginerror'] is not escaped.

File: profile-builder\front-end\login.php

// display our login errors
if( isset( $_GET['loginerror'] ) || isset( $_POST['loginerror'] ) ){
    $loginerror = isset( $_GET['loginerror'] ) ? $_GET['loginerror'] : $_POST['loginerror'];
    $loginerror = '<p class="wppb-error">'.urldecode( base64_decode( $loginerror ) ).'</p><!-- .error -->';
    if( isset( $_GET['request_form_location'] ) ){
        if( $_GET['request_form_location'] == 'widget' && !in_the_loop() ){
            $login_form .= $loginerror;
        }
        elseif( $_GET['request_form_location'] == 'page' && in_the_loop() ){
            $login_form .= $loginerror;
        }
    }
}

Similar issue exists also inside wck_single_metabox_errors_display(). There $_GET['wckerrorfields'] and $_GET['wckerrormessages'] are not escaped properly.

File: profile-builder\assets\lib\wck-api\wordpress-creation-kit.php

/* mark the fields */
if( isset( $_GET['wckerrorfields'] ) && !empty( $_GET['wckerrorfields'] ) ){
    echo '<script type="text/javascript">';
    $field_names = explode( ',', urldecode( base64_decode( $_GET['wckerrorfields'] ) ) );
    foreach( $field_names as $field_name ){
        echo "jQuery( '.field-label[for=\"". $field_name ."\"]' ).addClass('error');";
    }
    echo '</script>';
}
/* alert the error messages */
if( isset( $_GET['wckerrormessages'] ) ){
    echo '<script type="text/javascript">alert("'. urldecode( str_replace( '%0A', '\n', base64_decode( $_GET['wckerrormessages'] ) ) ) .'")</script>';
}

Proof of Concept

login-page is page where shortcode [wppb-login] is used.

http://wordpress-url/login-page?loginerror=PHNjcmlwdD5hbGVydChkb2N1bWVudC5jb29raWUpOzwvc2NyaXB0Pg&request_form_location=page

Timeline

  • 27-10-2015: Discovered
  • 27-10-2015: Vendor notified
  • 11-11-2015: Version 2.2.5 released, issue resolved