是否存在一种万能函数,可以很好地为SQL注入和XSS攻击清除用户输入,同时仍然允许某些类型的HTML标记?
当前回答
你从不清理输入。
你总是要清理输出。
你应用到数据的转换,使其能够安全地包含在SQL语句中,完全不同于你在HTML中应用的转换,完全不同于你在Javascript中应用的转换,完全不同于你在LDIF中应用的转换,完全不同于你应用到CSS中的转换,完全不同于你应用到Email....中的转换
务必验证输入——决定您是否应该接受它进行进一步处理,还是告诉用户它是不可接受的。但是不要对数据的表示进行任何更改,直到它离开PHP为止。
很久以前,有人试图发明一种适合所有人的机制来转义数据,我们最终使用了“magic_quotes”,它不能正确地转义所有输出目标的数据,导致不同的安装需要不同的代码才能工作。
其他回答
用PHP清除用户输入的方法:
Use Modern Versions of MySQL and PHP. Set charset explicitly: $mysqli->set_charset("utf8");manual $pdo = new PDO('mysql:host=localhost;dbname=testdb;charset=UTF8', $user, $password);manual $pdo->exec("set names utf8");manual $pdo = new PDO( "mysql:host=$host;dbname=$db", $user, $pass, array( PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8" ) );manual mysql_set_charset('utf8') [deprecated in PHP 5.5.0, removed in PHP 7.0.0]. Use secure charsets: Select utf8, latin1, ascii.., dont use vulnerable charsets big5, cp932, gb2312, gbk, sjis. Use spatialized function: MySQLi prepared statements: $stmt = $mysqli->prepare('SELECT * FROM test WHERE name = ? LIMIT 1'); $param = "' OR 1=1 /*";$stmt->bind_param('s', $param);$stmt->execute(); PDO::quote() - places quotes around the input string (if required) and escapes special characters within the input string, using a quoting style appropriate to the underlying driver:$pdo = new PDO('mysql:host=localhost;dbname=testdb;charset=UTF8', $user, $password);explicit set the character set$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);disable emulating prepared statements to prevent fallback to emulating statements that MySQL can't prepare natively (to prevent injection)$var = $pdo->quote("' OR 1=1 /*");not only escapes the literal, but also quotes it (in single-quote ' characters) $stmt = $pdo->query("SELECT * FROM test WHERE name = $var LIMIT 1"); PDO Prepared Statements: vs MySQLi prepared statements supports more database drivers and named parameters: $pdo = new PDO('mysql:host=localhost;dbname=testdb;charset=UTF8', $user, $password);explicit set the character set$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);disable emulating prepared statements to prevent fallback to emulating statements that MySQL can't prepare natively (to prevent injection) $stmt = $pdo->prepare('SELECT * FROM test WHERE name = ? LIMIT 1'); $stmt->execute(["' OR 1=1 /*"]); mysql_real_escape_string [deprecated in PHP 5.5.0, removed in PHP 7.0.0]. mysqli_real_escape_string Escapes special characters in a string for use in an SQL statement, taking into account the current charset of the connection. But recommended to use Prepared Statements because they are not simply escaped strings, a statement comes up with a complete query execution plan, including which tables and indexes it would use, it is a optimized way. Use single quotes (' ') around your variables inside your query. Check the variable contains what you are expecting for: If you are expecting an integer, use: ctype_digit — Check for numeric character(s);$value = (int) $value;$value = intval($value);$var = filter_var('0755', FILTER_VALIDATE_INT, $options); For Strings use: is_string() — Find whether the type of a variable is stringUse Filter Function filter_var() — filters a variable with a specified filter:$email = filter_var($email, FILTER_SANITIZE_EMAIL);$newstr = filter_var($str, FILTER_SANITIZE_STRING);more predefined filters filter_input() — Gets a specific external variable by name and optionally filters it:$search_html = filter_input(INPUT_GET, 'search', FILTER_SANITIZE_SPECIAL_CHARS); preg_match() — Perform a regular expression match; Write Your own validation function.
不,没有。
首先,SQL注入是一个输入过滤问题,而XSS是一个输出转义问题——因此您甚至不会在代码生命周期中同时执行这两个操作。
基本经验法则
对于SQL查询,绑定参数 使用strip_tags()过滤掉不需要的HTML 使用htmlspecialchars()转义所有其他输出,并注意这里的第2和第3个参数。
不要试图通过清除输入数据来防止SQL注入。
相反,不允许在创建SQL代码时使用数据。使用使用绑定变量的预制语句(即在模板查询中使用参数)。这是防止SQL注入的唯一方法。
有关防止SQL注入的更多信息,请访问我的网站http://bobby-tables.com/。
有一个技巧可以帮助您在特定情况下使用/mypage?id=53,在WHERE子句中使用id是为了确保id确实是一个整数,如下所示:
if (isset($_GET['id'])) {
$id = $_GET['id'];
settype($id, 'integer');
$result = mysql_query("SELECT * FROM mytable WHERE id = '$id'");
# now use the result
}
但当然,这只排除了一个特定的攻击,所以阅读所有其他的答案。(是的,我知道上面的代码不是很好,但它显示了具体的防御。)
避免在清理输入和转义数据时出错的最简单方法是使用Symfony、Nette等PHP框架或该框架的一部分(模板引擎、数据库层、ORM)。
像Twig或Latte这样的模板引擎默认有输出转义-如果你根据上下文(HTML或Javascript部分的网页)正确地转义了你的输出,你不必手动解决。
框架会自动清理输入,你不应该直接使用$_POST, $_GET或$_SESSION变量,而是通过路由,会话处理等机制。
对于数据库(模型)层,有像Doctrine这样的ORM框架或围绕PDO的包装器,如Nette database。
你可以在这里阅读更多关于它的内容-什么是软件框架?
推荐文章
- 致命错误:未找到类“SoapClient”
- 我目前使用的是哪个版本的CodeIgniter ?
- 合并两个PHP对象的最佳方法是什么?
- 如何使HTTP请求在PHP和不等待响应
- 发送附件与PHP邮件()?
- 如何获得当前的路线在Symfony 2?
- 用PHP删除字符串的前4个字符
- mysql_connect():[2002]没有这样的文件或目录(试图通过unix:///tmp/mysql.sock连接)在
- 一个函数的多个返回值
- 在PHP中使用foreach循环时查找数组的最后一个元素
- 检查数组是否为空
- PHP DOMDocument loadHTML没有正确编码UTF-8
- PHP在个位数数前加上前导零
- PHPMailer字符编码问题
- 删除多个空白空间