Java开发工程师(Web方向) - 03.数据库开发 - 第3章.SQL注入与防范
第3章--SQL注入与防范
SQL注入与防范
经常遇到的问题:数据安全问题,尤其是sql注入导致的数据库的安全漏洞
国内著名漏洞曝光平台:WooYun.org
数据库泄露的风险:用户信息、交易信息的泄露等
什么是SQL数据库注入?
Web应用下,终端用户是无法直接访问数据库的,他们必须通过发送http请求到Java服务器,由Java服务器访问后端数据库。因此,恶意用户想要获取数据库中的数据,必须通过Java服务器来访问后端数据库而无法绕行。他们的唯一途径就是利用应用程序的漏洞,伪装自己的请求,欺骗业务程序,达到访问数据库的目的。
之前学习的代码:用户登录场景
User user = null;
String sql = "select * from user where userName = '" + userName
+ "' and password = '" + password + "'";
rs = stmt.executeQuery(sql);
while(rs.next()) {
user = new User();
user.setUserName(rs.getString("userName"));
user.setCardNum(rs.getString("cardNum"));
}
return user;
Java应用程序接收到用户的输入后,检索后端数据库,匹配数据库记录。
如果:
用户输入为ZhangSan’;-- 密码随便输入(因为不知道真实密码)
也会登陆成功,为什么呢?
select * from user where userName = 'ZhangSan'; -- 'and password='111';
密码条件被注释
总结:数据库注入就是用户在输入部分输入SQL命令,破坏原有SQL的语义,以达到欺骗服务器并发送恶意SQL的业务程序的漏洞。
原因:SQL语句为动态拼接的,语义未知。
解决方案:除了动态拼接,还有什么办法能使用web传入的参数呢?
参数化sql的实现:1. 确定sql的语义;2. 传入参数
利用Connection对象的.preparedStatement(sql)方法;
preparedStatement()相对于Statement的最大优点:提供了参数化sql的实现(格式化的sql)
select * from user where userName = ? and password = ?
?为占位符,替代了一个参数。sql的语义确定了。
根据参数的类型:.setInt(); .setString(); .setBoolean(); 来替代参数化sql中的占位符。
除了使用PreparedStatement,我们还应该有一些其他的注意事项:
1. 执行严格的数据库权限管理
仅给予Web应用访问数据库的最小权限
严格禁止Drop table等权限
2. 封装数据库错误:不能将数据库异常直接暴露给用户(因为数据库异常通常包含了大量的数据库信息)
禁止直接将后端数据库异常信息暴露给用户
对后端异常信息进行必要的封装,避免用户直接查看到后端异常
3. 机密信息禁止明文存储
涉密信息需要加密处理
针对MySQL,可使用AES_ENCRYPT/AES_DECRYPT进行加密和解密
课堂交流区:
其他的SQL注入场景:可以使用 "or 1"
i.e. select name from student where name = '' or 1; -- '';
会返回所有
SQL注入与防范单元测试
以下哪项描述是正确的?
- A.PreparedStatement可以实现参数化SQL,防止SQL注入的风险。13.33/40.00
- B.SQL注入的本质是因为外部用户恶意改变了原有程序的执行语义,导致数据泄露。13.33/40.00
- C.SQL注入可以导致外部用户获取整个数据库的信息。13.33/40.00
- D.使用PreparedStatement,如果用户使用SQL注释符,也可能会改变SQL的语义执行。
SQL 注入是由于应用程序动态拼接SQL,用户利用该漏洞,注入特殊SQL语句,导致应用程序执行恶意SQL命令的现象。
- A.√10.00/10.00
- B.×
Statement接口可以实现参数化SQL,防止动态拼接SQL导致的SQL注入漏洞。
- A.×10.00/10.00
- B.√
应谨慎给予用户Delete权限,防止用户数据被恶意删除。
- A.×
- B.√10.00/10.00
SQL注入漏洞是由于数据库密码泄露,导致用户登陆到数据库上执行了恶意操作。
- A.√
- B.×10.00/10.00
PreparedStatement需要设置格式化SQL语句,格式化SQL语句就是将SQL的参数使用占位符替代的SQL语句。
- A.×
- B.√10.00/10.00
应用程序需要捕获SQL异常,将异常信息展现给用户,方便用户处理。
- A.√
- B.×10.00/10.00
SQL注入与防范单元作业
请完成SQL注入与防范的编程题目。
有一张学生表
| id | name | number |
| 1 | XiaoMing | 100 |
| 2 | XiaoLi | 101 |
| 3 | XiaoZhao | 102 |
现在需要根据学生名称获取学生的期末考试分数。
public static void getStudent(String name) throws ClassNotFoundException {
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
Class.forName(JDBC_DRIVER);
conn = DriverManager.getConnection(DB_URL, USER, PASS);
stmt = conn.createStatement();
rs = stmt.executeQuery("select name,score from student where name =' " + name +"'");
while (rs.next()) {
System.out.println(rs.getString("name") + ":" + rs.getInt("score"));
}
} catch (SQLException e) {
// ignore
} finally {
if (rs != null) {
try {
rs.close();
} catch (Exception e) {
// ignore
}
}
if (stmt != null) {
try {
stmt.close();
} catch (Exception e) {
// ignore
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
// ignore
}
}
}
}
1. 请指出上面这段程序存在什么安全风险?并给出具体的测试用例。
2. 请重新编写应用程序,解决上述风险。
答:
安全风险:上述程序使用Statement对象,有SQL注入的风险。
程序错误:
1. stmt.executeQuery(sql)中的sql语句有误,多了一个空格导致
"select name,number from student where name =' XiaoZhao'" 返回的为empty set
2. 数据库中columns分别为id, name和number,而程序中select语句包含的attributes为name和number
SQL注入测试用例:
getStudent("' or 1;#");

解决SQL注入、修改错误后的代码:
import java.sql.Connection;
import java.sql.DriverManager;
//import java.sql.Statement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException; public class Assignment { static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
static final String DB_URL = "jdbc:mysql://localhost/helloworld";
static final String USER = "matt";
static final String PASS = "matt"; public static void getStudent(String name) throws ClassNotFoundException {
Connection conn = null;
// Statement stmt = null;
PreparedStatement ptmt = null;
ResultSet rs = null;
try {
Class.forName(JDBC_DRIVER);
conn = DriverManager.getConnection(DB_URL, USER, PASS);
// stmt = conn.createStatement();
String sql = "select name,number from student where name = ?";
ptmt = conn.prepareStatement(sql);
ptmt.setString(1, name);
// rs = stmt.executeQuery("select name,number from student where name =' " + name +"'");
rs = ptmt.executeQuery();
while (rs.next()) {
System.out.println(rs.getString("name") + ":" + rs.getInt("number"));
}
} catch (SQLException e) {
// ignore
} finally {
if (rs != null) {
try {
rs.close();
} catch (Exception e) {
// ignore
}
}
// if (stmt != null) {
if (ptmt != null) {
try {
// stmt.close();
ptmt.close();
} catch (Exception e) {
// ignore
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
// ignore
}
}
}
} public static void main (String[] args) throws ClassNotFoundException {
getStudent("XiaoZhao");
getStudent("' or 1;#");
}
}
Java开发工程师(Web方向) - 03.数据库开发 - 第3章.SQL注入与防范的更多相关文章
- Java开发工程师(Web方向) - 03.数据库开发 - 第1章.JDBC
第1章--JDBC JDBC基础 通过Java Database Connectivity可以实现Java程序对后端数据库的访问 一个完整的数据库部署架构,通常是由客户端和服务器端两部分组成 客户端封 ...
- Java开发工程师(Web方向) - 03.数据库开发 - 第5章.MyBatis
第5章--MyBatis MyBatis入门 Abstract: 数据库框架的工作原理和使用方法(以MyBatis为例) 面向对象的世界与关系型数据库的鸿沟: 面向对象世界中的数据是对象: 关系型数据 ...
- Java开发工程师(Web方向) - 03.数据库开发 - 第4章.事务
第4章--事务 事务原理与开发 事务Transaction: 什么是事务? 事务是并发控制的基本单位,指作为单个逻辑工作单元执行的一系列操作,且逻辑工作单元需满足ACID特性. i.e. 银行转账:开 ...
- Java开发工程师(Web方向) - 03.数据库开发 - 第2章.数据库连接池
第2章--数据库连接池 数据库连接池 一般而言,在实际开发中,往往不是直接使用JDBC访问后端数据库,而是使用数据库连接池的机制去管理数据库连接,来实现对后端数据库的访问. 建立Java应用程序到后端 ...
- Java开发工程师(Web方向) - 03.数据库开发 - 期末考试
期末考试 编程题 本编程题包含4个小题,覆盖知识点从基础的JDBC.连接池到MyBatis. 1(10分) 有一款在线教育产品“天天向上”主要实现了在手机上查看课程表的功能.该产品的后端系统有一张保存 ...
- Java开发工程师(Web方向) - 04.Spring框架 - 第2章.IoC容器
第2章.IoC容器 IoC容器概述 abstract: 介绍IoC和bean的用处和使用 IoC容器处于整个Spring框架中比较核心的位置:Core Container: Beans, Core, ...
- Java开发工程师(Web方向) - 04.Spring框架 - 第1章.Spring概述
第1章.Spring概述 Spring概述 The Spring Framework is a lightweight solution and a potential one-stop-shop f ...
- Java开发工程师(Web方向) - 02.Servlet技术 - 第3章.Servlet应用
第3章.Servlet应用 转发与重定向 转发:浏览器发送资源请求到ServletA后,ServletA传递请求给ServletB,ServletB生成响应后返回给浏览器. 请求转发:forward: ...
- Java开发工程师(Web方向) - 02.Servlet技术 - 第2章.Cookie与Session
第2章--Cookie与Session Cookie与Session 浏览器输入地址--HTTP请求--Servlet--HTTP响应--浏览器接收 会话(session):打开浏览器,打开一系列页面 ...
随机推荐
- ARM Cortex-A53 Cache与内存的映射关系以及Cache的一致性分析
ARM Cortex-A53 Cache与内存的映射关系以及Cache的一致性分析 题记:如果文章有理解不对的地方,欢迎大家批评指正,谢谢大家. 摘要:本文以Cortex-A53为例,首先分析Cach ...
- 时钟晶振32.768KHz为什么是15分频?
实时时钟晶振为什么选择是32768Hz的晶振,在百度上搜索的话大部分的答案都是说2的15次方是32768,使用这个频率的晶振,人们可以很容易的通过分频电路得到1Hz的计时脉冲.但是话有说回来了,2的整 ...
- IE下页面左偏移并页头空出一行解决方法
在其它浏览器下显示正常,包括360浏览器,在IE下,页面向左偏移,通过firebug查看,head标签为空,并且head标签里面的内容都跑到body标签内了,原因是有bom头,访问的页面或是加载,包含 ...
- SpringBoot自动装配的原理
1.SpringApplication.run(AppConfig.class,args);执行流程中有refreshContext(context);这句话. 2.refreshContext(co ...
- MySQL 开启事件 使用定时器调用存储过程
mysql定时器是系统给提供了event,而oracle里面的定时器是系统给提供的job.废话少说,下面创建表:create table mytable (id int auto_incremen ...
- 【读书笔记 - Effective Java】04. 通过私有构造器强化不可实例化的能力
工具类(utility class)不希望被实例化,比如只包含静态方法和静态域的类.为了这个目的,需要让这个类包含一个私有构造器. // 私有构造器示例 public class UtilityCla ...
- 基于Geomesa服务查询轨迹数据无法根据空间和时间范围进行结果查询
一.Geomesa - QuickStart(教程工程包) 百度网盘下载地址:geomesa-tutorials-master.7z 二.解压后,IDEA编译如下 百度网盘下载地址:IDEA201 ...
- 如何将24位RGB颜色转换16位RGB颜色
有许多朋友第一次使用16位彩色显示屏会遇到如何将24位RGB颜色转换为对应的16位RGB颜色的问题, 通过查阅相关资料,就写一下其中的转换原理吧,希望对大家会有所帮助. 我们知道24位RGB是分别由8 ...
- Python的scrapy之爬取链家网房价信息并保存到本地
因为有在北京租房的打算,于是上网浏览了一下链家网站的房价,想将他们爬取下来,并保存到本地. 先看链家网的源码..房价信息 都保存在 ul 下的li 里面 爬虫结构: 其中封装了一个数据库处理模 ...
- python学习笔记:第4天 列表和元组
目录 基本数据类型:列表 基本数据类型:元组 补充知识 基本数据类型:列表 1. 列表的介绍 列表也是python的基础的数据类型之一,类似于Java中的数组一样,可以存放很多元素.列表是用括号括起来 ...