重新学习MySQL数据库11:以Java的视角来聊聊SQL注入

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: 以Java的视角来聊聊SQL注入 转自  javatiku Java面试那些事儿 2017-08-09 在大二就接触过sql注入,之前一直在学习windows逆向技术,认为web安全以后不是自己的从业方向,所以当时也就没有深入研究。

以Java的视角来聊聊SQL注入

转自  javatiku  Java面试那些事儿  2017-08-09

在大二就接触过sql注入,之前一直在学习windows逆向技术,认为web安全以后不是自己的从业方向,所以当时也就没有深入研究。工作多年来,本人也一直从事安全开发相关工作,随着Java的市场份额越来越重,在工作中接触Java的机会也越来越多,也是机缘巧合的契机,自己开始走向了偏 Java开发的道路。最近工作中接触到一个项目,其代码风格极其不堪入目,更严重的是DAO部分存在大量SQL注入的隐患,所以趁这个机会,作者复习研究了一把SQL注入相关的知识,在这里与大家探讨一下。

0

什么是SQL注入

SQL注入是影响企业运营最具有破坏性的漏洞之一。

应用程序向后台数据库进行SQL查询时,如果为攻击者提供了影响该查询的能力,就会引起SQL注入。


1

靶场准备

首先我们来准备一个web接口服务,该服务可以提供管理员的信息查询,这里我们采用springboot + jersey 来构建web服务框架,数据库则采用最常用的mysql。下面,我们来准备测试环境,首先建立一张用户表jwtk_admin,SQL如下:

然后插入默认的管理员:

这样我们就有了两位系统内置管理员了,管理员密码采用MD5进行Hash,当然这是一个很简单的为了作为研究靶场的表,所以没有很全的字段。


接下来,我们创建 spring boot + jersey 构建的RESTFul web服务,这里我们提供了一个通过管理员用户名查询管理员具体信息的接口,如下:


2

SQL注入测试

首先我们以开发者正向思维向web服务发送管理员查询请求,这里我们用PostMan工具发送一个GET请求,请求与结果如下图所示:

不出我们和开发者所料,Web接口返回了我们想要的结果,用户名为admin的管理员信息。OK,现在开发任务完成,Git Push,Jira任务点为待测试,那么这样的接口就真的没有问题了吗?现在我们发送这样一条GET请求:

发送该请求后,我们发现PostMan没有接收到返回结果,而Web服务后台却开始抛MySQLSyntaxErrorException异常了,错误如下:


You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''xxxx''' at line 1


原因是在我们查询的 xxxx' 处sql语句语法不正确导致。这里我们先不讨论SQL语法问题,我们继续实验,再次构造一条GET查询请求:

此时,我们可以惊讶的发现,查询接口非但没有报错,反而将我们数据库jwti_admin表中的所有管理员信息都查询出来了:

这是什么鬼,难道管理员表中还有 name=xxxx'or'a'='a 的用户?这就是 SQL Injection


3

注入原理分析

在接口中接受了一个String类型的name参数,并且通过字符串拼接的方式构建了查询语句。在正常情况下,用户会传入合法的name进行查询,但是黑客却会传入精心构造的参数,只要参数通过字符串拼接后依然是一句合法的SQL查询,此时SQL注入就发生了。正如我们上文输入的name=xxxx'or'a'='a与我们接口中的查询语句进行拼接后构成如下SQL语句:


当接口执行此句SQL后,系统后台也就相当于拱手送给黑客了,黑客一看到管理员密码这个hash,都不用去cmd5查了,直接就用123456密码去登录你的后台系统了。Why?因为123456的md5哈希太常见了,别笑,这就是很多中小网站的现实,弱口令横行,不见棺材不落泪!


好了,现在我们应该明白了,SQL Injection原因就是由于传入的参数与系统的SQL拼接成了合法的SQL而导致的,而其本质还是将用户输入的数据当做了代码执行。在系统中只要有一个SQL注入点被黑客发现,那么黑客基本上可以执行任意想执行的SQL语句了,例如添加一个管理员,查询所有表,甚至“脱裤” 等等,当然本文不是讲解SQL注入技巧的文章,这里我们只探讨SQL注入发生的原因与防范方法。


4

JDBC的预处理

在上文的接口中,DAO使用了比较基础的JDBC的方式进行数据库操作,直接使JDBC构建DAO在比较老的系统中还是很常见的,但这并不意味着使用JDBC就一定不安全,如果我将传入的参数  xxxx'or'a'='a 整体作为参数进行name查询,那就不会产生SQL注入。在JDBC中,提供了 PreparedStatement (预处理执行语句)的方式,可以对SQL语句进行查询参数化,使用预处理后的代码如下:

同样,我们使用上文的注入方式注入 ,此时我们发现,SQL注入没能成功。现在,我们来打印一下被被预处理后的SQL,看看有什么变化:

看到了吗?所有的   都被 \' 转义掉了,从而可以确保SQL的查询参数就是参数,不会被恶意执行,从而防止了SQL注入。


5

Mybatis下注入防范

MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的持久层框架, 其几乎避免了所有的 JDBC 代码和手动设置参数以及获取结果集。同时,MyBatis 可以对配置和原生Map使用简单的 XML 或注解,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录,因此mybatis现在在市场中采用率也非常高。这里我们定义如下一个mapper,来实现通过用户名查询管理员的接口:

同样提供Web访问接口:

接下来,我们尝试SQL注入name字段,可以发现注入并没有成功,通过打印mybatis的Log可以看到mybatis框架对参数进行了预处理处理,从而防止了注入:

那是否只要使用了mybatis就一定可以避免SQL注入的危险?我们把mapper做如下修改,将参数#{name}修改为${name},并使用name='xxxx' or 'a'='a' 作为GET请求的参数,可以发现SQL注入还是发生了:

那这是为什么,mybatis ${}#{}的差别在哪里?

原来在mybatis中如果以${}形式声明为SQL传递参数,mybatis将不会进行参数预处理,会直接动态拼接SQL语句,此时就会存在被注入的风险,所以在使用mybatis作为持久框架时应尽量避免采用${}的形式进行参数传递,如果无法避免(有些SQL如likeinorder by等,程序员可能依旧会选择${}的方式传参),那就需要对传入参数自行进行转义过滤。

6

JPA注入防范

JPA是Sun公司用来整合ORM技术,实现天下归一的ORM标准而定义的Java Persistence API(java持久层API),JPA只是一套接口,目前引入JPA的项目都会采用Hibernate作为其具体实现,随着无配置Spring Boot框架的流行,JPA越来越具有作为持久化首选的技术,因为其能让程序员写更少的代码,就能完成现有的功能,例如强大的JpaRepository,常规的SQL查询只需按照命名规则定义接口,便可以不写SQL(JPQL/SQL)就可以实现数据的查询操作,从SQL注入防范的角度来说,这种将安全责任抛给框架远比依靠程序员自身控制来的保险。因此如果项目使用JPA作为数据访问层,基本上可以很大程度的消除SQL注入的风险。但是话不能说的太死,在我见过的一个Spring Boot项目中,虽然采用了JPA作为持久框架,但是有一位老程序员不熟悉于使用JPQL来构建查询接口,依旧使用字符串拼接的方式来实现业务,而为项目安全埋下了隐患。

安全需要一丝不苟,安全是100 - 1 = 0的业务,即使你防御了99%的攻击,那还不算胜利,只要有一次被入侵了,那就有可能给公司带来很严重的后果

关于JPA的SQL注入,我们就不详细讨论了,因为框架下的注入漏洞属于框架漏洞范畴(如CVE-2016-6652),程序员只要遵循JPA的开发规范,就无需担心注入问题,框架都为你做好幕后工作了。


7

SQL注入的其他防范办法

很多公司都会存在老系统中有大量SQL注入风险代码的问题,但是由于其已稳定支持公司业务很久,不宜采用大面积代码更新的方式来消除注入隐患,所以需要考虑其采用他方式来防范SQL注入。除了在在SQL执行方式上防范SQL注入,很多时候还可以通过架构上,或者通过其他过滤方式来达到防止SQL注入的效果。

  • 一切输入都是不安全的:对于接口的调用参数,要进行格式匹配,例如admin的通过name查询的接口,与之匹配的Path应该使用正则匹配(因为用户名中不应该存在特殊字符),从而确保传入参数是程序控制范围之内的参数,即只接受已知的良好输入值,拒绝不良输入。注意:验证参数应将它与输出编码技术结合使用。

  • 利用分层设计来避免危险:前端尽量静态化,尽量少的暴露可以访问到DAO层的接口到公网环境中,如果现有项目,很难修改存在注入的代码,可以考虑在web服务之前增加WAF进行流量过滤,当然代码上就不给hacker留有攻击的漏洞才最好的方案。也可以在拥有nginx的架构下,采用OpenRestry做流量过滤,将一些特殊字符进行转义处理。

  • 尽量使用预编译SQL语句:由于动态SQL语句是引发SQL注入的根源。应使用预编译语句来组装SQL查询。

  • 规范化:将输入安装规定编码解码后再进行输入参数过滤和输出编码处理;拒绝一切非规范格式的编码。


小结 

其实随着ORM技术的发展,Java web开发在大趋势上已经越来越远离SQL注入的问题了,而有着Entity Framework框架支持的ASP.NET MVC从来都是高冷范。在现在互联网中,使用PHP和Python构建的web应用是目前SQL注入的重灾区。本文虽然是从JAVA的角度来研究SQL注入的问题,但原理上同样适用于其他开发语言,希望读者可以通过此文,触类旁通。

微信公众号【黄小斜】大厂程序员,互联网行业新知,终身学习践行者。关注后回复「Java」、「Python」、「C++」、「大数据」、「机器学习」、「算法」、「AI」、「Android」、「前端」、「iOS」、「考研」、「BAT」、「校招」、「笔试」、「面试」、「面经」、「计算机基础」、「LeetCode」 等关键字可以获取对应的免费学习资料。 


                     

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
8天前
|
NoSQL Java 关系型数据库
Liunx部署java项目Tomcat、Redis、Mysql教程
本文详细介绍了如何在 Linux 服务器上安装和配置 Tomcat、MySQL 和 Redis,并部署 Java 项目。通过这些步骤,您可以搭建一个高效稳定的 Java 应用运行环境。希望本文能为您在实际操作中提供有价值的参考。
64 26
|
12天前
|
SQL 存储 缓存
MySQL进阶突击系列(02)一条更新SQL执行过程 | 讲透undoLog、redoLog、binLog日志三宝
本文详细介绍了MySQL中update SQL执行过程涉及的undoLog、redoLog和binLog三种日志的作用及其工作原理,包括它们如何确保数据的一致性和完整性,以及在事务提交过程中各自的角色。同时,文章还探讨了这些日志在故障恢复中的重要性,强调了合理配置相关参数对于提高系统稳定性的必要性。
|
10天前
|
SQL 关系型数据库 MySQL
MySQL 高级(进阶) SQL 语句
MySQL 提供了丰富的高级 SQL 语句功能,能够处理复杂的数据查询和管理需求。通过掌握窗口函数、子查询、联合查询、复杂连接操作和事务处理等高级技术,能够大幅提升数据库操作的效率和灵活性。在实际应用中,合理使用这些高级功能,可以更高效地管理和查询数据,满足多样化的业务需求。
35 3
|
13天前
|
SQL 关系型数据库 MySQL
MySQL导入.sql文件后数据库乱码问题
本文分析了导入.sql文件后数据库备注出现乱码的原因,包括字符集不匹配、备注内容编码问题及MySQL版本或配置问题,并提供了详细的解决步骤,如检查和统一字符集设置、修改客户端连接方式、检查MySQL配置等,确保导入过程顺利。
|
12天前
|
SQL 监控 安全
SQL Servers审核提高数据库安全性
SQL Server审核是一种追踪和审查SQL Server上所有活动的机制,旨在检测潜在威胁和漏洞,监控服务器设置的更改。审核日志记录安全问题和数据泄露的详细信息,帮助管理员追踪数据库中的特定活动,确保数据安全和合规性。SQL Server审核分为服务器级和数据库级,涵盖登录、配置变更和数据操作等事件。审核工具如EventLog Analyzer提供实时监控和即时告警,帮助快速响应安全事件。
|
12天前
|
JavaScript 安全 Java
java版药品不良反应智能监测系统源码,采用SpringBoot、Vue、MySQL技术开发
基于B/S架构,采用Java、SpringBoot、Vue、MySQL等技术自主研发的ADR智能监测系统,适用于三甲医院,支持二次开发。该系统能自动监测全院患者药物不良反应,通过移动端和PC端实时反馈,提升用药安全。系统涵盖规则管理、监测报告、系统管理三大模块,确保精准、高效地处理ADR事件。
|
15天前
|
SQL 存储 关系型数据库
MySQL进阶突击系列(01)一条简单SQL搞懂MySQL架构原理 | 含实用命令参数集
本文从MySQL的架构原理出发,详细介绍其SQL查询的全过程,涵盖客户端发起SQL查询、服务端SQL接口、解析器、优化器、存储引擎及日志数据等内容。同时提供了MySQL常用的管理命令参数集,帮助读者深入了解MySQL的技术细节和优化方法。
|
16天前
|
SQL Oracle 关系型数据库
SQL(MySQL)
SQL语言是指结构化查询语言,是一门ANSI的标准计算机语言,用来访问和操作数据库。 数据库包括SQL server,MySQL和Oracle。(语法大致相同) 创建数据库指令:CRATE DATABASE websecurity; 查看数据库:show datebase; 切换数据库:USE websecurity; 删除数据库:DROP DATABASE websecurity;
|
7月前
|
存储 安全 Java
24、使用 Java 官方教程学习:① 类变量和类方法详解;② 深入介绍 main() 方法
24、使用 Java 官方教程学习:① 类变量和类方法详解;② 深入介绍 main() 方法
92 1
|
7月前
|
存储 Java
【JAVA学习之路 | 进阶篇】Map接口及其实现类及常用方法
【JAVA学习之路 | 进阶篇】Map接口及其实现类及常用方法