\r\n \"打印输出

发布于 2024-11-29 13:13:36 字数 5315 浏览 0 评论 0 原文

我已经开始使用 ADOdb 和参数化查询(例如 $db->Execute("SELECT FROM users WHERE user_name=?;",array($get->id);) 来防止 SQL 注入。我读过这是应该在 MySQL 注入方面保护您,但显然不是 XSS 虽然情况可能如此,但我仍然对此持怀疑态度,

但我总是在一开始就使用霰弹枪方法来过滤我的环境变量 。的我的包装器代码(kernel.php)。我注意到使用 ADOdb 和以下函数的组合会产生浏览器可见的回车符(\r\n \" \'),这是我不想要的(尽管我确实想要)存储该信息!)。我也不想在显示之前过滤我的输出,因为我已经正确过滤了我的输入(除了 BBcode 之类的东西)。 。

虽然一般来说我已经隔离了这一点 sanitize 函数的 mysql_real_escape_string 部分出现问题,请注意我的服务器运行的是 PHP 5.2+,当我使用我自己的简化数据库抽象类时,这个问题不存在。此外,该网站主要是在我自己的代码上运行的,而不是在某些现有 CMS 的支架上构建的。因此,考虑到这些因素,我唯一的猜测是存在一些双重转义。但是,当我查看 adodb.inc.php 文件时,我注意到 $rs->FetchNextObj() 不使用 mysql_real_escape_string。看来唯一执行此操作的函数是 qstr,它封装了整个字符串。这让我担心依赖参数化查询可能还不够,但我不知道!

// Sanitize all possible user inputs

if(keyring_access("am")) // XSS and HTML stripping exemption for administrators editing HTML content
{
$_POST =    sanitize($_POST,false,false);
$_GET =     sanitize($_GET,false,false);
$_COOKIE =  sanitize($_COOKIE,false,false);
$_SESSION = sanitize($_SESSION,false,false);    
}
else
{   
$_POST =    sanitize($_POST);
$_GET =     sanitize($_GET);
$_COOKIE =  sanitize($_COOKIE);
$_SESSION = sanitize($_SESSION);
}

// Setup $form object shortcuts (merely convenience)

if($_POST)
{
foreach($_POST as $key => $value)
{
        $form->$key = $value;
}
}

if($_GET)
{
foreach($_GET as $key => $value)
{
    $get->$key = $value;
}
}


function sanitize($val, $strip = true, $xss = true, $charset = 'UTF-8')
{
  if (is_array($val))
  {
    $output = array();
    foreach ($val as $key => $data)
    {
      $output[$key] = sanitize($data, $strip, $xss, $charset);
    }
    return $output;
  }
  else
  {
    if ($xss)
    {
      // code by nicolaspar
      $val = preg_replace('/([\x00-\x08][\x0b-\x0c][\x0e-\x20])/', '', $val);
      $search = 'abcdefghijklmnopqrstuvwxyz';
      $search .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
      $search .= '1234567890!@#$%^&*()';
      $search .= '~`";:?+/={}[]-_|\'\\';

      for ($i = 0; $i < strlen($search); $i++)
      {
        $val = preg_replace('/(&amp;#[x|X]0{0,8}'.dechex(ord($search[$i])).';?)/i', $search[$i], $val); // with a ;
        $val = preg_replace('/(&amp;#0{0,8}'.ord($search[$i]).';?)/', $search[$i], $val); // with a ;
      }

      $ra1 = Array('javascript', 'vbscript', 'expression', 'applet', 'meta', 'xml', 'blink', 'link', 'style', 'script', 'embed', 'object', 'iframe', 'frame', 'frameset', 'ilayer', 'layer', 'bgsound', 'title', 'base');
      $ra2 = Array('onabort', 'onactivate', 'onafterprint', 'onafterupdate', 'onbeforeactivate', 'onbeforecopy', 'onbeforecut', 'onbeforedeactivate', 'onbeforeeditfocus', 'onbeforepaste', 'onbeforeprint', 'onbeforeunload', 'onbeforeupdate', 'onblur', 'onbounce', 'oncellchange', 'onchange', 'onclick', 'oncontextmenu', 'oncontrolselect', 'oncopy', 'oncut', 'ondataavailable', 'ondatasetchanged', 'ondatasetcomplete', 'ondblclick', 'ondeactivate', 'ondrag', 'ondragend', 'ondragenter', 'ondragleave', 'ondragover', 'ondragstart', 'ondrop', 'onerror', 'onerrorupdate', 'onfilterchange', 'onfinish', 'onfocus', 'onfocusin', 'onfocusout', 'onhelp', 'onkeydown', 'onkeypress', 'onkeyup', 'onlayoutcomplete', 'onload', 'onlosecapture', 'onmousedown', 'onmouseenter', 'onmouseleave', 'onmousemove', 'onmouseout', 'onmouseover', 'onmouseup', 'onmousewheel', 'onmove', 'onmoveend', 'onmovestart', 'onpaste', 'onpropertychange', 'onreadystatechange', 'onreset', 'onresize', 'onresizeend', 'onresizestart', 'onrowenter', 'onrowexit', 'onrowsdelete', 'onrowsinserted', 'onscroll', 'onselect', 'onselectionchange', 'onselectstart', 'onstart', 'onstop', 'onsubmit', 'onunload');

      $ra = array_merge($ra1, $ra2);
      $found = true;

      while ($found == true)
      {
        $val_before = $val;
        for ($i = 0; $i < sizeof($ra); $i++)
        {
          $pattern = '/';
          for ($j = 0; $j < strlen($ra[$i]); $j++)
          {
            if ($j > 0)
            {
              $pattern .= '(';
              $pattern .= '(&amp;#[x|X]0{0,8}([9][a][b]);?)?';
              $pattern .= '|(&amp;#0{0,8}([9][10][13]);?)?';
              $pattern .= ')?';
            }
            $pattern .= $ra[$i][$j];
          }
          $pattern .= '/i';
          $replacement = substr($ra[$i], 0, 2).'<x>'.substr($ra[$i], 2);
          $val = preg_replace($pattern, $replacement, $val);
          if ($val_before == $val)
          {
            $found = false;
          }
        }
      }
    }

    // Strip HTML tags
    if ($strip)
    {
      $val = strip_tags($val);
      // Encode special chars
      $val = htmlentities($val, ENT_QUOTES, $charset);
    }

    // Cross your fingers that we don't get a MySQL injection with relying on ADOdb prepared statements alone… ? It works great otherwise by just returning $val... so it appears the code below is the culprit of the \r\n \" etc. escaping
    //return $val;

    if(function_exists('get_magic_quotes_gpc') or get_magic_quotes_gpc())
    {
        return mysql_real_escape_string(stripslashes($val));
    }
    else
    {
        return mysql_real_escape_string($val);
    }
  }
}

预先非常感谢您的帮助!如果您需要任何进一步的说明,请告诉我。

更新反斜杠仍然出现在“和'前面,是的,我删除了额外的mysql_real_escape_string...现在我只能认为这可能是get_quotes_gpc,或者ADOdb添加它们...

〜elix

I have begun using ADOdb and parameterized queries (ex. $db->Execute("SELECT FROM users WHERE user_name=?;",array($get->id);)to prevent SQL injections. I have read this is suppose to protect you on the MySQL injection side of things, but obviously not XSS. While this may be the case, I'm still a bit skeptical about it.

Nevertheless, I always filter my environmental variables using shotgun approach towards safety at the beginning of my wrapper code (kernel.php). I notice the combination of using ADOdb and the following functions produces browser-visible carriage returns (\r\n \" \'), which is something I don't want (although I do want to store that information!). I also don't want to have to filter my output before display, since I already properly filter my input (aside from BBcode and that sort of thing). Below you will find the functions I'm referring to.

While in general I have isolated this problem to the mysql_real_escape_string portion of the sanitize function, do note that my server is running PHP 5.2+, and this issue does not exist when I use my own simplified db abstraction class. Also, the site is ran on mostly my own code and not built on the scaffold of some preexisting CMS). Thus, considering these factors, my only guess is there is some double-escaping going on. However, when I looked at adodb.inc.php file, I noticed $rs->FetchNextObj() doesn't utilize mysql_real_escape_string. It appears the only function that does this is qstr, which encapsulates the entire string. This leads me to worry that relying on parameterized queries may not be enough, but I don't know!

// Sanitize all possible user inputs

if(keyring_access("am")) // XSS and HTML stripping exemption for administrators editing HTML content
{
$_POST =    sanitize($_POST,false,false);
$_GET =     sanitize($_GET,false,false);
$_COOKIE =  sanitize($_COOKIE,false,false);
$_SESSION = sanitize($_SESSION,false,false);    
}
else
{   
$_POST =    sanitize($_POST);
$_GET =     sanitize($_GET);
$_COOKIE =  sanitize($_COOKIE);
$_SESSION = sanitize($_SESSION);
}

// Setup $form object shortcuts (merely convenience)

if($_POST)
{
foreach($_POST as $key => $value)
{
        $form->$key = $value;
}
}

if($_GET)
{
foreach($_GET as $key => $value)
{
    $get->$key = $value;
}
}


function sanitize($val, $strip = true, $xss = true, $charset = 'UTF-8')
{
  if (is_array($val))
  {
    $output = array();
    foreach ($val as $key => $data)
    {
      $output[$key] = sanitize($data, $strip, $xss, $charset);
    }
    return $output;
  }
  else
  {
    if ($xss)
    {
      // code by nicolaspar
      $val = preg_replace('/([\x00-\x08][\x0b-\x0c][\x0e-\x20])/', '', $val);
      $search = 'abcdefghijklmnopqrstuvwxyz';
      $search .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
      $search .= '1234567890!@#$%^&*()';
      $search .= '~`";:?+/={}[]-_|\'\\';

      for ($i = 0; $i < strlen($search); $i++)
      {
        $val = preg_replace('/(&#[x|X]0{0,8}'.dechex(ord($search[$i])).';?)/i', $search[$i], $val); // with a ;
        $val = preg_replace('/(&#0{0,8}'.ord($search[$i]).';?)/', $search[$i], $val); // with a ;
      }

      $ra1 = Array('javascript', 'vbscript', 'expression', 'applet', 'meta', 'xml', 'blink', 'link', 'style', 'script', 'embed', 'object', 'iframe', 'frame', 'frameset', 'ilayer', 'layer', 'bgsound', 'title', 'base');
      $ra2 = Array('onabort', 'onactivate', 'onafterprint', 'onafterupdate', 'onbeforeactivate', 'onbeforecopy', 'onbeforecut', 'onbeforedeactivate', 'onbeforeeditfocus', 'onbeforepaste', 'onbeforeprint', 'onbeforeunload', 'onbeforeupdate', 'onblur', 'onbounce', 'oncellchange', 'onchange', 'onclick', 'oncontextmenu', 'oncontrolselect', 'oncopy', 'oncut', 'ondataavailable', 'ondatasetchanged', 'ondatasetcomplete', 'ondblclick', 'ondeactivate', 'ondrag', 'ondragend', 'ondragenter', 'ondragleave', 'ondragover', 'ondragstart', 'ondrop', 'onerror', 'onerrorupdate', 'onfilterchange', 'onfinish', 'onfocus', 'onfocusin', 'onfocusout', 'onhelp', 'onkeydown', 'onkeypress', 'onkeyup', 'onlayoutcomplete', 'onload', 'onlosecapture', 'onmousedown', 'onmouseenter', 'onmouseleave', 'onmousemove', 'onmouseout', 'onmouseover', 'onmouseup', 'onmousewheel', 'onmove', 'onmoveend', 'onmovestart', 'onpaste', 'onpropertychange', 'onreadystatechange', 'onreset', 'onresize', 'onresizeend', 'onresizestart', 'onrowenter', 'onrowexit', 'onrowsdelete', 'onrowsinserted', 'onscroll', 'onselect', 'onselectionchange', 'onselectstart', 'onstart', 'onstop', 'onsubmit', 'onunload');

      $ra = array_merge($ra1, $ra2);
      $found = true;

      while ($found == true)
      {
        $val_before = $val;
        for ($i = 0; $i < sizeof($ra); $i++)
        {
          $pattern = '/';
          for ($j = 0; $j < strlen($ra[$i]); $j++)
          {
            if ($j > 0)
            {
              $pattern .= '(';
              $pattern .= '(&#[x|X]0{0,8}([9][a][b]);?)?';
              $pattern .= '|(&#0{0,8}([9][10][13]);?)?';
              $pattern .= ')?';
            }
            $pattern .= $ra[$i][$j];
          }
          $pattern .= '/i';
          $replacement = substr($ra[$i], 0, 2).'<x>'.substr($ra[$i], 2);
          $val = preg_replace($pattern, $replacement, $val);
          if ($val_before == $val)
          {
            $found = false;
          }
        }
      }
    }

    // Strip HTML tags
    if ($strip)
    {
      $val = strip_tags($val);
      // Encode special chars
      $val = htmlentities($val, ENT_QUOTES, $charset);
    }

    // Cross your fingers that we don't get a MySQL injection with relying on ADOdb prepared statements alone… ? It works great otherwise by just returning $val... so it appears the code below is the culprit of the \r\n \" etc. escaping
    //return $val;

    if(function_exists('get_magic_quotes_gpc') or get_magic_quotes_gpc())
    {
        return mysql_real_escape_string(stripslashes($val));
    }
    else
    {
        return mysql_real_escape_string($val);
    }
  }
}

Thank you very much in advance for your help! If you need any further clarifications, please let me know.

Update the backslash is still showing up in front of " and ', and yes I removed the extra mysql_real_escape_string... now I can only think this might be get_quotes_gpc, or ADOdb adding them...

~elix

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

绝情姑娘 2024-12-06 13:13:36

事实证明这是 ADOdb 中 qstr 的副作用,尽管我没有引用该类的特定函数,但必须在其他地方调用。我的特定情况下的问题是启用了魔术引号,因此我将函数的默认参数设置为 $magic_quotes=disabled。至于不需要任何转义,我发现 ADOdb 本身不通过基本的 Execute() 单独绑定来利用 mysql_real_escape_string!我如何认识到这一点是因为字符“ ”引发了错误(因此没有在禁用 error_reporting 的服务器上呈现)。看起来这些功能的组合与修复 ADOdb 的小问题使我得到了很好的保护,并按照我想要的方式接受大多数/所有输入:在双引号的情况下,会阻止任何引号作为内容输入到数据库中,这意味着至少没有 HTML

尽管如此,我很欣赏你的建议,但是还觉得我的后续可能有帮助 其他的。

It turned out to be a side effect of qstr in ADOdb, even though I didn't reference that particular function of the class, but must be called elsewhere. The problem in my particular case was that magic quotes is enabled, so I set the default argument for the function to $magic_quotes=disabled. As for not needing any escaping with this, I found that ADOdb by itself DOES NOT utilize mysql_real_escape_string through the basic Execute() with binding alone! How I recognized this was due to the fact that the characters " ' threw errors (hence didn't render on my server where error_reporting is disabled). It appears the combination of the functions with fixing that small issue with ADOdb has me both well protected, and accepts most/all input the way I want it to: which in the case of the double quote prevented any quotes from being entered as content into the database, which meant at the very least no HTML

Nevertheless, I appreciate your suggestions, but also felt that my follow-up might help others.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文