网络安全系列 之 SQL注入学习总结
1. sql注入概述
程序里面如果使用了未经校验的外部输入来构造SQL语句,就很可能会引入SQL注入漏洞。
注入攻击
对于字符串输入,如果这个字符串将被解释为某种指令,那么需要特别注意防止注入攻击。sql注入、os命令注入、xml注入是典型的攻击类型。
2. sql注入测试工具
可以使用BurpSuite工具,浏览器上修改代理设置为burp工具配置的代理监听的IP端口。
对浏览器发送的请求进行拦截并修改其中参数,尝试注入攻击。
- sleep盲注: 返回时间>=5s,存在注入.
{"stationCodes":"AD02C7CCAB6F4BF9A85BC010AF16AC62')xor(sleep(5))and('","ptIds":"","pmYearDate":"2018","page":1,"pageSize":10} - 普通注入or /and : id="1' or '1'='1" id="1' or '1'='2"
- 报错注入: updatexml /extractvalue 、floor后group by。
- id=1 and updatexml(1,concat(0x7e,version(),0x7e),1) 返回version(),存在注入.
- id=1 and extractvalue(1,concat(0x7e,version()) 返回version(),存在注入.
- id=1 and (select 1 from (select count(),concat(version(),floor(rand(0)2))x from information_schema.tables group by x)a)
返回version(),存在注入.
3. sql注入防御方法
3.1 问题来源
- 执行外部数拼接的SQL语句。
- 执行外部传入的整条SQL语句
- 在配置文件中的SQL语句没有使用预编译方式占位符。
- 校验函数有缺陷或占位符使用错误。
3.2 防御方法
使用参数化语句
sql语句预编译绑定变量,不直接拼接。输入校验
采用白名单或黑名单方式对入参进行检查。
备注:ESAPI(Enterprise Security API)也提供了输入验证类 org.owasp.esapi.reference.DefaultValidator的实现。输出编码
在sql注入语境中,将发送给数据库的内容进行编码(或转义)是必需的操作,可以保证内容被正确的处理。
针对Mysql的编码举例:在动态sql中提交的信息(LIKE语句中使用通配符的位置)添加引用。
sql = sql.replace("%",“\%”); //%匹配0个或多个任意字符
sql = sql.replace("_",“\_”); //_匹配任意一个字符
备注:在动态sql和拼接sql场景下也可以利用ESAPI进行转义处理
// ESAPI转义,防SQL注入
public static String encodeForSql(String input) {
MySQLCodec mysqlCodec = new MySQLCodec(MySQLCodec.Mode.STANDARD);
return ESAPI.encoder().encodeForSQL(mysqlCodec, input);
}
// 说明: esapi需要有两个配置文件:ESAPI.properties、validation.properties
小结:输入校验和输出编码是处理注入问题(如xss)的一贯套路。
4. SQL注入防御举例
4.1 使用JDBC时,SQL语句进行了拼接
1. 使用statement的executeQuery、execute、executeUpdate等函数时,传入的SQL语句拼接了来自外部的不可信参数。
**错误示例**
String userName = ctx.getAuthenticatedUserName(); //this is a constant
//itemName是外部读入的参数拼接到SQL语句
String sqlString = "SELECT * FROM t_item WHERE owner='" + userName + "' AND itemName='" + request.getParameter("itemName") + "'";
stmt = connection.createStatement();
rs = stmt.executeQuery(sqlString);
解决方法 1) 使用预编译方式(不可信数据作为字段值); 2) 对拼接到SQL语句中的外部参数进行白名单校验(不可信数据作为表名,字段名,排序方式)。
**正确示例**:使用白名单校验方式校验itemName
String userName = ctx.getAuthenticatedUserName(); //this is a constant
String itemName=getCleanedItemName(request.getParameter("itemName"));
String sqlString = "SELECT * FROM t_item WHERE owner='" + userName + "' AND itemName='" + itemName + "'";
stmt = connection.createStatement();
rs = stmt.executeQuery(sqlString);
2. 使用connection的PreparedStatement时,使用的SQL语句拼接了来自外部的不可信参数。
**错误示例**
String userName = ctx.getAuthenticatedUserName(); //this is a constant
//itemName是外部读入的参数拼接到SQL语句
String itemName = request.getParameter("itemName");
// ...Ensure that the length of userName and itemName is legitimate
// ...
String sqlString = "SELECT * FROM t_item WHERE owner=? AND itemName='"+itemName+"'";
PreparedStatement stmt = connection.prepareStatement(sqlString);
stmt.setString(1, userName);
rs = stmt.executeQuery();
解决方法 1) 将拼接方式改为占位符方式; 2). 对拼接到SQL语句中的外部参数进行白名单校验。
**正确示例**:所有的参数使用占位符
String userName = ctx.getAuthenticatedUserName(); //this is a constant
String itemName = request.getParameter("itemName");
// ...Ensure that the length of userName and itemName is legitimate
// ...
String sqlString = "SELECT * FROM t_item WHERE owner=? AND itemName=?";
PreparedStatement stmt = connection.prepareStatement(sqlString);
stmt.setString(1, userName); // jdbc编号从1开始
stmt.setString(2, itemName);
rs = stmt.executeQuery();
3. 存储过程使用动态方式构建SQL语句,导致SQL注入风险。
**错误示例**
REATE PROCEDURE sp_queryItem
@userName varchar(50),
@itemName varchar(50)
AS
BEGIN
DECLARE @sql nvarchar(500);
SET @sql = 'SELECT * FROM t_item
WHERE owner = ''' + @userName + '''
AND itemName = ''' + @itemName + '''';
EXEC(@sql);
END
GO
解决方法 采用参数化查询的方式
**正确示例**:采用参数化查询的方式
CREATE PROCEDURE sp_queryItem
@userName varchar(50),
@itemName varchar(50)
AS
BEGIN
SELECT * FROM t_item
WHERE userName = @userName
AND itemName = @itemName;
END
GO
4.2 使用Hibernate时,调用API时,传入的SQL语句有拼接外部参数
1. 调用createQuery时,传入的SQL语句拼接了来自外部的不可信参数。
**错误示例**
//SQL语句拼接不可信参数
String itemName = request.getParameter("itemName");
Query hqlQuery = session.createQuery("from Item as item where item.itemName = '" + itemName + "'");
List<Item> hrs = (List<Item>) hqlQuery.list();
解决方法 1) 对拼接到SQL语句中的外部参数进行白名单校验; 2) 使用hibernate的配置映射关系方式。
**正确示例**:对外部参数进行白名单校验
String itemName = request.getParameter("itemName");
itemName=getCleanedItemName(itemName);//白名单校验
Query hqlQuery = session.createQuery("from Item as item where item.itemName = '" + itemName + "'");
List<Item> hrs = (List<Item>) hqlQuery.list();
4.3 使用MyBatis时,SQL语句使用$占位符
1. 配置文件使用$占位符
错误示例:
// 使用$,底层将使用简单拼接
<select id="getItems" resultClass="Item">
SELECT * FROM t_item WHERE owner = $userName$ AND itemName = $itemName$
</select>
解决方法 1) 将$占位符改为#占位符; 2) 如果外部不可信数据作为表名,字段名,排序方式,则对外部参数进行白名单校验。
**正确示例**:使用#占位符方式
<select id="getItems" resultClass="Item">
SELECT * FROM t_item WHERE owner = #userName# AND itemName =#itemName#
</select>
2. mybatis接口中的函数标签的SQL语句,使用了$占位符
**错误示例**
public interface IUserDAO {
//标注中的SQL语句通过$表示占位符,内部实现是单纯的拼接
@Select("select *from User where id=${id})
User getUser(@Param("id")String id);
}
**正确示例**:标注中的SQL语句通过'#'表示占位符,内部实现是参数化预处理
public interface IUserDAO {
@Select("select *from User where id=#{id})
User getUser(@Param("id")String id);
}
end.
2018.03.31
网络安全系列 之 SQL注入学习总结的更多相关文章
- SQL注入学习资料总结
转载自:https://bbs.ichunqiu.com/thread-12105-1-1.html 什么是SQL注入 SQL注入基本介绍 结构化查询语言(Structured Query Lang ...
- sql注入学习笔记,什么是sql注入,如何预防sql注入,如何寻找sql注入漏洞,如何注入sql攻击 (原)
(整篇文章废话很多,但其实是为了新手能更好的了解这个sql注入是什么,需要学习的是文章最后关于如何预防sql注入) (整篇文章废话很多,但其实是为了新手能更好的了解这个sql注入是什么,需要学习的是文 ...
- SQL学习之SQL注入学习总结
所谓SQL注入,就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令. 测试数据库 我们本文就以如下数据库作为测试数据库,完成我们的注入分析 ...
- sql注入学习笔记 详解篇
sql注入的原理以及怎么预防sql注入(请参考上一篇文章) https://www.cnblogs.com/KHZ521/p/12128364.html (本章主要针对MySQL数据库进行注入) sq ...
- SQL注入学习-Dnslog盲注
1.基础知识 1.DNS DNS(Domain Name System,域名系统),因特网上作为域名和IP地址相互映射的一个分布式数据库,能够使用户更方便的访问互联网,而不用去记住能够被机器直接读取的 ...
- 从零开始的sql注入学习(挖坑不填)
首先,本人是小白,这篇文章也只是总结了一下大佬们的sql注入方法,要是有错,请各位大佬指出,以便学习. 虽然我是菜鸡,但是太过基础的sql注入问题也就不再重复的解释了.直接从常用的说起. 实战中常用的 ...
- 简单sql注入学习
sql注入是什么? 所谓SQL注入,就是通过把SQL命令插入到Web表单提 交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令.具体来说,它是利用现有应用程序,将(恶意)的SQ ...
- SQL注入学习(一)
注入攻击的本质:web应用程序没有过滤用户输入或过滤不严谨,直接把用户输入的恶意数据当做代码执行 两个条件: 1.用户能够控制输入 2.原本程序要执行的代码,拼接了用户输入的数据 注入类型 SQL注入 ...
- Java SQL注入学习笔记
1 简介 文章主要内容包括: Java 持久层技术/框架简单介绍 不同场景/框架下易导致 SQL 注入的写法 如何避免和修复 SQL 注入 2 JDBC 介绍 JDBC: 全称 Java Databa ...
随机推荐
- 用Cygwin实现在window环境下使用Linux命令-nohup 来后台运行程序
1.安装Cygwin 下载 cygdrive-选择64或32位 http://www.cygwin.com/ 注:可以百度搜索安装步骤 2.配置它的环境变量 添加到path路径中 3.cmd 执 ...
- C/C++各个周期的学习
C/C++ 程序的生命周期 编写时: 要点:业务,数据结构,控制解耦:健壮:易修改:清晰简单无歧义:易重用:低耦合高内聚:易链接:速度快(时间复杂度,空间复杂度,cache友好): 书籍:<c+ ...
- NX二次开发-UFUN添加工程图投影视图UF_DRAW_add_orthographic_view
NX9+VS2012 #include <uf.h> #include <uf_draw.h> #include <uf_obj.h> #include <u ...
- 牛客多校第十场 B Coffee Chicken 递归
题意: 给你一个“斐波那契”字符串数列,第n项由第n-1项和第n-2项拼接而成,输出某项的某位及其后10位. 题解: 递归求解即可. #include<bits/stdc++.h> usi ...
- Centos 6 & Centos 7安装rabbitmq3.6.15(单节点)
系统准备 安装 erlang 语言环境 安装rabbitmq 配置网页插件 配置访问账号密码和权限 系统准备 centos6.5 与 centos7 都可以 ###安装依赖文件 yum -y inst ...
- Python 数据结构_队列
目录 目录 队列 队列 Queue 队列是一种先进先出(FIFO)的数据类型, 新的元素通过 入队 的方式添加进 Queue 的末尾, 出队 就是从 Queue 的头部删除元素. 用列表来做 Queu ...
- 删除csdn自己上传的资源
原文地址:http://www.xuebuyuan.com/1875216.html 昨天晚上进行测试,上传了一个压缩包和大家分享,测试完成后,为了不想给被测试的公司造成伤害,决定把上传的包删除,结果 ...
- Adobe Fireworks CS6 win64的安装
网页三大剑客之一 FW的安装 本人也是找了半天才找到的. (没有视频)这里先感谢原帖给我的链接https://blog.csdn.net/qq_38053395/article/details/ ...
- 【收集+】DDR5 vs DDR4
Advantages of Migrating to DDR5 DDR5 is the next evolution in DRAM, bringing a robust list of new fe ...
- 使用navicat 使用IP、用户名、密码直接连接linux服务器里面的数据库
一般新申请的服务器,没有开通3306端口的吧,反正我遇到的,要用Navicat去连接linux下的数据库,都必须填写两个地方的信息,才能链接成功. 如果想要只通过填写ip还有数据库用户名还有密码就可以 ...