防止SQL Injection攻击

1 篇文章 0 订阅
根据你的使用目的我觉得这个函数有两方面的用途:

1.防止SQL Injection攻击,也就是你必须验证用户的输入
2.操作数据的时候避免不必要的字符导致错误
mysql_real_escape_string() 函数转义 SQL 语句中使用的字符串中的特殊字符。

下列字符受影响:

•\x00
•\n
•\r
•\
•'
•"
•\x1a
如果成功,则该函数返回被转义的字符串。如果失败,则返回 false。

攻击的例子[1]

例子 1
<?php
$con = mysql_connect("localhost", "hello", "321");
if (!$con)
{
die('Could not connect: ' . mysql_error());
}
// 获得用户名和密码的代码

// 转义用户名和密码,以便在 SQL 中使用
$user = mysql_real_escape_string($user);
$pwd = mysql_real_escape_string($pwd);

$sql = "SELECT * FROM users WHERE
user='" . $user . "' AND password='" . $pwd . "'"

// 更多代码

mysql_close($con);
?>

例子 2
数据库攻击。本例演示如果我们不对用户名和密码应用 mysql_real_escape_string() 函数会发生什么:

<?php
$con = mysql_connect("localhost", "hello", "321");
if (!$con)
{
die('Could not connect: ' . mysql_error());
}
$sql = "SELECT * FROM users
WHERE user='{$_POST['user']}'
AND password='{$_POST['pwd']}'";
mysql_query($sql);

// 不检查用户名和密码
// 可以是用户输入的任何内容,比如:
$_POST['user'] = 'john';
$_POST['pwd'] = "' OR ''='";

// 一些代码...

mysql_close($con);
?>

那么 SQL 查询会成为这样:
SELECT * FROM users WHERE user='john' AND password='' OR ''=''这意味着任何用户无需输入合法的密码即可登陆。

例子 3
预防数据库攻击的正确做法:

<?php
function check_input($value)
{
// 去除斜杠
if (get_magic_quotes_gpc())
{
$value = stripslashes($value);
}
// 如果不是数字则加引号
if (!is_numeric($value))
{
$value = "'" . mysql_real_escape_string($value) . "'";
}
return $value;
}

$con = mysql_connect("localhost", "hello", "321");
if (!$con)
{
die('Could not connect: ' . mysql_error());
}

// 进行安全的 SQL
$user = check_input($_POST['user']);
$pwd = check_input($_POST['pwd']);
$sql = "SELECT * FROM users WHERE
user=$user AND password=$pwd";

mysql_query($sql);

mysql_close($con);
?>

对于情况2,当使用PHP准别数据插入的时候,如果插入数据包含单引号或者双引号,会导致插入失败。通过mysql_real_escape_string就可以避免这种错误。我的经验是,这个错误不太容易发现,前天花了2个小时才找到这个错误。而且这个函数并不会增加字段的长度[2]。

参考:
[1]http://www.w3school.com.cn/php/func_mysql_real_escape_string.asp
[2]http://php.net/manual/en/function.mysql-real-escape-string.php

[b]参数化查询[/b](Parameterized Query 或 Parameterized Statement)是指在设计与数据库链接并访问数据时,在需要填入数值或数据的地方,使用参数 (Parameter) 来给值,这个方法目前已被视为最有效可预防SQL注入攻击 (SQL Injection) 的攻击手法的防御方式。
目录

原理
SQL 指令撰写方法
展开
原理
SQL 指令撰写方法
展开
编辑本段原理
在使用参数化查询的情况下,数据库服务器不会将参数的内容视为SQL指令的一部份来处理,而是在数据库完成 SQL 指令的编译后,才套用参数运行,因此就算参数中含有具有损的指令,也不会被数据库所运行。 有部份的开发人员可能会认为使用参数化查询,会让程序更不好维护,或者在实现部份功能上会非常不便,然而,使用参数化查询造成的额外开发成本,通常都远低于因为SQL注入攻击漏洞被发现而遭受攻击,所造成的重大损失。
编辑本段SQL 指令撰写方法
在撰写 SQL 指令时,利用参数来代表需要填入的数值,例如:
Microsoft SQL Server
Microsoft SQL Server 的参数格式是以 "@" 字符加上参数名称而成,SQL Server 亦支持匿名参数 "?"。  SELECT * FROM myTable WHERE myID = @myID  INSERT INTO myTable (c1, c2, c3, c4) VALUES (@c1, @c2, @c3, @c4)
Microsoft Acce
Microsoft Access 不支持具名参数,只支持匿名参数 "?"。  UPDATE myTable SET c1 = ?, c2 = ?, c3 = ? WHERE c4 = ?
MySQL
MySQL 的参数格式是以 "?" 字符加上参数名称而成。  UPDATE myTable SET c1 = ?c1, c2 = ?c2, c3 = ?c3 WHERE c4 = ?c4
客户端程序撰写方法
在客户端代码中撰写使用参数的代码,例如:
ADO.NET
SqlCommand sqlcmd = new SqlCommand("INSERT INTO myTable (c1, c2, c3, c4) VALUES (@c1, @c2, @c3, @c4)", sqlconn);  sqlcmd.Parameters.AddWithValue("@c1", 1); // 设定参数 @c1 的值。  sqlcmd.Parameters.AddWithValue("@c2", 2); // 设定参数 @c2 的值。  sqlcmd.Parameters.AddWithValue("@c3", 3); // 设定参数 @c3 的值。  sqlcmd.Parameters.AddWithValue("@c4", 4); // 设定参数 @c4 的值。  sqlconn.Open();  sqlcmd.ExecuteNonQuery();  sqlconn.Close();
PHP
$query = sprintf("SELECT * FROM Users where UserName='%s' and Password='%s'",  mysql_real_escape_string($Username),  mysql_real_escape_string($Password));  mysql_query($query);  或是  $db = new mysqli("localhost", "user", "pass", "database");  $stmt = $mysqli -> prepare("SELECT priv FROM testUsers WHERE username=? AND password=?");  $stmt -> bind_param("ss", $user, $pass);  $stmt -> execute();
JDBC
PreparedStatement prep = conn.prepareStatement("SELECT * FROM USERS WHERE USERNAME=? AND PASSWORD=?");  prep.setString(1, username);  prep.setString(2, password);
Cold Fusion
<cfquery name="Recordset1" datasource="cafetownsend">  SELECT *  FROM COMMENTS  WHERE COMMENT_ID =<cfqueryparam value="#URL.COMMENT_ID#" cfsqltype="cf_sql_numeric">  </cfquery>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值