0

我在一个文件中有以下代码,当变量$action等于某个值时,会向数据库中添加一条消息,然后向用户发送一封电子邮件,告知他们该消息。简单的。

在过去的几天里,数据库中添加了垃圾邮件,并向用户发送了电子邮件,通知他们有新消息。不是很多,也不是一次全部,只是随机的时间和内容,但显然是垃圾邮件。

我设置了脚本,以便如果$from变量不等于 0 则不要继续,但它似乎以某种方式绕过了它(所有 hack 条目进入 db show from_userid = 0

我正在使用 cookie 来检查用户是否登录 - 当用户登录时设置了 cookie。

问题:在某个地方我可以查看我是如何被黑客入侵的,我应该使用会话而不是 cookie,这会阻止文件被访问/黑客攻击吗?

继承人的代码:

// check a user logged in as soon as file accessed
if (!isset($_COOKIE['cookieName'])) { header("Location: /userlogin.html); }

现在检查$action变量并继续

$action = $_POST['action'];

if (($action=='contact') && ($_POST['from'])){ // AA

    require_once '/home/php/lib/setup.inc';
    require_once '/home/php/lib/dbconnect.inc';

    $from = mysql_real_escape_string($_POST['from']);
    $to = mysql_real_escape_string($_POST['to']);
    $from_name = mysql_real_escape_string($_POST['from_name']);
    $body = mysql_real_escape_string($_POST['body']);
    $reply_id = mysql_real_escape_string($_POST['reply_id']);

    $body = nl2br($body);

    // add message to db

    if($from!='0'){ // BB

        $additem = mysql_query("
            insert into user_messages (
            from_userid,
            to_userid,
            from_name,
            message_contents,
            reply_to_id,
            msg_read
            )
            VALUES (
            '$from',
            '$to',
            '$from_name',
            '$body',
            '$reply_id',
            'No'
            )",$db
        );

        if(!$additem) { echo mysql_error(); exit; } // debug

        // send email notif for message
        $result20 = mysql_query("select name, emailaddr from users where (user_id = '$to')",$db);
        if(!$result20) { echo 'result error'; echo mysql_error(); exit; } // debug
        $databack20 = mysql_fetch_array($result20);
        $title = 'title';
        $currentdate = date("d");
        $month = date("m");    // "02"
        $currentmonth = date("F", mktime(0, 0, 0, $month)); 
        $currentyear = date("Y");
        $email = file_get_contents('/home/public_html/pages/html_email_templates/buddymessage.php');
        $email = str_replace(">name<","$from_name",$email);
        $email = str_replace(">name2<","$databack20[name]",$email);

        // setting Content-type header
        $headers  = 'MIME-Version: 1.0' . "\r\n";
        $headers .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n";

        // Additional headers
        $headers .= 'From: siteName <info@siteName.com>' . "\r\n";

                    //send mail
        mail("$databack20[emailaddr]", "siteName Message", "$email", "$headers");

        $success = "Message sent to $databack20[name]";

    } // BB

} // AA
4

3 回答 3

5

看来这里真正的问题是任何人都可以提交任何POST请求,而您没有检查它是否真的是他们。制作一个执行以下操作的机器人真的很容易(并使用00infrom而不是0,因此绕过了您的“安全性”-我建议改为转换为 int :$from = (int)$from然后检查if ($from > 0),但这不是您真正的问题):

POST http://www.domain.com/contact.php
action= contact &
from= 00 &
body= spam &
from_name= spammer & to
= 1

POST http://www.domain.com/contact.php
action= contact &
from= 00 &
body= spam &
from_name= spammer & to
= 2 <-- 循环增加

它甚至可以用 PHP 编写,如下所示:

<?php
    $curlHandle = curl_init();
    
    for ($i = 1; $i < 10000; $i++) {
        curl_setopt_array($curlHandle, array(
            CURLOPT_URL            => "http://www.domain.com/contact.php",
            CURLOPT_POST           => true,
            CURLOPT_COOKIE         => "cookieName: yep",
            CURLOPT_POSTFIELDS     => array(
                "action"    => "contact",
                "from"      => rand(1, 10000),
                "to"        => $i,
                "body"      => "Spam",
                "from_name" => "Spambot"
            )
        ));
        curl_exec($curlHandle);
    }
?>

因此,您应该使用$_SESSIONcookie 来检查它来自谁。也许还可以限制每n分钟只能发送一条消息。

于 2013-04-29T16:42:26.420 回答
0

您的问题是当攻击者在那里填写一个非整数值时,该值由数据库转换为整数:零。

检查是否$from为整数:

if ($from > 0 && (string)((int)$from) === $from) { /* ... */ }

Ps:您应该真正将用户数据存储在 a$_SESSION中,而不是让用户有可能操纵您的隐藏输入。

于 2013-04-29T16:39:57.750 回答
0

如果不了解攻击者的方法,我们无法直接回答“如何”的问题。但是,这里有一些可能会有所帮助的步骤。

这些mysql_*函数在 PHP 中已被弃用,取而代之的是PDO。您应该更新您的代码以使用 PDO 来利用它提供的新安全功能。

此外,验证对您的数据库的访问没有受到损害。您可能需要检查数据库日志以了解意外登录事件。

同时,在您重写代码时,请考虑将以下行替换为对 $_SESSION 的更安全调用:

if (!isset($_COOKIE['cookieName'])) { header("Location: /userlogin.html); }

当您使用此代码时,恶意用户可以创建一个 cookie 来绕过您的登录要求。

于 2013-04-29T16:38:56.533 回答