“中国要复兴、富强,必须在开源软件领域起到主导作用,为了国家安全和人类发展,责无旁贷,我们须为此而奋斗”——By:云客
SQL注入攻击其实就是对数据转义不完全,破坏了预期的sql查询语句的结构,那么今天来聊一聊数据的转义与清理,做好它就能避免这类型的攻击。
php程序曾经出现过魔术引号magic_quotes功能,开启时会自动对数据转义,该功能从5.3版本起废止,并在5.4版本中移除,他们是以下三个:
magic_quotes_sybase:
开启这个选项后,将用单引号对单引号转义,其他字符不转义。默认关闭,可在运行时修改,ini_get()ini_set()获取和设置状态
magic_quotes_gpc:
为 GPC (Get/Post/Cookie) 操作设置 magic_quotes 状态。 当 magic_quotes 为 on,所有的 ' (单引号)、" (双引号)、\(反斜杠)和 NUL's 被一个反斜杠自动转义。如果 magic_quotes_sybase 也是 ON,它会完全覆盖 magic_quotes_gpc。 两个指令都启用意味着只有单引号被转义为 ''(用单引号对单引号转义)。 双引号、反斜杠和 NUL's 不会被转义。bool get_magic_quotes_gpc ( void )获取当前 magic_quotes_gpc 的配置选项设置,注意尝试在运行时设置 magic_quotes_gpc 将不会生效,只能在系统级别关闭。
magic_quotes_runtime:
如果启用了 magic_quotes_runtime,大多数返回任何形式外部数据的函数,包括数据库和文本段将会用反斜线转义引号。 如果启用了 magic_quotes_sybase,单引号会被单引号转义而不是反斜线。bool set_magic_quotes_runtime ( bool $new_setting )设置是否开启,magic_quotes_runtime()是它的别名,bool get_magic_quotes_runtime ( void )获取当前状态
注意:以上的魔术引号功能从5.3版本起废止,并在5.4版本中移除,获取状态时将始终返回false.
以下是php转义方面的函数:
addslashes():
添加反斜线,函数原型string addslashes ( string $str )返回字符串,该字符串为了数据库查询语句等的需要在某些字符前加上了反斜线。这些字符是单引号(')、双引号(")、反斜线(\)与 NUL(NULL 字符)。
stripslashes()
去掉反斜线,函数原型string stripslashes ( string $str ),返回一个去除转义反斜线后的字符串(\' 转换为 ' 等等)。在多个连续反斜线的情况下,用它转义后并不能保证返回字符里面就没有反斜线了,比如在连续三个反斜线的情况下会保留一个返回。,经过笔者测试,此函数去除反斜杠的规则为:连续两个及两个以内则全部去除,超过两个则减去2再除以4,进一法取整,如7个连续的反斜杠经过它处理后为:ceil((7-2)/4)=2个,所以在实际的运用中可以将3个以上的连续反斜线替换为3个再用这个函数。注意,这个问题在php官方网站没有提及。
addcslashes():
以 C 语言风格使用反斜线转义字符串中的字符, string addcslashes ( string $str , string $charlist ),返回字符串,该字符串在属于参数 charlist 列表中的字符前都加上了反斜线。它可以对任意字符转义,甚至可以指定字符范围,在该范围内的字符全部进行转义,详见php官方网站有详细介绍
stripcslashes():
反引用一个使用 addcslashes() 转义的字符串, string stripcslashes ( string $str ),返回反转义后的字符串。可识别类似 C 语言的 \n,\r,... 八进制以及十六进制的描述。
在和数据库交互的时候强烈建议使用 DBMS 指定的转义函数 (比如 MySQL 是 mysqli_real_escape_string(),PostgreSQL 是 pg_escape_string()),但是如果你使用的 DBMS 没有提供一个转义函数,并且使用 \ 来转义特殊字符,你可以使用上面的函数,额外的 \ 并不会插入。
mysql_escape_string():
string mysql_escape_string ( string $unescaped_string )它将 unescaped_string 转义,使之可以安全用于 mysql_query()。但mysql_escape_string() 并不转义 % 和 _。 此函数和 mysql_real_escape_string() 完全一样,除了 mysql_real_escape_string() 接受的是一个连接句柄并根据当前字符集转移字符串之外。mysql_escape_string() 并不接受连接参数,也不管当前字符集设定。 在ASCII, UTF-8, or ISO-8859-*的情况下可以安全转义字符,在使用多字节字符集的时候它可能是不安全的,基于这个原因所以推荐用mysqli_real_escape_string代替
那么为了防范SQL注入攻击,我们来仔细看看这个mysqli_real_escape_string函数:
mysqli_real_escape_string():
函数原型:string mysql_real_escape_string ( string $unescaped_string [, resource $link_identifier ] )此函数转义 SQL 语句中使用字符串中的特殊字符,并考虑到连接的当前字符集,防止多字节字符攻击问题,因此可以安全用于 mysql_query()。 注意它并不转义 % 和 _。 在mysql中%代表正则表达式中的*,_代表?
在实际运用中最常用的搜索功能如下:
SELECT * FROM table_name where new like '%key%' and ok=1;其中key为关键词,如果key不转义则如果其值为:key%'# 就会中断#后面的部分,#在mysql中代表注释(在mysql中-- (双长划)也代表注释,不过该注释风格要求在两个长划后至少有一个空格!否则出错) ,使得#后面的限制条件失效,如果在#前面再加上union语句则可以查出其他数据表的内容!所以使用外来数据和数据库交互时务必使用mysqli_real_escape_string()进行转义
刚才说了mysqli_real_escape_string()并不对%和_转义,在上面的查询时用他们做关键词会列出全部OK=1的内容(和关键字为空效果一样),所以还是有必要转义他们的。
那么如果用反斜杠本身做关键词呢?则需要对反斜杠转义后形成\\再提交给该函数再次转义形成4个连续的\才能查询出内容中包含一个反斜线的记录
在查询的实际运用中$str是外部数据,这样做是稳妥的:$str=mysqli_real_escape_string($link,addcslashes($str,"\\%_"));
多重转义并不会突破SQL语句的结构,但会导致查询失败,初学者可能会想既然 ' 被转义成了 \' 那么使用 \' 能否达成攻击呢?意图是提交反斜线破坏函数添加的反斜线,但答案是不能,它会被转义成 \\\' 也就是说反斜线本身还会被转义一次。
至于插入修改数据也需要用此函数转义外部数据,注意mysqli_real_escape_string()并不对 ~!@#$%^&*()[]=;:+-/`<>及空格转义,特别注意 ` (tab上面那个键)是不转义的
做好这些sql注入攻击基本就不可能实现了
交流互动