首页 >php教程 >php手册 >PHP防sql注入方法总结分析

PHP防sql注入方法总结分析

WBOY
WBOY原创
2016-05-25 16:41:161118浏览

在程序开发中sql注入是一个大家常常会要考虑到的问题,下面我来解析一下常见的sql防注入代码,有需要的朋友可参考参考.

1、php提交数据过滤的基本原则

1)提交变量进数据库时,我们必须使用addslashes()进行过滤,像我们的注入问题,一个addslashes()也就搞定了,其实在涉及到变量取值时,intval()函数对字符串的过滤也是个不错的选择.

2)在php.ini中开启magic_quotes_gpc和magic_quotes_runtime,magic_quotes_gpc可以把get,post,cookie里的引号变为斜杠。magic_quotes_runtime对于进出数据库的数据可以起到格式话的作用,其实,早在以前注入很疯狂时,这个参数就很流行了,代码如下:

<?php
if (isset($_POST["f_login"])) {
    // 连接数据库...
    // ...代码略...
    // 检查用户是否存在
    $t_strUname = $_POST["f_uname"];
    $t_strPwd = $_POST["f_pwd"];
    $t_strSQL = "SELECT * FROM tbl_users WHERE username=&#39;$t_strUname&#39; AND password = &#39;$t_strPwd&#39; LIMIT 0,1";
    if ($t_hRes = mysql_query($t_strSQL)) {
        // 成功查询之后的处理. 略...
        
    }
}
?>
<html><head><title>sample test</title></head> 
<body> 
<form method=post action=""> 
  Username: <input type="text" name="f_uname" size=30><br> 
  Password: <input type=text name="f_pwd" size=30><br> 
  <input type="submit" name="f_login" value="登录"> 
</form> 
</body>

3)在使用系统函数时,必须使用escapeshellarg(),escapeshellcmd()参数去过滤,这样你也就可以放心的使用系统函数.

4)对于跨站,strip_tags(),htmlspecialchars()两个参数都不错,对于用户提交的的带有html和php的标记都将进行转换。比如尖括号"

$new = htmlspecialchars("Test", ENT_QUOTES);strip_tags($text,); 

5)对于相关函数的过滤,就像先前的include(),unlink,fopen()等等,只要你把你所要执行操作的变量指定好或者对相关字符过滤严密,我想这样也就无懈可击了.

2、PHP简单的数据过滤

1)入库:  trim($str),addslashes($str)

2)出库:  stripslashes($str)

3)显示:  htmlspecialchars(nl2br($str))

一、 注入式攻击的类型

可能存在许多不同类型的攻击动机,但是乍看上去,似乎存在更多的类型。这是非常真实的-如果恶意用户发现了一个能够执行多个查询的办法的话。本文后面,我们会对此作详细讨论。 

如果你的脚本正在执行一个SELECT指令,那么,攻击者可以强迫显示一个表格中的每一行记录-通过把一个例如"1=1"这样的条件注入到WHERE子句中,如下所示,其中,注入部分以粗体显示,代码如下:

SELECT * FROM wines WHERE variety = 'lagrein' OR 1=1;'

正如我们在前面所讨论的,这本身可能是很有用的信息,因为它揭示了该表格的一般结构(这是一条普通的记录所不能实现的),以及潜在地显示包含机密信息的记录。 

一条更新指令潜在地具有更直接的威胁,通过把其它属性放到SET子句中,一名攻击者可以修改当前被更新的记录中的任何字段,例如下面的例子,其中,注入部分以粗体显示,代码如下:

UPDATE wines SET type='red','vintage'='9999' WHERE variety = 'lagrein'

通过把一个例如1=1这样的恒真条件添加到一条更新指令的WHERE子句中,这种修改范围可以扩展到每一条记录,例如下面的例子,其中,注入部分以粗体显示,代码如下:

UPDATE wines SET type='red','vintage'='9999 WHERE variety = 'lagrein' OR 1=1;'

最危险的指令可能是DELETE-这是不难想像的,其注入技术与我们已经看到的相同-通过修改WHERE子句来扩展受影响的记录的范围,例如下面的例子,其中,注入部分以粗体显示,代码如下:

DELETE FROM wines WHERE variety = 'lagrein' OR 1=1;'  

二、多个查询注入

多个查询注入将会加剧一个攻击者可能引起的潜在的损坏-通过允许多条破坏性指令包括在一个查询中,在使用MySQL数据库时,攻击者通过把一个出乎意料之外的终止符插入到查询中即可很容易实现这一点-此时一个注入的引号(单引号或双引号)标记期望变量的结尾,然后使用一个分号终止该指令,现在,一个另外的攻击指令可能被添加到现在终止的原始指令的结尾,最终的破坏性查询可能看起来如下所示"

SELECT * FROM wines WHERE variety = 'lagrein';

GRANT ALL ON *.* TO 'BadGuy@%' IDENTIFIED BY 'gotcha';'

这个注入将创建一个新的用户BadGuy并赋予其网络特权(在所有的表格上具有所有的特权);其中,还有一个"不祥"的口令被加入到这个简单的SELECT语句中。如果你遵循我们在以前文章中的建议-严格限制该过程用户的特权,那么,这应该无法工作,因为web服务器守护程序不再拥有你撤回的GRANT特权。但是从理论上讲,这样的一个攻击可能给予BadGuy自由权力来实现他对你的数据库的任何操作。

下面分享一个自己写的代码,如下:

<?php
function phpsql_show($str) {
    $str = stripslashes($str);
    $str = str_replace("&#92;", "", $str);
    $str = str_replace("&#47;", "/", $str);
    $str = str_replace("&#32;", " ", $str);
    $str = str_replace("&#44;", ",", $str);
    return $str;
}
function phpsql_post($str) {
    $str = stripslashes($str);
    $str = str_replace("|", "&#124;", $str);
    $str = str_replace("<", "<", $str);
    $str = str_replace(">", ">", $str);
    $str = str_replace(" ", "&#32;", $str);
    $str = str_replace(" ", "&#32;", $str);
    $str = str_replace("(", "&#40;", $str);
    $str = str_replace(")", "&#41;", $str);
    $str = str_replace("`", "&#96;", $str);
    //$str = str_replace("&#39;", "&#39;", $str);
    $str = str_replace(&#39;"&#39;, """, $str);
    $str = str_replace(",", "&#44;", $str);
    $str = str_replace("$", "&#36;", $str);
    $str = str_replace("", "&#92;", $str);
    $str = str_replace("/", "&#47;", $str);
    return $str;
}
function phpsql_replace($str) {
    $str = stripslashes($str);
    $str = str_replace("&#39;", "&#39;", $str);
    return $str;
}
?>

总结一下:

* addslashes() 是强行加,

* mysql_real_escape_string() 会判断字符集,但是对PHP版本有要求,

* mysql_escape_string不考虑连接的当前字符集.

dz中的防止sql注入就是用addslashes这个函数,同时在dthmlspecialchars这个函数中有进行一些替换$string = preg_replace(/&((#(d{3,5}|x[a-fA-F0-9]{4}));)/, &1,这个替换解决了注入的问题,同时也解决了中文乱码的一些问题.


本文地址:

转载随意,但请附上文章地址:-)

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn