PHP输入GET vars sanitizing

Posted

技术标签:

【中文标题】PHP输入GET vars sanitizing【英文标题】:PHP input GET vars sanitizing 【发布时间】:2017-09-09 22:10:49 【问题描述】:

对于我用 php 5+ 编写的应用程序,我有一个 common.php,它包含在所有其他页面中。其中我有一个include sanitize.php,它旨在清理 URL 中使用的任何输入变量。所以,定位$_GET[] 值。

这只是为了有一个地方我可以整理任何变量(如果使用),然后在代码中使用它们。

据我所知,似乎没有整洁的方法可以根据预期/期望的输入进行清理。我最初查看的方法是 sanitize.php 有一个 foreach 循环遍历任何变量,查找所需的清理类型,然后将清理后的变量添加到单独的数组中以在我的代码中使用。

为了保持标准,我想我会使用正则表达式,而不是使用 PHP 清理过滤器。我想要的类型是 alphaonlyalphanumericemailpassword。尽管“密码”允许使用一些特殊字符,但我想删除甚至逃避潜在的“危险”字符,例如 ' ",然后将其包含到 mysql 数据库中。我们有一个欧洲用户群,因此可以使用不同的语言环境,但我希望这不会成为太大的问题。

这是一个“好的”解决方案,还是我想重新发明***?

随机页面

/mypage.php?c=userid&p=lkasjdlakjsdlakj&z=....
(use SANITIZED_SAFE_INPUT_VARS variable only)

sanitize.php

var aryAllowedGetParamNames = array(
    "c" => "alphaonly",         //login
    "p" => "alphaemail",        //password
    "e" => "email"              //email
    //...
);

var sanitizeTypes = array (
    "alphaonly" => "[a-zA-Z]",
    "alphanumeric" => "[a-zA-Z0-9]",
    "email" => "[a-zA-Z0-9]...etc"
);

var SANITIZED_SAFE_INPUT_VARS = array();

foreach ($_GET as $key => $value)  
    //apply regex and add value to SANITIZED_SAFE_INPUT_VARS 

编辑

似乎有一些关于在 URL 中使用密码的意见。我会更详细地解释一下。我没有使用带有用户名和密码的 POST 登录提示,而是使用带有用户 ID 和密码参数的 _db_tryLogin.php 的 ajax 异步调用。用户名始终是一个 6-ALPHA-only 文本字符串,密码是输入内容的 md5。我知道关于 MD5 不够“安全”的观点。

JS 当前 MD5s 密码并将其发送到_db_tryLogin.php

-> async : _db_login.php?c=ABCDEF&p=SLKDauwfLKASFUWPOjkjafkKoAWOIFHF2733287

这将返回“1”或“0”的异步响应。两者都会导致页面刷新,但如果_db_tryLogin.php 页面检测到密码并且用户ID 与一条数据库记录匹配,则设置会话变量并且站点知道用户已登录。

我将 MD5 用于异步请求,只是为了快速散列密码,使其不会以明文形式传输。

_db_tryLogin.php 获取密码,即md5(plainpass) 再次添加 SALT 和 MD5s,然后与 DB 中的用户表进行比较。

存储的数据库密码 = md5(SALT.md5(plainpass))

【问题讨论】:

而不是经历允许某些字符的冗长乏味的过程,只需禁止(即删除)您不想接受的字符,例如非字母数字或反引号字符等。使用PHPstrip_tags()函数也可以为您节省很多精力。 您在这方面花了一些心思。但它通常被认为是错误的方法。不要将输入视为“危险”,而是查看您的数据库 API 使用情况。转义和清理始终是特定于上下文的;不是一个全面的安全小发明。 您要针对什么进行消毒?如果您 [仅] 试图保护您的 SQL 数据库您做错了,应该查看Prepared Statements @Martin 我的主要议程是防止注入,并且页面使用它知道受信任的变量 @Jammo 他们的观点是这还不够,如果你希望找到一份工作,那么它不会被接受为一种在安全环境中编程的方法 【参考方案1】:

我会开始正则表达式每个变量,如果它不符合要求,则应用 null。要么测试它应该只有什么,或者它不应该有什么,以较小者为准:

$safeValue = (preg_match('/^[a-zA-Z0-9]0,5$/',$value) ? $value : "");

与带有参数输入的准备好的语句一起

$query = "SELECT x FROM table WHERE id=?";
bind_param("si",$var,$var)

PHP 还带有内置过滤器,例如电子邮件和其他)。示例:filter_var($data, FILTER_SANITIZE_EMAIL)

http://php.net/manual/en/filter.filters.sanitize.php

【讨论】:

应用 false 而不是 null 似乎更合乎逻辑,因为 if 语句 (===) 可以定义它无法完整地传递正则表达式。但这种细节取决于我猜的 OP.... @Martin 通常稍后我会使用 if($var != "") ,这就是为什么。我完全清空它。【参考方案2】:

您要针对什么进行消毒?如果您 [仅] 试图保护您的 SQL 数据库您做错了,应该查看Prepared Statements

用户提交的数据绝不应该受到信任。接受,是的,受信任 - 不。

与其经历允许某些字符的冗长繁琐过程,不如简单地禁止(即删除)您不想接受的字符,例如非字母数字或反引号字符等。它还可以为您节省很多精力使用 PHP strip_tags() 函数。

1) 在包含文件中创建函数。我建议在abstract Static Class 中创建它,但这有点超出了这个答案的范围。

2) 在此函数/类方法中,添加您要查找的坏字符的定义,以及这些检查将应用于的数据。您似乎对自己的逻辑过程有一个很好的了解,但请注意,没有明确的正确代码答案,因为每个程序员对字符串的需求都不同。

3) 使用 (2) 中定义的标准,您可以使用 Regex 删除无效字符以返回“安全”变量集。

示例:

   // Remove backtick, single and double quotes from a variable.  
   // using PCRE Regex.
   $data = preg_relace("/[`"']/","",$data);

4) 使用 PHP 函数 strip_tags() 来执行此操作并从字符串中删除 html 和 PHP 代码。

5) 对于电子邮件验证,请使用 PHP $email = filter_var($data, FILTER_SANITIZE_EMAIL); 函数,它会比您自己的简单正则表达式好得多。 使用PHP Filter Validations,它们完全适合你的情况。

6) 从不相信输出数据,即使它通过了你可以给它的所有检查和正则表达式,某些东西仍然可以通过。总是非常警惕用户提交的数据。 永远不要相信它。

7) 使用准备好的语句进行 SQL 交互。

8) 作为数字类型(int / float)的快捷方式,您可以使用 PHP 类型转换来强制给定变量成为某种类型并破坏它成为其他任何东西的任何机会:

$number = $_GET['number']; //can be anything.
$number = (int)$_GET['number']; //must be an integer or zero.

注意事项:

密码不应仅为a-z,但应尽可能多地使用字符,越多越好。

如果您在此处所做的工作是为了保护数据库的安全性和完整性,那么您做错了,应该使用 Prepared Statements 进行 MySQL 交互。

停止使用var来声明变量,因为这是来自PHP4的and is VERY old,最好使用变量前置条件$(例如$variable = true;)。

你说:

我们拥有欧洲用户群,因此可以使用不同的语言环境

我强烈建议您探索PHP mb_string functions,因为 PHP 本身并不是多字节安全的。

【讨论】:

以上是关于PHP输入GET vars sanitizing的主要内容,如果未能解决你的问题,请参考以下文章

清理用户输入PHP

PHP filter_var() 函数

清理数据库的POST/Get

php实现验证邮箱格式的代码实例

php优秀框架codeigniter学习系列——CI_Input类学习

FILTER_SANITIZE_STRING 是不是足以避免 SQL 注入和 XSS 攻击?