简体   繁体   中英

\r\n \" printing out

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('/(&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);
    }
  }
}

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

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM