报价通知插件中的漏洞

时间:2017-02-07 06:54:26

标签: php mysql vbulletin

以下插件用于为vbulletin论坛中的成员提供通知。

一位朋友告诉我,由于这个插件,Mysql数据库可能存在漏洞。我不是mysql专家,所以我不知道究竟是什么问题。

如果有人发现此漏洞,我想知道我该怎么做才能解决它。

使用插件来到这个php页面,它将显示成员http://textuploader.com/d1hch的通知列表  不确定这个php脚本是否有任何漏洞

这个问题可能与mysqli :: escape_string或PDO准备好的声明有关。

<?xml version="1.0" encoding="ISO-8859-1"?>

<product productid="k_quote_notifications" active="0">
    <title>Quote Notifications</title>
    <description>Notify User after being quoted</description>
    <version>1.0.0</version>
    <url></url>
    <versioncheckurl></versioncheckurl>
    <dependencies>
    </dependencies>
    <codes>
        <code version="1.0.0">
            <installcode><![CDATA[$db->hide_errors();
$db->query_write("
CREATE TABLE   " . TABLE_PREFIX . "quotedatanew (
  `quoted` int(10) NOT NULL default '0',
  `quoter` int(10) NOT NULL default '0',
  `quotername` varchar(255) NOT NULL default '0',
  `postid` int(10) NOT NULL default '0',
  `threadid` int(10) NOT NULL default '0',
  `threadtitle` varchar(255) NOT NULL default '0',
  `dateline` int(10) NOT NULL default '0',
  `hasseen` int(1) NOT NULL default '0',
  KEY `quoted` (`quoted`)
)
");
$db->show_errors();]]></installcode>
            <uninstallcode><![CDATA[$db->query_write("
 DROP TABLE " . TABLE_PREFIX . "quotedatanew
");]]></uninstallcode>
        </code>
    </codes>
    <templates>
        <template name="NOTI" templatetype="template" date="1401826799" username="AAA" version="1.0.0"><![CDATA[$stylevar[htmldoctype]
<html dir="$stylevar[textdirection]" lang="$stylevar[languagecode]">
<head>
<title>$vboptions[bbtitle]</title>

<style type="text/css">
.alert-box {
    color:#555;
    border-radius:10px;
    font-family:Tahoma,Geneva,Arial,sans-serif;font-size:11px;
    padding:10px 36px;
    margin:10px;
}
.alert-box span {
    font-weight:bold;
    text-transform:uppercase;
}
.error {
    background:#ffecec url('images/error.png') no-repeat 10px 50%;
    border:1px solid #f5aca6;
}
.success {
    background:#e9ffd9 url('images/success.png') no-repeat 10px 50%;
    border:1px solid #a6ca8a;
}
.warning {
    background:#fff8c4 url('images/warning.png') no-repeat 10px 50%;
    border:1px solid #f2c779;
}
.notice {
    background:#e3f7fc url('images/notice.png') no-repeat 10px 50%;
    border:1px solid #8ed9f6;
}
.paginate {
font-family:Arial, Helvetica, sans-serif;
    padding: 3px;
    margin: 3px;
}

.paginate a {
    padding:2px 5px 2px 5px;
    margin:2px;
    border:1px solid #999;
    text-decoration:none;
    color: #666;
}
.paginate a:hover, .paginate a:active {
    border: 1px solid #999;
    color: #000;
}
.paginate span.current {
    margin: 2px;
    padding: 2px 5px 2px 5px;
        border: 1px solid #999;

        font-weight: bold;
        background-color: #999;
        color: #FFF;
    }
    .paginate span.disabled {
        padding:2px 5px 2px 5px;
        margin:2px;
        border:1px solid #eee;
        color:#DDD;
    }

 </style>
$headinclude
</head>
<body>
$header

$navbar

<table class="tborder" cellpadding="$stylevar[cellpadding]" cellspacing="$stylevar[cellspacing]" border="0" width="100%" align="center">
<tr>
    <td class="tcat">$vbphrase[notification_page_title]</td>
</tr>
<tr>
    <td class="alt1">$content</td>
</tr>
$paginate
</table>

$footer
</body>
</html>]]></template>
        <template name="TEST" templatetype="template" date="1401824077" username="AAA" version="1.0.0"><![CDATA[$stylevar[htmldoctype]
<html dir="$stylevar[textdirection]" lang="$stylevar[languagecode]">
<head>
<title>$vboptions[bbtitle]</title>
$headinclude
</head>
<body>
$header

$navbar

<table class="tborder" cellpadding="$stylevar[cellpadding]" cellspacing="$stylevar[cellspacing]" border="0" width="100%" align="center">
<tr>
    <td class="tcat">Title</td>
</tr>
<tr>
    <td class="alt1">Text</td>
</tr>
</table>

$footer
</body>
</html>]]></template>
    </templates>
    <plugins>
        <plugin active="1" executionorder="5">
            <title>Get Notifications</title>
            <hookname>global_start</hookname>
            <phpcode><![CDATA[$counter = $vbulletin->db->query_first("SELECT COUNT(*) AS id FROM quotedatanew where quoted =" . $vbulletin->userinfo['userid'] . " and hasseen= '0'");
$count   = $counter['id'];
$notifi  = $vbulletin->db->query_read("SELECT * FROM quotedatanew where quoted =" . $vbulletin->userinfo['userid'] . " and hasseen = '0' ORDER BY dateline DESC LIMIT 4");
while ($noti = $vbulletin->db->fetch_array($notifi)) {
    $threadurl    = $vbulletin->options['bburl'] . '/showthread.php?source=noti&p=' . $noti['postid'] . '#post' . $noti['postid'];
    $memberurl    = $vbulletin->options['bburl'] . '/member.php?u=' . $noti['quoter'];
    $notiurl      = $vbulletin->options['bburl'] . '/noti.php';
    $qoutername   = $noti['quotername'];
    $threadname   = $noti['threadtitle'];
    $phrasequote  = $vbphrase['has_quoted_your_post_in'];
    $seeallphrase = $vbphrase['see_all_noti'];
    $notihtml .= '<tr><td class="vbmenu_option" style="white-space:normal;max-width:200px;"><a href="' . $memberurl . '">' . $qoutername . '</a> ' . $phrasequote . ' <a href="' . $threadurl . '">' . $threadname . '</a></td></tr>';
}
if ($count > 4) {
    $notihtml .= '<tr><td class="vbmenu_option" style="white-space:normal;max-width:200px;"><a href="' . $notiurl . '">' . $seeallphrase . '</a></td></tr>';
}]]></phpcode>
        </plugin>
        <plugin active="1" executionorder="5">
            <title>Insert Notification</title>
            <hookname>newpost_complete</hookname>
            <phpcode><![CDATA[if ($vbulletin->options['wqm_system'] == true) {


    if (preg_match('/\[quote=(.*?)\]((?:.|\s)+?)\[\/quote\]/i', $post['message'])) {
        preg_match_all('/\[quote=(.*?)\]((?:.|\s)+?)\[\/quote\]/i', $post['message'], $quotematch);

        $quotecount = count($quotematch[0]);
        $tempcount  = 0;
        $quotearray = array();


        while ($tempcount < $quotecount) {
            $username     = explode(';', $quotematch[1][$tempcount]);
            $quoteduserid = $vbulletin->db->query_first("SELECT userid FROM " . TABLE_PREFIX . "user
            WHERE username = '" . $vbulletin->db->escape_string(htmlspecialchars_uni($username[0])) . "'");

            if (!in_array($quoteduserid['userid'], $quotearray)) {
                if ($quoteduserid['userid'] > 0 AND $quoteduserid['userid'] != $vbulletin->userinfo['userid']) {
                    $quotearray[] = $quoteduserid['userid'];

                    // check forum permissions
                    $quoteduserinfo = fetch_userinfo(intval($quoteduserid['userid']));
                    $forumperms     = fetch_permissions($foruminfo['forumid'], intval($quoteduserid['userid']), $quoteduserinfo);

                    if (!($forumperms & $vbulletin->bf_ugp_forumpermissions['canview']) OR !($forumperms & $vbulletin->bf_ugp_forumpermissions['canviewthreads'])) {
                        $tempcount++;
                        continue;
                    }
                    if (!($forumperms & $vbulletin->bf_ugp_forumpermissions['canviewothers']) AND ($threadinfo['postuserid'] != intval($quoteduserid['userid']) OR $vbulletin->userinfo['userid'] == 0)) {
                        $tempcount++;
                        continue;
                    }

                    $vbulletin->db->query_write("
                    INSERT INTO " . TABLE_PREFIX . "quotedatanew (quoted,quoter,postid,threadid,threadtitle,dateline,quotername)
                    VALUES ('" . $quoteduserid['userid'] . "','" . $vbulletin->userinfo['userid'] . "','" . $post['postid'] . "','" . $threadinfo[threadid] . "','" . $vbulletin->db->escape_string(htmlspecialchars_uni($threadinfo[title])) . "','" . time() . "','" . $vbulletin->db->escape_string(htmlspecialchars_uni($vbulletin->userinfo['username'])) . "')");
                }
            }
            $tempcount++;
        }
    }


}]]></phpcode>
        </plugin>
        <plugin active="1" executionorder="5">
            <title>Dismiss notification</title>
            <hookname>showthread_start</hookname>
            <phpcode><![CDATA[$postid = intval($_GET["p"]);
$source = $_GET["source"];
if ($source == "noti") {
    $vbulletin->db->query_write("update quotedatanew set hasseen = '1' where postid = '" . $postid . "' and quoted = '" . $vbulletin->userinfo['userid'] . "'");
}]]></phpcode>
        </plugin>
    </plugins>
    <phrases>
        <phrasetype name="GLOBAL" fieldname="global">
            <phrase name="delete_all_nots" date="1401999437" username="bbb" version="1.0.0"><![CDATA[Õ–› ÄÌ⁄ «· ‰»Ì« ]]></phrase>
            <phrase name="has_quoted_your_post_in" date="1401739493" username="AAA" version="1.0.0"><![CDATA[Has Quoted Your Post In]]></phrase>
            <phrase name="no_notification_text" date="1401999471" username="bbb" version="1.0.0"><![CDATA[·« ÌÊÃœ  ‰»Ì«  Ü̜…]]></phrase>
            <phrase name="noti_icon" date="1401829523" username="AAA" version="1.0.0"><![CDATA[Notifications]]></phrase>
            <phrase name="notification_read" date="1401825953" username="AAA" version="1.0.0"><![CDATA[Read]]></phrase>
            <phrase name="notification_unread" date="1401826023" username="AAA" version="1.0.0"><![CDATA[Unread]]></phrase>
            <phrase name="see_all_noti" date="1401810412" username="AAA" version="1.0.0"><![CDATA[See All Notification]]></phrase>
        </phrasetype>
        <phrasetype name="vBulletin Settings" fieldname="vbsettings">
            <phrase name="setting_wqm_system_desc" date="1401828337" username="AAA" version="1.0.0"><![CDATA[<style type="text/css">
body { background:#555;color:white; }
a:link, a:visited, a:active { color:white; }
.optiontitle { background:#10a113;color:#FFF;border:none; }
.button { background:#10A113;border:none;color:white;padding:6px 12px;}
.button:hover { background:#057c08; }
.tcat { color:white;background: #111;border:none; }
.tcat a:link, .tcat a:visited, .tcat a:active { color:white; }
.tfoot { background:#111;border:none; }
.alt1 { color:white;background:#333; }
.tborder { border:1px solid #000; -moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;-moz-box-shadow: 2px 2px 8px #000;-webkit-box-shadow: 2px 2px 8px #000;box-shadow: 2px 2px 8px #000; }
textarea, .bginput, input.col-c, input.col-i, input.col-g { border:1px solid #000;color:#EEE;background:#444; }
.pagetitle { background:#111;color:white;border:1px solid #000;-moz-box-shadow: 2px 2px 8px #000;-webkit-box-shadow: 2px 2px 8px #000;box-shadow: 2px 2px 8px #000; }
</style>]]></phrase>
            <phrase name="setting_wqm_system_title" date="1401828337" username="AAA" version="1.0.0"><![CDATA[Enable Notifications System]]></phrase>
            <phrase name="settinggroup_Notification System" date="1401828329" username="AAA" version="1.0.0"><![CDATA[Notification System]]></phrase>
        </phrasetype>
    </phrases>
    <options>
        <settinggroup name="Notification System" displayorder="590">
            <setting varname="wqm_system" displayorder="10">
                <datatype>boolean</datatype>
                <optioncode>yesno</optioncode>
                <defaultvalue>1</defaultvalue>
            </setting>
        </settinggroup>
    </options>
    <helptopics>
    </helptopics>
    <cronentries>
    </cronentries>
    <faqentries>
    </faqentries>
</product>

1 个答案:

答案 0 :(得分:0)

我在这段代码中看到的唯一潜在问题是查询是通过连接字符串而不是使用预准备语句构建的,例如:

        $quoteduserid = $vbulletin->db->query_first("SELECT userid FROM " . TABLE_PREFIX . "user
        WHERE username = '" . $vbulletin->db->escape_string(htmlspecialchars_uni($username[0])) . "'");

这会将查询暴露给潜在的sql注入攻击。

我在代码中看到采取了预防措施,例如where子句中的username由以下内容组成:

username = '" . $vbulletin->db->escape_string(htmlspecialchars_uni($username[0])) . "'"

username被转义为db->escape_string,可以防止注入攻击。但是该函数中的错误可能导致代码不安全。

进行查询的唯一推荐和防弹方法是使用准备好的目标。

此处为prepared statements mysqli

的链接

准备好的语句允许您将要在查询中使用的参数(例如用户名)直接传递给mysqli或pdo。使用这种方法,参数中的字符或字符序列无法“中断”查询,因为在通过串联静态字符串和(转义的)变量值构建查询时可能会发生这种情况。

如果您想改进代码,则必须在“准备好的声明表单”中替换每个查询。

准备语句查询很容易(只需检查$vbullettin->db是否是mysqli或PDO连接以使用正确的方法)。

因为必须传递参数未转义,您应该检查$vbulletin->db->escape_string实际上做了什么(在示例中),以便存储在数据库中的数据保持其格式。