首页 > MySQL > 【译】如何防范SQL注入攻击(代码示例)

【译】如何防范SQL注入攻击(代码示例)

本文通过一些简单示例解释基本的SQL注入攻击,并提供方法如何去处理这些攻击问题。

如题所示,黑客能够通过SQL查询语句进行攻击。一些网站的开发者还不太了解黑客是如何通过SQL查询来攻击网站的。如果程序完全相信用户的输入信息,并不做一些适当的过滤处理,SQL注入完全可以实现,SQL注入的思路就是让程序运行一些不被期望的SQL查询。

示例测试环境:

  • PHP 5.3.3-7
  • Apache2.2.16
  • Postgresql8.4
SQL注入示例
大多数WEB程序都有一个登陆页面,我们的示例就从这里开始吧。首先我们假设程序页面代码如下(实际项目可能比这个要复杂):
index.html
[code]
<html>
<head><title>SQL Injection Demo</title></head>
<body onload="document.getElementById(‘user_name’).focus();" >
<form name="login_form" id="login_form" method="post" action="login.php">
<table border=0 align="center" >
<tr>
<td colspan=5 align="center" ><font face="Century Schoolbook L" > Login Page </font></td>
</tr>
<tr>
<td> User Name:</td><td> <input type="text" size="13" id="user_name" name="user_name" value=""></td>
</tr>
<tr>
<td> Password: </td><td> <input type="password" size="13" id="pass_word" name="pass_word" value=""></td>
</tr>
<tr>
<td colspan=2 align="center"><input type="submit" value="Login"> </div></td>
</tr>
</table>
</form>
</body>
</html>
[/code]

当用户输入用户名和密码后,将会通过HTTP_POST方法提交到login.php
[code]
<?php
$Host= ‘192.168.1.8’;
$Dbname= ‘john’;
$User= ‘john’;
$Password= ‘xxx’;
$Schema = ‘test’;

$Conection_string="host=$Host dbname=$Dbname user=$User password=$Password";

/* Connect with database asking for a new connection*/
$Connect=pg_connect($Conection_string,$PGSQL_CONNECT_FORCE_NEW);

/* Error checking the connection string */
if (!$Connect) {
echo "Database Connection Failure";
exit;
}

$query="SELECT * from $Schema.users where user_name=’".$_POST[‘user_name’]."’ and password=’".$_POST[‘pass_word’]."’;";

$result=pg_query($Connect,$query);
$rows = pg_num_rows($result);
if ($rows) {
echo "Login Success";
}
else {
echo "Login Failed";
}
?>
[/code]
上面程序的第19行代码将会被利用做SQL注入攻击(i.e 这一行从这里开始“$query=”SELECT * …””).这个地方的SQL查询设计目的是为了把用户输入的用户名和密码与数据库进行匹配.它将会进行合适的处理,如果提供的用户名和密码是可用的话。但是黑客可以巧妙地通过这样输入来“蒙混过关”:

黑客在username字段输入如下内容:

‘ or 1=1;–

之后让密码字段为空.

当黑客提交输入后,login.php文件将对输入做如下处理,并生成如下SQL语句:

SELECT * from test.members where user_name=” or 1=1;–‘ and password=”;

上面的SQL是一个合法的SQL查询语句。在Postgresql字符“-”是注释标识,因此“–”之后的语句将被当作句释处理,最后执行语句将会是:

select * from test.members where user_name=” or 1=1;

这将会返回“true”并返回登陆成功信息。

如果黑客知道数据库的表名称,甚至可以删除整个表,通过向”username”字段输入如下代码:

‘;drop table test.lop;–

一些登陆程序经常会做这样的处理:

  • 将密码进行md5加密运算后存入在数据库中
  • 首先根据用户输入的username查询数据库中对应的username和password字段值
  • 然后对用户输入的密码进行md5加密处理,并跟数据库中的password进行比对
  • 如果比对匹配则登陆验证通过
下面让我们来看看如何通过SQL注入绕开登陆验证

[code]
$query="SELECT user_name,password from $Schema.members where user_name=’".$_POST[‘user_name’]."’;";

$result=pg_query($Connect,$query);

$row=pg_fetch_array($result,NULL,PGSQL_ASSOC);

# Find the md5 for the user supplied password.
$user_pass = md5($_POST[‘pass_word’]);

if(strcmp($user_pass,$row[‘password’])!=0) {
echo "Login Failed\n";
}
else {
echo "Login Success\n";
}
[/code]

现在在username字段输入如下内容

‘ UNION ALL SELECT ‘laksh’,’202cb962ac59075b964b07152d234b70

在password字段输入“123”并提交.md5(123)结果是“202cb962ac59075b964b07152d234b70”

现在SQL语句最后将会是如下形式:

SELECT user_name,password from test.members where user_name=” UNION ALL SELECT ‘laksh’,’202cb962ac59075b964b07152d234b70′;

上面的SQL语句执行后将会以返回”laksh”作为username,“202cb962ac59075b964b07152d234b70”作为password。

我们也会提交”123″作为password字段值,此时输入与数据库返回匹配,登陆验证通过。

上面两个只是两个SQL攻击示例,还有很多变种。

下面我们大概列举常见SQL注入攻击预防手段,可最大程序避免SQL注入侵扰:

  • 严格类型检查(永远不要信任用户输入的数据)
  • 检查用户输入username是否只包含数字和字母
  • 转义或过滤用户输入的特殊字符
  • 使用预处理语句执行查询
  • 一条语句中不允许多条查询
  • 不要让”syntax errors”错误提示泄漏数据库信息

原文地址:http://www.thegeekstuff.com/2012/02/sql-injection-attacks/

引用地址:http://doophp.sinaapp.com/archives/mysql/prevent-sql-injection-attack.html

分类: MySQL 标签: ,
  1. 本文目前尚无任何评论.
  1. 本文目前尚无任何 trackbacks 和 pingbacks.

=4加6(必填)请输入两数相加的结果。