您好,欢迎访问三七文档
当前位置:首页 > 办公文档 > 事务文书 > PHP代码安全性的规范
PHP代码安全性的规范1、SQL注入1.1概念所谓SQL注入,就是通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。1.2危害查询数据库中敏感信息。绕过认证。添加、删除、修改服务器数据。拒绝服务。?id=(BENCHMARK(100000000,MD5(RAND()));1.3原因php配置文件php.ini中的magic_quotes_gpc选项没有打开,被置为off开发者没有对数据类型进行检查和转义第二点最为重要?因为如果没有第二点的保证,magic_quotes_gpc选项,不论为on,还是为off,都有可能引发SQL注入攻击。1.4例子magic_quotes_gpc=Off时的注入攻击magic_quotes_gpc=Off是php中一种非常不安全的选项。新版本的php已经将默认的值改为了On。但仍有相当多的服务器的选项为off。当magic_quotes_gpc=On时,它会将提交的变量中所有的'(单引号)、(双号号)、\(反斜线)、空白字符,都为在前面自动加上\。下面是php的官方说明:magic_quotes_gpcbooleanSetsthemagic_quotesstateforGPC(Get/Post/Cookie)operations.Whenmagic_quotesareon,all'(single-quote),(doublequote),\(backslash)andNUL'sareescapedwithabackslashautomatically如果没有转义,即off情况下,就会让攻击者有机可乘。当用户输入正常的用户名和密码,假设值分别为zhang3、abc123,则提交的SQL语句如下:SELECT*FROMtbl_usersWHEREusername='zhang3'ANDpassword='abc123'LIMIT0,1如果攻击者在username字段中输入:zhang3'OR1=1#,在password输入abc123,则提交的SQL语句变成如下:SELECT*FROMtbl_usersWHEREusername='zhang3'OR1=1#'ANDpassword='abc123'LIMIT0,1由于#是mysql中的注释符,#之后的语句不被执行,实现上这行语句就成了:SELECT*FROMtbl_usersWHEREusername='zhang3'OR1=1这样攻击者就可以绕过认证了。如果攻击者知道数据库结构,那么它构建一个UNIONSELECT,那就更危险了:假设在username中输入:zhang3'OR1=1UNIONselectcola,colb,coldFROMtbl_b#在password输入:abc123,则提交的SQL语句变成:SELECT*FROMtbl_usersWHEREusername='zhang3'OR1=1UNIONselectcola,colb,coldFROMtbl_b#'ANDpassword='abc123'LIMIT0,1这样就相当危险了。magic_quotes_gpc=On时的注入攻击当magic_quotes_gpc=On时,攻击者无法对字符型的字段进行SQL注入。这并不代表这就安全了。这时,可以通过数值型的字段进行SQL注入。在最新版的MYSQL5.x中,已经严格了数据类型的输入,已默认关闭自动类型转换。数值型的字段,不能是引号标记的字符型。也就是说,假设uid是数值型的,在以前的mysql版本中,这样的语句是合法的:INSERTINTOtbl_userSETuid=1;SELECT*FROMtbl_userWHEREuid=1;在最新的MYSQL5.x中,上面的语句不是合法的,必须写成这样:INSERTINTOtbl_userSETuid=1;SELECT*FROMtbl_userWHEREuid=1;那么攻击者在magic_quotes_gpc=On时,他们怎么攻击呢?很简单,就是对数值型的字段进行SQL注入。一个正常的语句,用户输入1001和abc123,提交的sql语句如下:SELECT*FROMtbl_usersWHEREuserid=1001ANDpassword='abc123'LIMIT0,1如果攻击者在userid处,输入:1001OR1=1#,则注入的sql语句如下:SELECT*FROMtbl_usersWHEREuserid=1001OR1=1#ANDpassword='abc123'LIMIT0,1攻击者达到了目的。1.5解决方法如何防止phpsql注入攻击?我认为最重要的一点,就是要对数据类型进行检查和转义。总结的几点规则如下:1)、php.ini中的display_errors选项,应该设为display_errors=off。这样php脚本出错之后,不会在web页面输出错误,以免让攻击者分析出有作的信息。调用mysql_query等mysql函数时,前面应该加上@,即@mysql_query(...),这样mysql错误不会被输出。同理以免让攻击者分析出有用的信息。2)、SQL组装的时候,对外部变量以及所有变量都进行过滤:define(XH_PARAM_INT,0);define(XH_PARAM_TXT,1);functionPAPI_GetSafeParam($pi_strName,$pi_Def=,$pi_iType=XH_PARAM_TXT){if(isset($_GET[$pi_strName]))$t_Val=trim($_GET[$pi_strName]);elseif(isset($_POST[$pi_strName]))$t_Val=trim($_POST[$pi_strName]);elsereturn$pi_Def;//INTif(XH_PARAM_INT==$pi_iType){if(is_numeric($t_Val))return$t_Val;elsereturn$pi_Def;}//String$t_Val=str_replace(&,&,$t_Val);$t_Val=str_replace(,<,$t_Val);$t_Val=str_replace(,>,$t_Val);if(get_magic_quotes_gpc()){$t_Val=str_replace(\\\,",$t_Val);$t_Val=str_replace(\\'',',$t_Val);}else{$t_Val=str_replace(\,",$t_Val);$t_Val=str_replace(',',$t_Val);}return$t_Val;}3)、php可用于防注入的一些函数addslashes和stripslashesAddslashes给这些“’”、“””、“\”,“NULL”添加斜杆“\’”、“\””、“\\”,“\NULL”,stripslashes则相反,这里要注意的是php.ini是否开启了magic_quotes_gpc=ON,开启若使用addslashes会出现重复。所以使用的时候要先get_magic_quotes_gpc()检查一般代码类似:1.if(!get_magic_quotes_gpc())2.{3.$abc=addslashes($abc);4.}mysql_escape_string()和mysql_real_escape_string()mysql_real_escape_string必须在(PHP4=4.3.0,PHP5)的情况下才能使用。否则只能用mysql_escape_string1.if(PHP_VERSION='4.3')2.{3.$string=mysql_real_escape_string($string);4.}else5.{6.$string=mysql_escape_string($string);7.}mysql_escape_string()和mysql_real_escape_string()却别在于后者会判断当前数据库连接字符集,换句话说在没有连接数据库的前提下会出现类似错误:Warning:mysql_real_escape_string()[function.mysql-real-escape-string]:Accessdeniedforuser'ODBC'@'localhost'(usingpassword:NO)inE:\webphp\test.phponline11字符代替函数和匹配函数str_replace()、perg_replace()这些函数之所以也在这里提是因为这些函数可以用于过滤或替代一些敏感、致命的字符。防注入字符优先级防注入则要先知道有哪些注入字符或关键字,常见的mysql注入字符有字符界定符号如“'”、“”;逻辑关键字如“and”、“or”;mysql注悉字符如“#”,“--”,“/**/”;mysql通配符“%”,“_”;mysql关键字“select|insert|update|delete|*|union|join|into|load_file|outfile”A、防注入优先级最高的是空格””,空格字符的变种有:“%20”,“\n”,“\r”,“\r\n”,“\n\r”,“chr(32)”这也是为什么mysql_escape_string()和mysql_real_escape_string()两个函数转义“\n”,“\r”。B、“and”,“or”,“\”,“#”,“--”。逻辑关键可以组合很多注入代码;mysql注悉则把固有sql代码后面的字符全部给注悉掉从而让注入后的sql语句能正常运行;“\”也是能组合很多注入字符\x00,\x1a。sql解析“#”,“--”是大多数mysql防注入代码没有考虑到的,也是很多phper忽略。还有因为一些phper给参数赋值的时候会有用“-”来隔开,所以笔者建议不要这样写参数,当然也可以再过滤参数的时候“--”(注意有空格的,没空格不解析为注悉)当一个整体过滤而不是过滤“-”,这样就避免过多过滤参数。C、“null”,“%”,“_”。这几个不能独立,都不要在特定情况下,比如通配字符“%,_”都要在mysqllike子句的前提下。所以“%”,“_”的过滤一般在搜索相关才过滤,不能把它们纳入通常过滤队列,因为有些如邮箱就可以有”_”字符D、关键字“select|insert|update|delete|*|union|join|into|load_file|outfile”。也许你会问怎么这些重要关键字却优先级这么低。笔者想说的是因为这些关键字在没有“'”,“”,“”,“and”,“or”等情况下购不成伤害。换句话说这些关键字不够“独立”,“依赖性”特别大。当然优先级低,不代表不要过滤。2、XML注入2.1概念XML是存储数据的地方,如果在查询或修改时,如果没有做转义,直接输入或输出数据,都将导致XML注入漏洞。攻击者可以修改XML数据格式,增加新的XML节点,对数据处理流程产生影响。2.2危害攻击者可以新增XML节点破坏原来的XML结构,影响业务流程,甚至产生严重的错误。2.3例子$xml=USERrole=guestname“.$_GET[‘name’]./nameemail“.$_GET[‘email’]./email/USER;需要得到的XML结构:?xmlversion=1.0encoding=UTF-8?USERrole=guestnameuser1/nameemailuser1@a.com/email/USER恶意代码:user1@a.com/email/USERUSERrole=adminnametest
本文标题:PHP代码安全性的规范
链接地址:https://www.777doc.com/doc-2850380 .html