如何通过过滤php中的URL参数来阻止SQL注入攻击?

时间:2018-03-05 02:46:51

标签: php sql-injection

我目前受到以下格式的网址攻击:

/act/test.php?CourseId=66'+and(%2f**%2fsElEcT+1+%2f**%2ffRoM(%2f**%2fsElEcT+count(*),%2f**%2fcOnCaT((%2f**%2fsElEcT(%2f**%2fsElEcT(%2f**%2fsElEcT+%2f**%2fcOnCaT(0x217e21,ifnull(MailingDate,char(32)),0x217e21)+%2f**%2ffRoM+contin5_Mailing.Customers+%2f**%2flImIt+1400,1))+%2f**%2ffRoM+information_schema.%2f**%2ftAbLeS+%2f**%2flImIt+0,1),floor(rand(0)*2))x+%2f**%2ffRoM+information_schema.%2f**%2ftAbLeS+%2f**%2fgRoUp%2f**%2fbY+x)a)+and+'1'='1

/act/index.php?Ad=999999.9+%2f**%2fuNiOn%2f**%2faLl+%2f**%2fsElEcT+0x393133353134353632312e39

我希望在我网站的PHP处理早期对网址进行合理直接的验证来阻止这些类型的攻击。<​​/ p>

由于此类攻击的签名似乎是&#34;%2f *&#34; (意思是&#34; / *&#34;这是注入评论,我猜),我使用了这种针对这种特定攻击的Hamfisted方法:

$UrlParms = $_SERVER['REQUEST_URI'];
$FoundAnomalies = (strpos($UrlParms, '%2f*'));  //* If we found anomalies in the parameters
if ($FoundAnomalies)
{
   LogErrorToFileOnly("BOGUS URL: ".$FoundAnomalies." ".$UrlParms);
   die();
}

将错误记录到文件中并在实际输出任何HTML之前消失。通过在实际打开数据库并执行此失败的SQL注入之后提前失败而不是更晚失败,这大大减少了我的服务器上的CPU和内存负载。

我知道这是一种&#34;打击鼹鼠&#34;方法,但你能告诉我这是否合理,是否有任何其他字符串可以指示SQL注入攻击?或者指向任何可以更好地处理这个问题的通用PHP代码?请注意,我只对在PHP执行中很早就查看URL和参数的代码感兴趣,并且不知道哪些参数在代码中稍后合法使用。

历史记录:我在15年前使用PHP和MySQL编写了这个电子商务代码,并且它一直延续至今。但是,时间标准并没有真正考虑这种类型的安全性,我也不知道SQL注入是否在当时存在。重写整个网站所需的努力并不值得,所以请不要告诫我擦洗每个参数等等。我今天会用不同的方式写出来,但我只是想尝试一下在php处理中首先用简单的URL过滤检测SQL注入,然后中止。

最终编辑5/11/2018:

尽管反对者,我已经创建了一些PHP代码和Javascript,可以很好地解决这个问题(以及许多相关问题),并且一直在挫败活跃的黑客攻击我的商业网站。它已经工作了两个月了。代码发布在我的答案下面。

2 个答案:

答案 0 :(得分:1)

有些网络应用防火墙产品使用网址列入白名单作为过滤掉任何未经授权的网址的尝试。

  • GreenSQL的
  • Oracle数据库防火墙
  • Apache mod_security

一般来说,你需要教授&#34;这些防火墙是什么类型的URL是合法的,然后防火墙拒绝任何不在白名单URL列表中的请求。

但在我看来,修复代码以使用SQL查询参数比将WAF产品集成到您的网站中要少。

如果你想避免一次性重写大量代码,你更喜欢&#34; whack-a-mole&#34;方法,我鼓励您一次修复一个PHP页面中的代码,因为您检测到尝试的SQL注入攻击。当然,从index.php开始。如果攻击者发现主页对SQL注入有抵抗力,那么大多数人可能会认为其余页面也是安全的,并转移到其他网站。但你永远不知道,他们可能只是测试你网页的所有。如果你是黑客,不是吗?

这仍然不是一个好计划,因为如果你推迟修改代码,你会想要被黑客攻击。但至少随着时间的推移它会扩展工作。

P.S。:你评论说15年前SQL注入可能不是一件事,但事实上:

  

SQL注入的第一次公开讨论开始于1998年左右出现;例如,1998年Phrack杂志的一篇文章。

那是20年前的事了!

请参阅https://en.wikipedia.org/wiki/SQL_injection#History

答案 1 :(得分:1)

最后更新5/11/2018:

好的,这是我对自己问题的最终答案,经过几周的精心构建,并在我的活跃电子商务网站上进行了两个月的测试。它非常有效。

这也阻止了其他类型的非SQL注入攻击,例如尝试注入虚假博客帖子以及其他尝试使用网址和其他碎片注入全局变量。

//************ Foil SQL injection attacks early by validating the URL and parameters ********
//*** Rejecting a bunch of special characters - make sure to change in both places if you change this!
function VerifyURL()
{
    global $URL_LOG;
    global $BOGUSURL_LOG;

$RejectChars = "'\"%;\\/()[]";  //* If you change this, also change the Javascript below
    $SleepTime = rand(2, 15);   //* Seconds to sleep to slow down the hackers (random to confuse them)

//* REQUEST_URI breaks down to: SCRIPT_NAME, PATH_INFO, QUERY_STRING
    $UrlParms = $_SERVER['REQUEST_URI'];
$ScriptName = $_SERVER['SCRIPT_NAME'];
$PathInfo = $_SERVER['PATH_INFO'];
$QueryString = $_SERVER['QUERY_STRING'];
$ClientIPAddress = str_pad($_SERVER['REMOTE_ADDR'], 15);

//* We don't use PATH_INFO (extra "/something/" after the SCRIPT_NAME) so this is always BOGUS
if (isset($PathInfo))
{
    LogToFileOnly($ClientIPAddress." *BOGUS PATH_INFO: ".$UrlParms, $URL_LOG);
    LogToFileOnly($ClientIPAddress." *BOGUS PATH_INFO: ".$UrlParms, $BOGUSURL_LOG);
    if (!empty($_POST))  //* Log any POST data, too, to help analyze the intent of this attack
    {
        LogArrayToFileOnly($ClientIPAddress." *BOGUS POST Array:", $_POST, $URL_LOG);
            LogArrayToFileOnly($ClientIPAddress." *BOGUS POST Array:", $_POST, $BOGUSURL_LOG);
    }
    sleep($SleepTime);  //* Slow down the hackers
    die();
}

    //* Look for unusual characters that should not be in the URL and abort
    $FoundAnomalies = (strpbrk($QueryString, $RejectChars));
    $Exception = strpos($ScriptName, "/srch.php");  //* if this is the search page, let it through
    $Exception |= strpos($ScriptName, "/amn2/");    //* if this is an admin page, let it through

    if ($FoundAnomalies && !$Exception)
    {
        LogToFileOnly($ClientIPAddress." *BOGUS URL: ".$UrlParms, $URL_LOG);
        LogToFileOnly($ClientIPAddress." *BOGUS URL: ".$UrlParms, $BOGUSURL_LOG);
    if (!empty($_POST))  //* Log any POST data, too, to help analyze the intent of this attack
    {
        LogArrayToFileOnly($ClientIPAddress." *BOGUS POST Array:", $_POST, $URL_LOG);
            LogArrayToFileOnly($ClientIPAddress." *BOGUS POST Array:", $_POST, $BOGUSURL_LOG);
    }
    sleep($SleepTime);  //* Slow down the hackers
        die();
    }
    else
        LogToFileOnly($ClientIPAddress." Valid URL: ".$UrlParms, $URL_LOG);

    //* Now look for unusual characters injected into a POST, if a POST was sent
    if (!empty($_POST) && !$Exception)
    {
        foreach ($_POST as $key => $value)
        {
            //* Validate both keys and values
            $FoundAnomalies = (strpbrk($key, $RejectChars) || strpbrk($value, $RejectChars));
            //$Exception = ($key == "AmnMsg");    //* if this is the admin emailing message page, let it through - we want to email urls and stuff
            if ($FoundAnomalies && !$Exception)
            {
                //* Found an anomaly, report it and die
                LogArrayToFileOnly($ClientIPAddress." *BOGUS POST Array:", $_POST, $URL_LOG);
        LogToFileOnly($ClientIPAddress." Valid URL: ".$UrlParms, $BOGUSURL_LOG);
                LogArrayToFileOnly($ClientIPAddress." *BOGUS POST Array:", $_POST, $BOGUSURL_LOG);
        sleep($SleepTime);  //* Slow down the hackers
                die();
            }
        }
        LogArrayToFileOnly($ClientIPAddress." Valid POST Array:", $_POST, $URL_LOG);
    }
}

//*** This code is added near the bottom of the page, and is for javascript filtering, but could be for other purposes
function FinalHTMLCode()
{
//* Attach a filter to every text input field to filter prohibited characters using javascript
echo '
     <script>
         //* Set the key filtering for every text type input field in the entire page
     var node = document.querySelectorAll("input[type=text],input[type=password],textarea");
     for (var i = 0, len = node.length; i < len; i++)
     {
         node[i].addEventListener("keyup", OnKeyUpEvent);  //* Filter later on keypresses (and paste)
         FilterInputChars(node[i]);                        //* Do the filtering immediatly, too
     }

     function OnKeyUpEvent()
     {
         FilterInputChars(this);
     }

     function FilterInputChars(textfield)
     {
         //* Remove prohibited characters globally in this field - also works when user pastes text!
         textfield.value=textfield.value.replace(/[\\\'\"%\;\\\\/()\[\]]/g,\'\');
     }
    </script>
';  //* End echo
}

这种方法的首要好处是它可以在处理的早期检测到黑客攻击,并且只是die(),因此不会导致开放数据库等的额外CPU负载,并且没有进一步向黑客提供有关原因的信息尝试失败了。我还添加了代码,通过随机延迟响应来混淆活跃的黑客(参见sleep()),所以他认为他正在完成某些事情。

合法用户不得在表单中输入这些禁止的字符,因此我设置了一些自动过滤所有特殊字符的Javascript。您可以将这一行代码放在HTML底部附近,它会自动将Javascript附加到每个文本字段并过滤字符:

<?php FinalHTMLCode(); //* Block prohibited characters from all text fields ?>

请注意,代码还包含页面的例外情况,我知道可能有合法用户输入的特殊字符,但SQL注入攻击不可能成功。

我在此过程中所做的其他改进包括创建一个没有管理员权限的SQL Web用户帐户,但只包含数据库的SELECT,INSERT和UPDATE权限。这可以使恶意攻击者远离DROPing表或DELETEing行或其他潜在的恶意活动。

相关问题