关于验证:PHP输入GET vars清理

PHP input GET vars sanitizing

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

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

我已经看到,基于预期/期望的投入,似乎没有整洁的方式来消毒。我最初看到的方法是这个sanitize.php有一个foreach循环遍历任何vars,查找所需的清理类型,然后将清理过的vars添加到一个单独的数组中以便在我的代码中使用。

我没有使用PHP清理过滤器来保持标准,我以为我会使用正则表达式。我想要的类型是alphaonly,字母数字,电子邮件,密码。虽然"密码"允许一些特殊的字符,但我想删除甚至逃避可能"危险"的字符,如' ",然后将其包含在mysql DB中。我们有一个欧洲用户群,因此可能有不同的语言环境,但我希望这不会是一个太大的问题。

这是一个"好"的解决方案,或者我试图重新发明轮子?

随机页面

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

sanitize.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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的文本字符串,密码是输入内容的md5。我知道关于MD5的意见不够"安全"。

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

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

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

我使用MD5作为异步请求只是为了快速散列密码,所以它不是以明文形式传输的。

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

存储的DB密码= md5(SALT.md5(plainpass))


What are you sanitising against? If you're [only] trying to protect your SQL database you're doing it wrong, and should be looking into Prepared Statements.

用户提交的数据不应受到信任。接受,是的,可信任的 - 没有。

不要经历允许某些字符的冗长乏味的过程,只是禁止(即删除)您不想接受的字符,例如非字母数字或反引号字符等。它也可以为您节省大量的工作量。 PHP strip_tags()函数。

1)在包含文件中创建您的功能。我建议在抽象的静态类中创建它,但这有点超出了这个答案的范围。

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

3)使用(2)中定义的标准,然后您可以使用正则表达式删除无效字符以返回"安全"变量集。

例:

1
2
3
   // 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过滤器验证它们完全适用于您的情况。

6)永远不要信任输出数据,即使它通过了你可以提供的所有检查和正则数据,仍然可以通过。总是非常警惕用户提交的数据。永远不要相信它。

7)使用Prepared Statements进行SQL交互。

8)作为数字类型(int / float)的快捷方式,你可以使用PHP类型转换来强制给定的varibles成为某种类型,并且破坏它的任何其他可能性:

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

笔记:

  • 密码不应仅为a-z,但应该是您可以选择的字符数,越多越好。

  • 如果您在此处采取的措施是针对保护数据库安全性和完整性的情况,那么您做错了,应该使用Prepared Statements进行MySQL交互。

  • 停止使用var来声明变量,因为它来自PHP4并且非常陈旧,使用变量前置$(例如$variable = true;)要好得多。

  • 你说:

    We have a european userbase so different locales are possible

    我强烈建议您去探索PHP mb_string函数,因为PHP本身并不是安全的。


我想开始只是regex每个变量,如果它不符合要求,则应用null。要么测试它应该只具有什么,要么它应该具有什么,以较小者为准:

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

ALONG与参数输入aka的预准备语句

1
2
$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