我正在构建一个新的Web应用程序,LAMP环境...我想知道preg_match是否可以信任用户的输入验证(当然+准备好的stmt)用于所有基于文本的字段(也就是不是HTML字段;电话,名称) ,姓氏等.).
例如,对于经典的"电子邮件字段",如果我检查输入如下:
$email_pattern = "/^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)" . "|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}" . "|[0-9]{1,3})(\]?)$/"; $email = $_POST['email']; if(preg_match($email_pattern, $email)){ //go on, prepare stmt, execute, etc... }else{ //email not valid! do nothing except warn the user }
我可以在SQL/XXS注入时轻松入睡吗?
我写的正则表达式更具限制性.
编辑:正如已经说过的,我确实使用了预处理语句,这种行为仅适用于基于文本的字段(如电话,电子邮件,姓名,姓氏等),因此不允许包含HTML(对于HTML字段) ,我使用HTMLpurifier).
实际上,我的任务是只有在匹配我的regexp-white-list时才传递输入值; 否则,将其返回给用户.
ps ::我正在寻找没有mysql_real_escape_strings的东西; 可能该项目将在未来切换到Postgresql,因此需要一个跨数据库的验证方法;)
正则表达式是否足以进行过滤取决于正则表达式.如果您要在SQL语句中使用该值,则正则表达式必须以某种方式禁止'
和"
.如果你想使用HTML输出中的值并且害怕XSS,你必须确保你的正则表达式不允许<
,>
并且"
.
尽管如此,正如已经反复说,你不希望依靠正则表达式,并请$神的爱,不要!在HTML上下文中打印时,请为您的SQL语句使用mysql_real_escape_string()或预准备语句,并为您的值使用htmlspecialchars().
根据其背景选择消毒功能.作为一般的经验法则,它比你更了解什么是什么,什么不危险.
编辑,以适应您的编辑:
准备好的语句== mysql_real_escape_string()放在每个值上.基本上完全相同的东西,没有在准备好的语句变体中提高性能,并且无法忘记在其中一个值上使用该函数.准备好的语句可以保护你免受SQL注入,而不是正则表达式.你的正则表达式可以是任何东西,它对准备好的声明没有任何影响.
您不能也不应该尝试使用正则表达式来构建"跨数据库"架构.同样,通常系统比你更了解它的危险性和危害性.准备好的陈述是好的,如果这些陈述与变化兼容,那么你可以轻松入睡.没有正则表达式.
如果它们不是,你必须使用抽象层到你的数据库,类似于自定义的$ db-> escape(),它在你的MySQL体系结构中映射到mysql_real_escape_string(),在你的PostgreSQL体系结构中映射到PostgreSQL的相应方法(我不知道哪个是副手,抱歉,我没有使用过PostgreSQL).
HTML Purifier是一种清理HTML输出的好方法(假设你在白名单模式下使用它,这是它附带的设置),但你应该只在你绝对需要保留HTML的东西上使用它,因为调用一个purify( )是非常昂贵的,因为它解析整个事物并以旨在彻底性和通过一套强大的规则的方式操纵它.因此,如果您不需要保留HTML,则需要使用htmlspecialchars().但话说回来,在这一点上,你的正则表达式与你的逃避无关,而且可能是任何东西.
实际上,我的任务是只有在匹配我的regexp-white-list时才传递输入值; 否则,将其返回给用户.
这可能不适用于您的场景,但仅作为一般信息:"将错误输入返回给用户"的理念可能会导致您反映XSS攻击.用户并不总是攻击者,因此在将内容返回给用户时,请确保将其全部撤销.请记住一些事情.
对于SQL注入,你应该总是使用正确的转义
你已经做过了.mysql_real_escape_string
.最好的方法是使用预备语句(甚至是ORM)来防止遗漏.
其余的取决于您的应用程序的逻辑.您可以过滤HTML以及验证,因为您需要正确的信息,但我不进行验证以防止XSS,我只进行业务验证*.
一般规则是"过滤/验证输入,转义输出".所以我逃避了我显示的内容(或传输给第三方)以防止HTML标记,而不是我记录的内容.
*不过,一个人的姓名或电子邮件地址不应包含 < >