轻则数据遭到泄露,重则服务器被拿下
1.SQL注入产生的原因:程序开发过程中不注意规范书写sql语句和对特殊字符进行过滤,导致客户端可以通过全局变量POST和GET提交一些sql语句正常执行。
2.SQL注入的步骤:
a.寻找注入点(如:登录界面,留言板)
b.构造SQL语句(如: ' or 1=1# )
c.将sql语句发送给数据库管理系统(DBMS)
d.DBMS接受请求,并将改请求解释成机器代码指令,执行必要的存取操作
e.DBMS接受返回的结果,并处理,返回给用户
3.SQL注入实例详解:
登录后台管理员页面
a.首先创建一张试验用的数据表
CREATETABLE `users` (
`id`int(11) NOT NULL AUTO_INCREMENT,
`username`varchar(64) NOT NULL,
`password`varchar(64) NOT NULL,
`email`varchar(64) NOT NULL,
PRIMARYKEY (`id`),
UNIQUEKEY `username` (`username`)
)ENGINE=MyISAM AUTO_INCREMENT=3 DEFAULT CHARSET=latin1;
b.添加一条记录用于测试
INSERTINTO users (username,password,email)
VALUES('MarcoFly',md5('test'),'marcofly@test.com');
c.登录界面的源代码如下
<html>
<head>
<title>Sql注入演示</title>
<meta http-equiv="content-type"content="text/html;charset=utf-8">
</head>
<body>
<form action="validate.php" method="post">
<fieldset >
<legend>Sql注入演示</legend>
<table>
<tr>
<td>用户名:</td>
<td><inputtype="text" name="username"></td>
</tr>
<tr>
<td>密 码:</td>
<td><inputtype="text" name="password"></td>
</tr>
<tr>
<td><inputtype="submit" value="提交"></td>
<td><inputtype="reset" value="重置"></td>
</tr>
</table>
</fieldset>
</form>
</body>
</html>
d.当用户单击提交按钮的时候,将会把表单的数据提交给validate.php页面,这个页面用来判断用户输入的用户名和密码有没有符合要求,
(这一步至关重要,也往往是SQL漏洞所在)
<?php
$conn=@mysql_connect("localhost",'root','')or die("数据库连接失败!");;
mysql_select_db("injection",$conn) or die("您要选择的数据库不存在");
$name=$_POST['username'];
$pwd=$_POST['password'];
$sql="select * from users where username='$name' andpassword='$pwd'";
$query=mysql_query($sql);
$arr=mysql_fetch_array($query);
if(is_array($arr)){
header("Location:manager.php");
}else{
echo "您的用户名或密码输入有误,<a href="Login.php">请重新登录!</a>";
}
?>
注意到了没有,我们直接将用户提交过来的数据(用户名和密码)直接拿去执行,并没有实现进行特殊字符过滤,待会你们将明白,这是致命的。
代码分析:如果,用户名和密码都匹配成功的话,将跳转到管理员操作界面(manager.php),不成功,则给出友好提示信息。
到这里,前期工作已经做好了
e.接下来将展开我们的重头戏:SQL注入
填好正确的用户名(marcofly)和密码(test)后,点击提交,将会返回给我们“欢迎管理员”的界面。
因为根据我们提交的用户名和密码被合成到SQL查询语句当中之后是这样的:
select * from users where username='marcofly' andpassword=md5('test')
很明显,用户名和密码都和我们之前给出的一样,肯定能够成功登陆。但是,如果我们输入一个错误的用户名或密码呢?很明显,肯定登入不了吧。
恩,正常情况下是如此,但是对于有SQL注入漏洞的网站来说,只要构造个特殊的“字符串”,照样能够成功登录。
比如:在用户名输入框中输入:' or 1=1#,密码随便输入,这时候的合成后的SQL查询语句为:
select * from users where username='' or 1=1#' and password=md5('')
语义分析:“#”在mysql中是注释符,这样井号后面的内容将被mysql视为注释内容,这样就不会去执行了,换句话说,以下的两句sql语句等价:
select * from users where username='' or 1=1#' and password=md5('')
select *from users where username='' or 1=1
因为1=1永远是都是成立的,即where子句总是为真,将该sql进一步简化之后,等价于如下select语句:
select * from users
3.防止SQL注入的方式:使用预备义语句和参数化查询,对于带有任何参数的Sql语句都会被发送到数据库服务器并被解析。
a.使用PDO(PHP DATA Objects)代码如下:
$stmt = $pdo->prepare('SELECT * FROM employees WHERE name = :name');
$stmt->execute(array(':name' => $name));
foreach ($stmt as $row) {
// do something with $row
}
b.使用mysqli代码如下
$stmt = $dbConnection->prepare('SELECT * FROM employees WHERE name = ?');
$stmt->bind_param('s', $name);
$stmt->execute()
$result = $stmt->get_result();
while ($row = $result->fetch_assoc()) {
// do something with $row
}
1 开启配置文件中的magic_quotes_gpc 和 magic_quotes_runtime设置
2 执行sql语句时使用addslashes进行sql语句转换
3 Sql语句书写尽量不要省略双引号和单引号。
4 过滤掉sql语句中的一些关键词:update、insert、delete、select、 * 。
5 提高数据库表和字段的命名技巧,对一些重要的字段根据程序的特点命名,取不易被猜到的。
6 Php配置文件中设置register_globals为off,关闭全局变量注册
7 控制错误信息,不要在浏览器上输出错误信息,将错误信息写到日志文件中。
1.SQL注入产生的原因:程序开发过程中不注意规范书写sql语句和对特殊字符进行过滤,导致客户端可以通过全局变量POST和GET提交一些sql语句正常执行。
2.SQL注入的步骤:
a.寻找注入点(如:登录界面,留言板)
b.构造SQL语句(如: ' or 1=1# )
c.将sql语句发送给数据库管理系统(DBMS)
d.DBMS接受请求,并将改请求解释成机器代码指令,执行必要的存取操作
e.DBMS接受返回的结果,并处理,返回给用户
3.SQL注入实例详解:
登录后台管理员页面
a.首先创建一张试验用的数据表
CREATETABLE `users` (
`id`int(11) NOT NULL AUTO_INCREMENT,
`username`varchar(64) NOT NULL,
`password`varchar(64) NOT NULL,
`email`varchar(64) NOT NULL,
PRIMARYKEY (`id`),
UNIQUEKEY `username` (`username`)
)ENGINE=MyISAM AUTO_INCREMENT=3 DEFAULT CHARSET=latin1;
b.添加一条记录用于测试
INSERTINTO users (username,password,email)
VALUES('MarcoFly',md5('test'),'marcofly@test.com');
c.登录界面的源代码如下
<html>
<head>
<title>Sql注入演示</title>
<meta http-equiv="content-type"content="text/html;charset=utf-8">
</head>
<body>
<form action="validate.php" method="post">
<fieldset >
<legend>Sql注入演示</legend>
<table>
<tr>
<td>用户名:</td>
<td><inputtype="text" name="username"></td>
</tr>
<tr>
<td>密 码:</td>
<td><inputtype="text" name="password"></td>
</tr>
<tr>
<td><inputtype="submit" value="提交"></td>
<td><inputtype="reset" value="重置"></td>
</tr>
</table>
</fieldset>
</form>
</body>
</html>
d.当用户单击提交按钮的时候,将会把表单的数据提交给validate.php页面,这个页面用来判断用户输入的用户名和密码有没有符合要求,
(这一步至关重要,也往往是SQL漏洞所在)
<?php
$conn=@mysql_connect("localhost",'root','')or die("数据库连接失败!");;
mysql_select_db("injection",$conn) or die("您要选择的数据库不存在");
$name=$_POST['username'];
$pwd=$_POST['password'];
$sql="select * from users where username='$name' andpassword='$pwd'";
$query=mysql_query($sql);
$arr=mysql_fetch_array($query);
if(is_array($arr)){
header("Location:manager.php");
}else{
echo "您的用户名或密码输入有误,<a href="Login.php">请重新登录!</a>";
}
?>
注意到了没有,我们直接将用户提交过来的数据(用户名和密码)直接拿去执行,并没有实现进行特殊字符过滤,待会你们将明白,这是致命的。
代码分析:如果,用户名和密码都匹配成功的话,将跳转到管理员操作界面(manager.php),不成功,则给出友好提示信息。
到这里,前期工作已经做好了
e.接下来将展开我们的重头戏:SQL注入
填好正确的用户名(marcofly)和密码(test)后,点击提交,将会返回给我们“欢迎管理员”的界面。
因为根据我们提交的用户名和密码被合成到SQL查询语句当中之后是这样的:
select * from users where username='marcofly' andpassword=md5('test')
很明显,用户名和密码都和我们之前给出的一样,肯定能够成功登陆。但是,如果我们输入一个错误的用户名或密码呢?很明显,肯定登入不了吧。
恩,正常情况下是如此,但是对于有SQL注入漏洞的网站来说,只要构造个特殊的“字符串”,照样能够成功登录。
比如:在用户名输入框中输入:' or 1=1#,密码随便输入,这时候的合成后的SQL查询语句为:
select * from users where username='' or 1=1#' and password=md5('')
语义分析:“#”在mysql中是注释符,这样井号后面的内容将被mysql视为注释内容,这样就不会去执行了,换句话说,以下的两句sql语句等价:
select * from users where username='' or 1=1#' and password=md5('')
select *from users where username='' or 1=1
因为1=1永远是都是成立的,即where子句总是为真,将该sql进一步简化之后,等价于如下select语句:
select * from users
3.防止SQL注入的方式:使用预备义语句和参数化查询,对于带有任何参数的Sql语句都会被发送到数据库服务器并被解析。
a.使用PDO(PHP DATA Objects)代码如下:
$stmt = $pdo->prepare('SELECT * FROM employees WHERE name = :name');
$stmt->execute(array(':name' => $name));
foreach ($stmt as $row) {
// do something with $row
}
b.使用mysqli代码如下
$stmt = $dbConnection->prepare('SELECT * FROM employees WHERE name = ?');
$stmt->bind_param('s', $name);
$stmt->execute()
$result = $stmt->get_result();
while ($row = $result->fetch_assoc()) {
// do something with $row
}
1 开启配置文件中的magic_quotes_gpc 和 magic_quotes_runtime设置
2 执行sql语句时使用addslashes进行sql语句转换
3 Sql语句书写尽量不要省略双引号和单引号。
4 过滤掉sql语句中的一些关键词:update、insert、delete、select、 * 。
5 提高数据库表和字段的命名技巧,对一些重要的字段根据程序的特点命名,取不易被猜到的。
6 Php配置文件中设置register_globals为off,关闭全局变量注册
7 控制错误信息,不要在浏览器上输出错误信息,将错误信息写到日志文件中。