PrepareStatement防止sql注入漏洞分析
2016-12-29 14:05
513 查看
sql注入:就是通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令
危害:数据库信息泄露
*恶意字符:1 or 1=’1’等
案例:
控制台日志:
1–zhangsan–zhangsan–10–F
2–lisi–lisi–20–M
3–wangwu–wangwu–15–M
4–maliu–maliu–13–F
5–tianqi–tianqi–18–M
6–maba–maba–19–F
22–BBBB–BBBB–16–M
数据库记录:
结果:
sql语句没有查出我们想要的数据记录,而是将所有的表的记录都查询出来了,造成数据泄露(典型的sql注入漏洞)
分析:
select *from user where name=’zhangsan’ and ‘1’ or 1=’1’
语句分析:sql语句中and的优先级高于or的优先级,因此
select *from user where name=’zhangsan’ and ‘1’ or 1=’1’
等价于:
select *from user where (name=’zhangsan’ and ‘1’) or 1=’1’
因此name=’zhangsan’ and ‘1’ or 1=’1’的最终结果都是为真,where条件就失去作用,
整条sql的功能等价于:select *from user
优化后的sql语句:
select *from user where name=’zhangsan’ and (‘1’ or 1=’1’)
分析:
将恶意sql字符隔开,根据()的优先级大于and,因此整个sql语句的判断条件就变成name=’zhangsan’和(‘1’ or 1=’1’),而(‘1’ or 1=’1’)永久为真,因此整条语句就实现了对name的过滤作用,恶意sql则变得多余,但是这样的sql并没有实际的使用价值
sql注入的解决方案:
①:使用PrepareStatement类的set方法,它在sql预编译的时候对sql语句进行转义,
PrepareState过滤特定的字符将“干净”的二进制文件提交给数据库,因而就达不到欺骗数据库的效果
ps=ct.prepareStatement(“select *from user where name=?”);
ps.setString(1, “zhangsan and 1 or 1=’1’”);
rs=ps.executeQuery();
②:web项目中一般使用过滤器或者拦截器去过滤页面表单传过来的字符,自己拼接”干净”的sql语句再提交数据库执行
使用prepareStatement设置参数的效果:不能查询出有效数据,因此有效防止恶意sql的注入。
危害:数据库信息泄露
*恶意字符:1 or 1=’1’等
案例:
package com.zhiwei.database; import java.sql.*; public class PrepareStatementTest { public static void main(String[] args) { PreparedStatement ps =null; ResultSet rs=null; Connection ct=null; try { Class.forName("com.mysql.jdbc.Driver"); ct = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test","squirrel","xiaoyang"); ps=ct.prepareStatement("select *from user where name='zhangsan' and '1' or 1='1'"); rs=ps.executeQuery(); while(rs.next()){ int id =rs.getInt(1); String name = rs.getString(2); String passwd = rs.getString(3); int age=rs.getInt(4); String sex=rs.getString(5); System.out.println(id+"--"+name+"--"+passwd+"--"+age+"--"+sex); } } catch (Exception e) { e.printStackTrace(); } finally{ try { if(rs!=null){ rs.close(); }if(ps!=null){ ps.close(); }if(ct!=null){ ct.close(); } } catch (SQLException e) { e.printStackTrace(); } } } }
控制台日志:
1–zhangsan–zhangsan–10–F
2–lisi–lisi–20–M
3–wangwu–wangwu–15–M
4–maliu–maliu–13–F
5–tianqi–tianqi–18–M
6–maba–maba–19–F
22–BBBB–BBBB–16–M
数据库记录:
结果:
sql语句没有查出我们想要的数据记录,而是将所有的表的记录都查询出来了,造成数据泄露(典型的sql注入漏洞)
分析:
select *from user where name=’zhangsan’ and ‘1’ or 1=’1’
语句分析:sql语句中and的优先级高于or的优先级,因此
select *from user where name=’zhangsan’ and ‘1’ or 1=’1’
等价于:
select *from user where (name=’zhangsan’ and ‘1’) or 1=’1’
因此name=’zhangsan’ and ‘1’ or 1=’1’的最终结果都是为真,where条件就失去作用,
整条sql的功能等价于:select *from user
优化后的sql语句:
select *from user where name=’zhangsan’ and (‘1’ or 1=’1’)
分析:
将恶意sql字符隔开,根据()的优先级大于and,因此整个sql语句的判断条件就变成name=’zhangsan’和(‘1’ or 1=’1’),而(‘1’ or 1=’1’)永久为真,因此整条语句就实现了对name的过滤作用,恶意sql则变得多余,但是这样的sql并没有实际的使用价值
sql注入的解决方案:
①:使用PrepareStatement类的set方法,它在sql预编译的时候对sql语句进行转义,
PrepareState过滤特定的字符将“干净”的二进制文件提交给数据库,因而就达不到欺骗数据库的效果
ps=ct.prepareStatement(“select *from user where name=?”);
ps.setString(1, “zhangsan and 1 or 1=’1’”);
rs=ps.executeQuery();
②:web项目中一般使用过滤器或者拦截器去过滤页面表单传过来的字符,自己拼接”干净”的sql语句再提交数据库执行
使用prepareStatement设置参数的效果:不能查询出有效数据,因此有效防止恶意sql的注入。
相关文章推荐
- Android之获取手机上的图片和视频缩略图thumbnails
- 数据库链接字符串查询网站
- DB2实例管理
- DB2实例管理
- 保障MySQL数据安全的14个最佳方法
- mysql问答汇集
- Oracle用户被锁原因及办法
- 数据库的迁移救援
- mysql存储引擎MyISAM与InnoDB的优劣
- 第三章 数据库备份和还原
- 创建一个空的IBM DB2 ECO数据库的方法
- BBSXP漏洞再探究
- Access 2000 数据库 80 万记录通用快速分页类
- 开通一个数据库失败的原因的和解决办法
- 一个简单的asp数据库操作类
- 在线用表单建立文件夹
- Dedecms getip()的漏洞利用代码
- CentOS下DB2数据库安装过程详解
- Jquery 表单取值赋值的一些基本操作