绑定参数原理以及SQL注入..
假设我们的用户表中存在一行.用户名字段为username.值为aaa.密码字段为pwd.值为pwd..
下面我们来模拟一个用户登录的过程..
- <?php
- $username = "aaa";
- $pwd = "pwd";
- $sql = "SELECT * FROM table WHERE username = '{$username}' AND pwd = '{$pwd}'";
- echo $sql; //输出 SELECT * FROM table WHERE username = 'aaa' AND pwd = 'pwd'
- ?>
这样去执行这个sql语句.显然是可以查询出来东西的.返回用户的这一列.登录成功!!
然后我改一下..把密码改一下.随便一个值.如下.我改成了ppp.
- <?php
- $pwd = 'ppp';
- $sql = "SELECT * FROM table WHERE username = '{$username}' AND pwd = '{$pwd}'";
- echo $sql; //输出 SELECT * FROM table WHERE username = 'aaa' AND pwd = 'ppp'
- ?>
这样很显然.如果去执行这个SQL语句..是查询不到东西的.也就是密码错误.登录失败!!
但是有的人总是不老实的.他们会想尽一切办法来进行非法的登录.所谓非法就是在他不知道用户名密码的时候进行登录.并且登录成功..
那么他们所做的原理是什么呢??其实原理都是利用SQL语句..SQL语句强大的同时也给我们带来了不少麻烦..
我来举个最简单的例子.我们要运用到的SQL关键字是or
还是上面的代码.我们只要修改一下密码即可
- <?php
- $username = "aaa";
- $pwd = "fdsafda' or '1'='1"; //前面的密码是瞎填的..后来用or关键字..意思就是无所谓密码什么都执行
- $sql = "SELECT * FROM table WHERE username = '{$username}' AND pwd = '{$pwd}'";
- echo $sql; //输出 SELECT * FROM table WHERE username = 'aaa' AND pwd = 'fdsafda' or '1'='1'
- ?>
执行一下这个SQL语句..可怕的事情发生了..竟然可以查询到这一行数据..也就是登录成功了..
这是多么可怕的事情..
PHP为了解决这个问题.magic_quotes state..就是PHP会自动过滤传过来的GET.POST等等.
题外话.实践证明这个东西是畸形的..大部分程序不得不为判断此功能而耗费了很多代码..
在Java中可没有这个东西..那么Java中如何防止这种SQL注入呢??
Java的sql包中提供了一个名字叫PreparedStatement的类.
这个类就是我要说的绑定参数!
什么叫绑定参数??我继续给大家举例..(我用PHP举例)
- <?php
- $username = "aaa";
- $pwd = "pwd";
- $sql = "SELECT * FROM table WHERE username = ? AND pwd = ?";
- bindParam($sql, 1, $username, 'STRING'); //以字符串的形式.在第一个问号的地方绑定$username这个变量
- bindParam($sql, 2, $pwd, 'STRING'); //以字符串的形式.在第二个问号的地方绑定$pwd这个变量
- echo $sql;
- ?>
当然.到此.你肯定不知道会输出什么..更无法知道绑定参数有什么好处!这样做的优势是什么.更不知道bindParam这个函数到底做了什么.
下面我简单的写一下这个函数..只是一个模拟的过程..表达一个意思..代码幼稚还望包涵..
- <?php
- /**
- * 模拟简单的绑定参数过程
- *
- * @param string $sql SQL语句
- * @param int $location 问号位置
- * @param mixed $var 替换的变量
- * @param string $type 替换的类型
- */
- $times = 0;
- function bindParam(&$sql, $location, $var, $type) {
- global $times;
- //确定类型
- switch ($type) {
- //字符串
- default: //默认使用字符串类型
- case 'STRING' :
- $var = addslashes($var); //转义
- $var = "'".$var."'"; //加上单引号.SQL语句中字符串插入必须加单引号
- break;
- case 'INTEGER' :
- case 'INT' :
- $var = (int)$var; //强制转换成int
- //还可以增加更多类型..
- }
- //寻找问号的位置
- for ($i=1, $pos = 0; $i<= $location; $i++) {
- $pos = strpos($sql, '?', $pos+1);
- }
- //替换问号
- $sql = substr($sql, 0, $pos) . $var . substr($sql, $pos + 1);
- }
- ?>
注:由于得知道去除问号的次数..所以我用了一个global来解决.如果放到类中就非常容易了.弄个私有属性既可..我这只是个模拟..
通过上面的这个函数.我们知道了..绑定参数的防注入方式其实也是通过转义进行的..只不过是对于变量而言的..
我们来做一个实验
- <?php
- $times = 0;
- $username = "aaaa";
- $pwd = "123";
- $sql = "SELECT * FROM table WHERE username = ? AND pwd = ?";
- bindParam($sql, 1, $username, 'STRING'); //以字符串的形式.在第一个问号的地方绑定$username这个变量
- bindParam($sql, 2, $pwd, 'INT'); //以字符串的形式.在第二个问号的地方绑定$pwd这个变量
- echo $sql; //输出 SELECT * FROM table WHERE username = 'aaaa' AND pwd = 123
- ?>
可以看到.生成了非常正规的SQL语句.那么好.我们现在来试下刚才被注入的那种情况
- <?php
- $times = 0;
- $username = "aaa";
- $pwd = "fdsafda' or '1'='1";
- $sql = "SELECT * FROM table WHERE username = ? AND pwd = ?";
- bindParam($sql, 1, $username, 'STRING'); //以字符串的形式.在第一个问号的地方绑定$username这个变量
- bindParam($sql, 2, $pwd, 'STRING'); //以字符串的形式.在第二个问号的地方绑定$pwd这个变量
- echo $sql; //输出 SELECT * FROM table WHERE username = 'aaa' AND pwd = 'fdsafda\' or \'1\'=\'1'
- ?>
可以看到.pwd内部的注入已经被转义.当成一个完整的字符串了..这样的话.就不可能被注入了.
在PHP6中.PHP打算取消魔术过滤..而打规模的普及使用PDO..PDO中的bindParam()就如我上面描述的那样.已经在防注入中起到了关键作用.
所以为了迎接PHP6的到来.更为了使大家的程序严谨安全..强烈推荐大家使用PDO来做程序的DB类..( 可惜现在很少空间支持:( )
好了.我的废话就说到这里..希望大家对绑定参数已经有了一个比较有深度的理解:)
3 Comments to “ 绑定参数原理以及SQL注入.. ”
Post comment
分类目录
- ActionScript (2)
- CSS (25)
- Java (3)
- JavaScript (41)
- PHP (108)
- 心情杂谈 (34)
- 收集整理 (77)
- 本站原创 (58)
最近文章
- [演讲稿]OAuth1.0协议
- 在sae中利用SaeFetchurl进行豆瓣的OAuth授权
- OAuth 1.0a与1.0协议的改进…
- 深入理解OAuth与豆瓣OAuth test
- include_path+__autoload与数组+__autoload的比较
- 将google ssl设置为IE8的默认搜索引擎..
- 我们来做一个会呼吸的菜单吧!!
- 在编译php-fpm0.6的时候需要注意的一些问题
- 使用PHP将大文件导入到数据库中..
- 关于用PHP调用WebService中参数为complexType的问题
- 神奇的两次按位非运算符
- 百路推免费短网址服务..首创”收藏夹获取短网址”..
- 哥学社正式上线..
- jQuery中getJSON跨域原理详解
- Web辅助工具条(原名:河蟹工具条CrabBar)0.1发布
近期评论
- Gonten 在 在sae中利用SaeFetchurl进行豆瓣的OAuth授权 上的评论
- Amaranth 在 [演讲稿]OAuth1.0协议 上的评论
- 胖子 在 [演讲稿]OAuth1.0协议 上的评论
- 老飞的小窝 在 jQuery中getJSON跨域原理详解 上的评论
- Jackie.Hamos 在 将google ssl设置为IE8的默认搜索引擎.. 上的评论
- Elmer Zhang 在 在sae中利用SaeFetchurl进行豆瓣的OAuth授权 上的评论
- 茶叶蛋 在 一个PHP+AJAX留言板的完整例子.非常简单! 上的评论
- 9527 在 我们为什么要抛弃模板引擎?? 上的评论
- hikurasai 在 Flash TagCloud中文版. 上的评论
- lx 在 PHP上传进度条深度解析 上的评论
文章归档
- 2010 年九月 (1)
- 2010 年八月 (4)
- 2010 年七月 (3)
- 2010 年六月 (4)
- 2010 年五月 (2)
- 2010 年四月 (9)
- 2010 年三月 (12)
- 2010 年二月 (1)
- 2010 年一月 (3)
- 2009 年十二月 (2)
- 2009 年十一月 (3)
- 2009 年十月 (3)
- 2009 年九月 (5)
- 2009 年八月 (4)
- 2009 年七月 (6)
- 2009 年六月 (8)
- 2009 年五月 (8)
- 2009 年四月 (16)
- 2009 年三月 (19)
- 2009 年二月 (22)
- 2009 年一月 (20)
- 2008 年十二月 (38)
- 2008 年十一月 (22)
- 2008 年十月 (7)
- 2008 年九月 (3)
- 2008 年八月 (24)

Jessica

密码md5就没有问题了
现在框架也比较多了,而且主流都提供了比较安全的过滤方式
看完了…学习了…但觉得有点麻烦啊
推荐使用pdo