韩顺平数据库陷阱编程 sql注入原理解释

70%以上的站点存在SQL  Injection漏洞,包括国内大部分安全站点。

sql注入:利用数据库的缺陷

/*
Navicat MySQL Data Transfer

Source Server         : localhost_3306
Source Server Version : 50516
Source Host           : localhost:3306
Source Database       : spdb

Target Server Type    : MYSQL
Target Server Version : 50516
File Encoding         : 65001

Date: 2012-08-01 10:29:35
*/

SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for `users`
-- ----------------------------
DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (
  `userid` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(64) NOT NULL,
  `password` varchar(64) NOT NULL,
  `email` varchar(64) CHARACTER SET utf8 NOT NULL,
  `job` varchar(64) CHARACTER SET utf8 NOT NULL,
  `sal` float NOT NULL DEFAULT '0',
  PRIMARY KEY (`userid`),
  UNIQUE KEY `username` (`username`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1;

-- ----------------------------
-- Records of users
-- ----------------------------
INSERT INTO `users` VALUES ('1', 'admin', '111111', 'admin@qq.com', '经理', '10000');
INSERT INTO `users` VALUES ('2', 'guest', '111111', 'guest@qq.com', '职员', '5000');

 

<html>
<head>
<title>用户验证</title>
<meta http-equiv="content-type" content="text/html;charset=utf-8"/>

</head>
<?php
//这里我们就可以编写php代码
//接收用户提交的用户名和密码
$username=$_REQUEST['username'];
$password=$_REQUEST['password'];
//echo $username,$password;
//现在我们看到数据库验证,要怎样写出安全的代码,防止用户攻击
//1 连接数据库
$conn=mysql_connect("localhost","root","root");
//die等价于exit() 退出

if(!$conn){
 die("连接数据库失败".mysql_error());
}
//2 选择数据库
mysql_selectdb("spdb",$conn) or die("连接数据库失败".mysql_error());

//3 编写sql语句,并查询
$sql="select  *  from users where username='$username'  AND  password='$password'";

$res=mysql_query($sql,$conn);

//4 查看结果
if(mysql_num_rows($res)!=0)
{
 //跳转到管理页面
 header("Location:ManageUsers.php");
}else{
 echo  "您的用户名和密码不对,<a href='Login.php'>返回</a>";
}
/*if($username=='admin'&&$password='111111'){
 //跳转到管理页面
 header("Location:ManageUsers.php");
}else{
 //提示
 echo  '您的用户名和密码不对';
}*/
?>
</html>

 

 

用万能密码

 

select  *  from users where username='admin '    AND  password='adfasf' or 1='1'

select  *  from users where username='admin1asdf '    AND  password='adfasf'' or 1='1'

 

输入da' or 1='1

绕过登录成功

 

用万能用户名

 

select  *  from users where username='admin1asdf '    union  select  * from users;/*  AND  password='adfasf''

 

万能用户名 注入失败

select * from users where username='fa' union select * from users; /*' ' AND password=''

( ! ) Warning: mysql_num_rows() expects parameter 1 to be resource, boolean given in F:\xampp\htdocs\phptest\LoginCl.php on line 31
Call Stack
#TimeMemoryFunctionLocation
10.0033339016{main}( )..\LoginCl.php:0
20.0121345472mysql_num_rows ( bool )..\LoginCl.php:31
您的用户名和密码不对, 返回

 

但是此句却能在数据库执行

select * from users where username='fa' union select * from users; /*' ' AND password=''

 

 

在用where语句中不用 ',万能密码失效

mysql中有一个特点:

会把这种语句认为是数字,会有另外一种 数字注入。

会把你的输入当成数字,输入字母会报错,仍然会被注入。

 

select *  from users where username=78 and  password=89  union select  *  from users

 

用户名输入数字:54

密码使用万能密码:89  union select  *  from users

 

照样可以注入。

 

万能用户名注入仍然存在问题:

 

select * from users where username=89 union select * from users;/* AND password=

数据库可以执行

界面无法绕过

 

 

如何解决注入问题?

————————————————————————————————————————————————————————————————————

1 服务器入手
magic_quotes_gpc  设置为on   有引号的万能用户名和万能密码失效,启用为on时,服务器就会对所有的'加入\转义。

高手仍然可以用 select  char(96) from dual  来代替单引号'

 

但是数字的注入还是无法解决。

综上所述 写成单引号要安全些。

display_errors  设置为off

 

2  对于程序员来说,不一定有权限来修改服务器的设置。

   我们现在使用第一种方案来防止登录用户注入

   a  密码比对

      首先通过用户输入的用户名,去查询数据库,如果查到了这个用户对应的密码。则和用户提交的密码比对,相同则说明该用户合法,反之则说明该用户非法。

$sql="select  *  from users where username='$username'";
$res=mysql_query($sql,$conn);
//取出密码
if($row=mysql_fetch_array($res)){
 //说明用户存在
 if($row[0]==$password){
  //该用户是合法的
  header("Location:ManageUsers.php");
 }else{
  echo "您输入的密码不正确,<a href='Login.php'>返回</a>";
 }
}else{
 //err
 echo "您的用户名和密码不对,<a href='Login.php'>返回</a>";
}

 

b  用pdo方式解决防范注入

  PDO  php data boject 相当于是一个数据库抽象层,不同的数据库使用相同的方法名,解决数据库连接不统一的问题。

使用pdo来解决注入

 first  在php.ini中启动pdo  extension=php_pdo_mysql.dll  前面的分号去掉

second   可以通过名字或者?号来绑定

 

//pdo 1  创建一个pdo对象
$sql="select  *  from  users where username=?  and  password=?";
$my_pdo=new PDO("mysql:host=localhost;port=3306;dbname=spdb", "root","root");

 

//pdo 2  设置编码  网页时utf-8  数据库是utf8
$my_pdo->exec("set  names  utf8");
//pdo 3  预处理sql
$pdoStatment=$my_pdo->prepare($sql);
//pdo 4  把接收到的用户名和密码填入
$pdoStatment->execute(array($username,$password));
//pdo 5  取出结果
$res=$pdoStatment->fetch();
if(empty($res)){
 echo "您的用户名和密码不对,<a href='Login.php'>返回</a>";
  
}else{
 header("Location:ManageUsers.php");
}

 

 

IDS 入侵检测系统

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值