为什么我们需要特定于数据库的功能,例如mysql_real_escape_string()? addlashes()不能做什么?
暂时忽略了参数化查询的高级替代方案,是一个仅使用addlashes()的web应用仍然容易受到SQL注入的攻击,如果是,怎么办?
当处理多字节编码的字符串时,加号通常不够好。
任何有效的多字节字符以0x5c结尾的编码都可以在addslashes()之后使用引号。克里斯·希弗莱特(Chris Shiflett)在其使用GBK的博客中有一个很好的例子。 shiflett.org/blog/2006/jan/
你是对的,但你没有说怎么做。
恰恰相反-一般情况下,加号是可以的,但在极少数情况下,我们实际上需要mre。
它将斜杠添加到:
\x00,
,
, \, '," and \x1a. characters.
凡加斜杠仅将斜杠添加到
' \ and NUL
Ilias的文章也非常详细地介绍了其功能
gs严厉否决的答案实际上是正确的。
标准SQL使用加倍符来避免文字撇号。 MySQL的反斜杠用于转义的非标准用法是默认设置,但可以禁用它,并且通常是禁用的,特别是在sql_mode ANSI中。
在这种情况下,只有加倍的语法会起作用,并且您使用addslashes(或其他临时转义方法)的任何应用程序都会中断。 mysql_real_escape_string将使用最适合连接sql_mode的任何转义方法。
如果您仍在使用那些讨厌的东亚编码(可重复使用较低的128个字符),那么多字节编码问题也很重要,但实际上,您确实想使用UTF-8。 n转义是无关紧要的,因为MySQL可以在语句中完全愉快地处理原始换行符。
mysql_real_escape_string比addslashes做的更多。
addlashes在纯ascii上运行,而对数据库一无所知。它逃脱了:
'→\'
"→\"
\→\\
ASCII 0→\0。
mysql_real_escape_string的目的是"创建可在SQL语句中使用的合法SQL字符串"。 mysql_real_escape_string考虑了连接的当前字符集(这就是为什么必须始终传递有效的$ mysql对象的原因)。
它执行以下操作(取自MySQL C API文档):
编码:\,',",ASCII 0,,和Control+Z
确保0字节终止字符串(在C api中)
如果$ mysql中链接的数据库使用宽字符集,则可以执行多字节(ascii)到宽字符转换。
我真的不知道PHP如何在内部存储字符串,但是要点是,当您使用mysql_real_escape_string时,PHP都可以使用所有这些功能。我想区别的主要点是mysql_real_escape_string考虑了连接的字符集,而addslashes却不能(它甚至不知道您连接的是哪个DB)。
大多数要点都没有道理。无论使用什么方式,addslashes都会创建合法的SQL字符串。 mres根本不进行字符转换。而且用NUL终止字符串毫无意义。你从哪儿得到的?
直接来自文档。多字节可能会转换为宽。"由from指向的字符串必须是长度字节长。必须将to缓冲区分配为至少长度* 2 + 1字节长。(在最坏的情况下,每个字符可能需要使用两个字节进行编码,并且您需要为终止的空字节留出空间。)"。我假设PHP库在后台调用了mysql_real_escape_string C API函数。
somedb_real_escape_string()是特定于数据库的,addslashes()不是。
对于MySQL,这意味着:
mysql_real_escape_string() calls
MySQL's library function
mysql_real_escape_string, which
prepends backslashes to the following
characters: \x00,
,
, \, '," and
\x1a.
(来自手册。)
Why do we need a DB-specific functions like mysql_real_escape_string()?
实际上,大多数时候我们不这样做。
一些极少见的编码需要此功能,并且要美化mysql日志并转储一下。
is a webapp that uses addslashes() exclusively still vulnerable to SQL injection?
只要它使用任何单字节字符集或utf8,它都可以通过addslashes()完全安全。
What can it do that addslashes() doesn't?
在某些罕见编码的情况下,它可以保护SQL字符串文字。
但是,它本身无法做到。必须首先使用mysql_set_charset()函数设置正确的编码。如果未使用此功能,则在字符集处理方面,mysql_real_escape_string()的行为与addslashes()完全相同-根本没有区别。
只要它使用任何单字节字符集或utf8,它都可以通过addslashes()完全安全。为什么要使用addslashes作为惯例,而一旦使用Unicode,却突然不得不改变惯例?
不幸的是,从PHP开始,您必须在服务器级别设置字符集或使用mysqli_set_charset。 C并非如此。
@bobobobo" [使用utf8时,addslashes绝对是安全的……如果您在使用Unicode后突然不得不改变惯例,为什么要使用addlashes?"你误会了; UTF-8是Unicode。唯一易受攻击的情况是使用非Unicode字符集,例如GBK。也就是说,addslashes()对于使用Unicode的任何人都是绝对安全的,并且仅对选择使用奇怪的国家字符集代替Unicode的人是不安全的。
客观地解决addslashes()情况的极为罕见的答案之一。普通常识!
PHP的mysql_real_escape_string函数或多或少会询问mysql需要转义什么字符,而addlashses函数将在其前面加上反斜杠,并在单引号('),双引号("),反斜杠()前面添加反斜杠。或NUL(空字节)字符。
这两个实际的效果是,addlashes不能与多字节字符一起很好地工作,更重要的是,通过询问mysql需要转义哪些字符,可以避免将来可能的兼容性。使用斜杠有点像将几个特定字符硬编码到转义序列中。
根据PHP手册:
mysql_real_escape_string() calls MySQL's library function mysql_real_escape_string, which prepends backslashes to the following characters: \x00,
,
, \, '," and \x1a.
我所知道的唯一真正的区别是,在转义输入字符串时,mysql_real_escape_string()将考虑数据库的字符集。这两个函数都不会转义通配符%和_,这仍然使脚本可以进行某些SQL注入。
%和_与SQL注入无关。
在MySQL中,%可在GRANT语句中用作通配符。 MySQL也将_视为语句中的单个字符通配符。
%和_与SQL注入无关。
根据我的理解,mysql_real_escape_string()可以更精确地完成工作,因为它与db通信以首先检查需要编码的内容,然后进行相应的编码,不是吗?因此,它的工作效率更高
为什么要先做addlashes,然后在显示数据之前仍然删除斜线,仍然显示addlashes效率不如mysql_real_escape_string,如果使用mysql_query这样的db函数查询,请使用mysql_real_escape_string,或者我认为带prepare的PDO是更好的方法,因为mysql_real_escape_string是数据库特定的
它应该以其他引号功能无法实现的方式对MySQL的字符串进行转义。
但是,更可取的是使用mysqli接口,并使用参数化的预准备查询,而不是尝试确保所有字符串均已正确转义。使用参数化查询消除了对此类混乱字符串工作的需求,并大大降低了SQL注入的风险。
编辑:我将澄清为什么我考虑引用一个坏主意:很容易忘记何时何地需要引用-变量是字符串还是数字,是否已经被引用,等等。参数化查询没有这些问题,并且完全消除了引用的需要。
我想我应该澄清一下,我非常清楚参数化查询的优越性:)