简体   繁体   English

PHP / MYSQL:消除用户输入 - 这是一个坏主意吗?

[英]PHP / MYSQL: Sanitizing user input - is this a bad idea?

I have one "go" script that fetches any other script requested and this is what I wrote to sanitize user input: 我有一个“go”脚本来获取所请求的任何其他脚本,这是我写的用于清理用户输入的内容:

foreach ($_REQUEST as $key => $value){
    if (get_magic_quotes_gpc()) 
    $_REQUEST[$key] = mysql_real_escape_string(stripslashes($value));  
    else
    $_REQUEST[$key] = mysql_real_escape_string($value); 
}

I haven't seen anyone else use this approach. 我还没有看到其他人使用这种方法。 Is there any reason not to? 有什么理由不去吗?

EDIT - amended for to work for arrays: 编辑 - 修改为适用于数组:

function mysql_escape($thing) {
  if (is_array($thing)) {
    $escaped = array();
    foreach ($thing as $key => $value) {
      $escaped[$key] = mysql_escape($value);
    }          
    return $escaped;
  }
  // else
  if (get_magic_quotes_gpc()) $thing = stripslashes($thing);
  return mysql_real_escape_string($thing);
}

foreach ($_REQUEST as $key => $value){
    $_REQUEST[$key] = mysql_escape($value); 
}

I find it much better to escape the data at the time it is used, not on the way in. You might want to use that data in JSON, XML, Shell, MySQL, Curl, or HTML and each will have it's own way of escaping the data. 我发现在使用数据时逃避数据要好得多,而不是在进行中。您可能希望在JSON,XML,Shell,MySQL,Curl或HTML中使用这些数据,并且每个数据都有自己的方式。逃避数据。


Lets have a quick review of WHY escaping is needed in different contexts: 让我们快速回顾一下为什么在不同的环境中需要逃避:

If you are in a quote delimited string, you need to be able to escape the quotes. 如果您使用引号分隔的字符串,则需要能够转义引号。 If you are in xml, then you need to separate "content" from "markup" If you are in SQL, you need to separate "commands" from "data" If you are on the command line, you need to separate "commands" from "data" 如果您使用的是xml,则需要将“内容”与“标记”分开如果您使用的是SQL,则需要将“命令”与“数据”分开如果您在命令行中,则需要分离“命令”来自“数据”

This is a really basic aspect of computing in general. 这一般是计算的一个基本方面。 Because the syntax that delimits data can occur IN THE DATA, there needs to be a way to differentiate the DATA from the SYNTAX, hence, escaping. 因为分隔数据的语法可以在数据中出现,所以需要有一种方法来区分DATA和SYNTAX,从而逃避。

In web programming, the common escaping cases are: 1. Outputting text into HTML 2. Outputting data into HTML attributes 3. Outputting HTML into HTML 4. Inserting data into Javascript 5. Inserting data into SQL 6. Inserting data into a shell command 在Web编程中,常见的转义案例是:1。将文本输出到HTML 2.将数据输出到HTML属性3.将HTML输出到HTML 4.将数据插入到Javascript中5.将数据插入到SQL中6.将数据插入到shell命令中

Each one has a different security implications if handled incorrectly. 如果处理不当,每个都有不同的安全隐患。 THIS IS REALLY IMPORTANT! 这真的很重要! Let's review this in the context of PHP: 让我们在PHP的上下文中回顾一下:

  1. Text into HTML: htmlspecialchars(...) 文本转换为HTML:htmlspecialchars(...)

  2. Data into HTML attributes htmlspecialchars(..., ENT_QUOTES) 数据转换为HTML属性htmlspecialchars(...,ENT_QUOTES)

  3. HTML into HTML Use a library such as HTMLPurifier to ENSURE that only valid tags are present. HTML转换为HTML使用HTMLPurifier等库来确保只存在有效标记。

  4. Data into Javascript I prefer json_encode . 数据到Javascript我更喜欢json_encode If you are placing it in an attribute, you still need to use #2, such as 如果要将其放在属性中,则仍需要使用#2,例如

  5. Inserting data into SQL Each driver has an escape() function of some sort. 将数据插入SQL每个驱动程序都有某种类型的escape()函数。 It is best. 这是最好的。 If you are running in a normal latin1 character set, addslashes(...) is suitable. 如果您使用普通的latin1字符集运行,则addslashes(...)是合适的。 Don't forget the quotes AROUND the addslashes() call: 不要忘记引号AROUND addslashes()调用:

    "INSERT INTO table1 SET field1 = '" . “INSERT INTO table1 SET field1 ='”。 addslashes($data) . addslashes($ data)。 "'" “'”

  6. Data on the command line escapeshellarg() and escapeshellcmd() -- read the manual 命令行中的数据escapeshellarg()和escapeshellcmd() - 阅读手册

-- Take these to heart, and you will eliminate 95%* of common web security risks! - 牢记这些,您将消除95%*的常见网络安全风险! (* a guess) (* 一个推测)

如果$_REQUEST有数组,则它们的值将不会被清理。

I've made and use this one: 我已经制作并使用了这个:

<?php
function _clean($var){
    $pattern = array("/0x27/","/%0a/","/%0A/","/%0d/","/%0D/","/0x3a/",
                     "/union/i","/concat/i","/delete/i","/truncate/i","/alter/i","/information_schema/i",
                     "/unhex/i","/load_file/i","/outfile/i","/0xbf27/");
    $value = addslashes(preg_replace($pattern, "", $var));
    return $value;
}

if(isset($_GET)){
    foreach($_GET as $k => $v){
        $_GET[$k] = _clean($v);
    }
}

if(isset($_POST)){
    foreach($_POST as $k => $v){
        $_POST[$k] = _clean($v);
    }
}
?>

Your approach tries to sanitize all the request data for insertion into the database, but what if you just wanted to output it? 您的方法会尝试清理所有请求数据以插入数据库,但是如果您只想输出它呢? You will have unnecessary backslashes in your output. 输出中会有不必要的反斜杠。 Also, escaping is not a good strategy to protect from SQL exceptions anyway. 此外,无论如何,转义不是防止SQL异常的好策略。 By using parametrized queries (eg in PDO or in MySQLi) you "pass" the problem of escaping to the abstraction layer. 通过使用参数化查询(例如在PDO或MySQLi中),您将“转义”问题“传递”到抽象层。

Apart from the lack of recursion into arrays and the unnecessary escaping of, say, integers, this approach encodes data for use in an SQL statement before sanitization. 除了没有递归到数组和不必要的转换,例如整数之外,这种方法在清理之前编码用于SQL语句的数据。 mysql_real_escape_string() escapes data, it doesn't sanitize it -- escaping and sanitizing aren't the same thing. mysql_real_escape_string()转义数据,它不会消毒它 - 转义和消毒不是一回事。

Sanitization is the task many PHP scripts have of scrutinizing input data for acceptability before using it. 清理是许多PHP脚本在使用之前仔细检查输入数据的可接受性的任务。 I think this is better done on data that hasn't been escaped. 我认为对未转义的数据做得更好。 I generally don't escape data until it goes into the SQL. 在进入SQL之前,我通常不会转义数据。 Those who prefer to use Prepared Statements achieve the same that way. 那些喜欢使用预备语句的人就是这样做的。

One more thing: If input data can include utf8 strings, it seems these ought to be validated before escaping. 还有一件事:如果输入数据可以包含utf8字符串,那么它们似乎应该在转义之前进行验证。 I often use a recursive utf8 cleaner on $_POST before sanitization. 我经常在清理之前在$ _POST上使用递归的utf8清理器。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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