一文搞懂SQL注入攻击

目录
  • 1. 前言
  • 2. SQL注入简介
    • (1)SQL语言
    • (2)SQL注入
  • 3. SQL注入步骤
    • (1)发现漏洞
    • (2)信息收集
    • (3)攻击Web系统(猜解用户名和密码)
    • (4)获取管理员权限
  • 4. 防范SQL注入
    • (1)使用参数化查询或存储过程
    • (2)用户输入检测
    • (3)SQL语法分析
    • (4)其他

1. 前言

随着互联网的发展和普及,网络安全问题越来越突出,网络在为用户提供越来越多服务的同时,也要面对各类越来越复杂的恶意攻击。SQL注入(SQL Injection)攻击是其中最普遍的安全隐患之一,它利用应用程序对用户输入数据的信任,将恶意SQL代码注入到应用程序中,从而执行攻击者的操作。这种攻击可以导致敏感信息泄露、数据损坏或删除及系统瘫痪,给企业和个人带来巨大损失。因此,如何防范SQL注入攻击成为了网络安全领域的一个重要议题。

在国外,SQL注入最早出现在1999年;在我国大约出现在2002年。2015年,约翰·卡特尔(John McAfee)的网站遭到了SQL注入攻击,导致黑客获取了网站上全部的注册用户信息。2016年,Yahoo公司披露了两起大规模数据泄露事件,其中涉及的一次就是通过SQL注入攻击获得的。2017年,Equifax公司遭到了一次严重的数据泄露事件,泄露了超过1.43亿条用户记录。调查人员发现,攻击者使用了SQL注入攻击。

可见,SQL注入攻击破坏敏感数据的完整性和可用性,给网络用户和企业造成了巨大的生活困扰和经济损失。

2. SQL注入简介

(1)SQL语言

Structured Query Language(简称SQL)是—种结构化查询语言,一种数据库文本语言。SQL用于同关系数据库进行交互,能够执行对数据库的查询、获取数据库的信息、向数据库插入新的纪录、删除及更新数据库中的记录。

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

(2)SQL注入

SQL注入攻击是一种利用应用程序漏洞的攻击方式。攻击者通过向应用程序发送构造的恶意SQL语句,欺骗应用程序执行这些SQL语句,如果Web应用没有适当的验证用户输入的信息,攻击者就有可能改变后台执行的SQL语句的结构,获取相应结果。攻击者可以利用SQL注入漏洞获取数据库中的敏感信息,修改或删除数据库中的数据,或者完全控制Web服务器。

比如基于表单登录功能的应用程序,通过执行一个简单的SQL查询来确认每次登录,以下是这个查询的一个典型实例:

SELECT * FROM users WHERE username='alice' and password='secret'

这个查询要求数据库检查用户表中的每一行,提取username值为alice并且password值为secret的记录。如果返回一条用户记录,该用户即可成功登录。

攻击者可注入用户名或密码字段来修改程序执行的查询,一般是输入双连字符(--)注释掉其余部分或类似’ or ‘1’ =‘1用引号包含的字符串数据来“平衡引号”,来破坏查询的逻辑。比如攻击者可以通过提交用户名为alice’--alice’ or ‘1’=‘1,密码为任意,应用程序将执行以下查询:

SELECT * FROM users WHERE username='alice'--‘' and password='any'

SELECT * FROM users WHERE username=' alice' or ‘1'=‘1' and password='any'

这两条查询均等同于

SELECT * FROM users WHERE username='alice'

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

因此SQL注入漏洞本质上是针对程序员编程中的漏洞,利用SQL的语法在应用程序与数据库交互的SQL语句中插入精心编制的额外的SQL语句,从而对数据库进行非法查询和修改。由于程序运行SQL语句时的权限与当前该组建(例如,数据库服务器、Web应用服务器)的权限相同,而这些组件一般的运行权限都很高,而且经常是以管理员的权限运行,所以攻击者可能获得数据库的完全控制,并执行系统命令。

3. SQL注入步骤

SQL注入攻击有多种类型,包括基于错误的注入、联合查询注入、堆叠查询注入等。其中,基于错误的注入是最常见的类型。攻击者通过发送包含恶意SQL语句的输入数据来触发应用程序中的错误,从而获取有关数据库结构和内容的信息。

(1)发现漏洞

可以用经典的1=1,1=2测试法测试SQL注入是否存在。

以http://www.test.com/profile.do?id=113为例,使用以下测试方案:

  • http://www.test.com/profile.do?id=113’
  • http://www.test.com/profile.do?id=113 and 1=1
  • http://www.test.com/profile.do?id=113 and 1=2

(2)信息收集

确认系统表是否存在,主要利用Oracle数据库中以下系统表:

  • all_tables:存放当前ID和其他用户的所有表
  • user_tables:存放当前用户所有表
  • user_tab_columns:存放当前用户表的所有列

测试以下URL:

  • http://www.test.com/profile.do?id=113’and 0<>(select count(*) from all_tables) and '1'='1
  • http://www.test.com/profile.do?id=113’and 0<>(select count(*) from user_tables)and '1'='1
  • http://www.test.com/profile.do?id=113’and 0<>(select count(*) from user_tab_ columns) and '1'='1

如果以上页面都能正确返回,说明存在猜测的系统表。

(3)攻击Web系统(猜解用户名和密码)

首先查找当前用户是否有敏感列名:

'and 0<>(select count(*) from user_tab_columns where column_name like '%25PASS%25') and '1'='1

正常返回说明存在类似PASS的字段,猜解该字段对应的表名。先确定表名的长度(不断改变length(table_name)后的数值):

'and 0<>(select count(*) from user_tables where length(table_name)>8 and table_ name like'%25PASS%25') and '1'='1

利用ASCII二分法猜解表名(不断改变substr函数的参数及比较值):

'and  (ascii(substr((select table_name from user_tab_columns where column_name like '%PASS%' And Rownum<=1),1,1))>64) and '1'='1

猜字段同样先确定长度,然后利用ASCII二分法猜解字段名:

'and 0<>(select count(*) from user_tables where table_name='T_SYSUSER'and length (column_ name) >8  and column_name like '%PASS%') and '1'='1
'and  (ascii(substr((select column_name from user_tab_columns where table_name ='T_SYSUSER' and column_name like '%25PASS%25'),1,1))>64) and '1'='1

得到用户表的USERNAMEPASSWD两列的名称后,依然是利用ASCII码猜解法来一步一步确定USERNAMEPASSWD的值,不再详述。

(4)获取管理员权限

要想获取对系统的完全控制,还要有系统的管理员权限。Oracle包含许多可在数据库管理员权限下运行的内置存储过程,并发现在这些存储过程中存在SQL注入漏洞。2006年7月补丁发布之前,存在于默认包SYS.DBMS_ EXPORT_EXTERSION.GET_DOMAIN_INDEX_TABLES中的缺陷就是一个典型的示例。攻击者可以利用这个缺陷,在易受攻击的字段中注入GRANT DBA TO PUBLIC查询(需要换成char形式)来提升权限。

这种类型的攻击可通过利用Web程序中的SQL注入漏洞,在易受攻击的参数中输入函数来实现。许多其他类型的缺陷也影响到Oracle的内置组件。一个示例是CTXSYS.DRILOAD.VALIDATE_STMT函数。这个函数的目的是检查一个指定的字符串中是否包含一个有效的SQL语句。早期Oracle版本中,在确定被提交的语句的过程中,这个函数实际执行了该语句。这意味着任何用户只需向这个函数提交一个语句,就能够作为数据库管理员执行该语句。例如:

exec CTXSYS.DRILOAD.VALIDATE_STMT(‘GRANT DBA TO PUBLIC')

除这些漏洞外,Oracle还含有大量默认功能,这些功能可被低权限用户访问,并可用于执行各种敏感操作,建立网络连接或访问文件系统。比如,可利用UTL_HTTP 包里面的 request函数构造注射,来建立用户,并赋予DBA权限。

4. 防范SQL注入

(1)使用参数化查询或存储过程

参数化查询分两个步骤建立一个包含用户输入的SQL语句:

  • 应用程序制定查询结构,为用户输入的每个数据预留占位符;
  • 应用程序制定每个占位符的内容。
    在第二步中指定的专门设计的数据无法破坏在第一步中指定的查询结构。由于查询结构已经确定,且相关API 对任何类型的占位符数据进行安全处理,因此它总被解释为数据,而非语句结构的一部分。

Java提供以下API,允许应用程序创建一个预先编译的SQL语句,并以可靠且类型安全的方式指定它的参数占位符的值:

 java.sql.Connection.prepareStatement
 java.sql.PrepareStatement.*

使用如下:

String username = request.getParameter("j_username");
String passwd = request.getParameter("j_password");
String query = "select * from t_sysuser where username=? and passwd=?";
PreparedStatement stmt = con.prepareStatement(query);
stmt.setString(1, username);
stmt.setString(1, passwd);
ResultSet rs=stmt.executeQuery();

如果用户提交的用户名为alice’ or 1=1--,密码为any,生成的查询等同于:

select * from t_sysuser where username= ‘alice' ‘or 1=1--' and passwd='any'

由此可见使用参数化查询可以有效防止SQL注入,应在每一个数据库查询中使用参数化查询。如果仅注意用户直接提交的输入,二阶SQL注入攻击就很容易被忽略因为已经被处理的数据被认为是可信的。另外参数占位符不能用于指定查询中表和列的名称,如果应用程序需要根据用户提交的数据在SQL查询中指定这些数据行,需要使用一份由已知可靠的值组成的“白名单”(即数据库中表和列的名称),并拒绝任何与这份名单上数据不匹配的输入项。或者对用户输入实施严格的确认机制。

使用存储过程的原理与参数化查询类似,传入的参数在最后被执行的SQL语句中会被数据库服务器软件进行处理,使得输入的字符串会被当作一个单纯的文本参数参与到SQL查询中。不论是攻击者输入什么参数都不会改变设计者编写的SQL语句的语义,也就防止了SQL注入。另外由于存储过程是预编译的,对复杂的SQL语句,效率有很大程度上的提升,还可以进一步减少查询时客户端发送到服务端的数据包。

(2)用户输入检测

对输入进行检测一般是在客户端和服务器端利用正则表达式来匹配SQL的特殊字符及其等值的十六进制形式,包括单引号(’)、双重破折号(–)、SELECT、UNION等查询关键字,然后对其进行替换或者过滤。但是在所有的接受输入的程序部分都严格的执行检测却很难,而且会产生误报。

(3)SQL语法分析

SQL注入根源在于对于用户提交的请求没有足够的验证机制,正常的用户输入是具有逻辑整体含义的简单结构,而实施 SQL 注入的字符串一定是包含 SQL语法片段的复合结构。 SQL 注入攻击本质上是希望后台数据库的 SQL 解释程序按照不同的方式解释组装好的 SQL 语句,如果用户输入的字符串不包含 SQL 语法片段,显然无法达到这个目的。

静态代码分析中能从语法、语义上理解程序行为,直接分析被测程序特征,寻找可能导致错误的异常。因此可以在服务器端采用一种类似于静态代码分析的SQL 语法预分析策略来防止SQL注入。首先将 SQL 注入分类,并对其进行词法分析和语法分析,抽象出各类注入的语法结构,生成语法分析树;能够利用该语法分析树通过机器学习的方法来得到预想的SQL注入的集合,并从该集合中生成新的语法分析树;然后将用户提交的输入预先组装成完整的 SQL 语句,对该语句进行语法分析,如果发现具有 SQL 注入特征的语法结构,则判定为 SQL 注入攻击。判定的唯一依据是抽象的语法结串,而非具体的特征字符串,避免了传统的特征字符串匹配策略固有的高识别率和低误判率之间的矛盾。

由于SQL注入利用的是正常的服务端口,在各类Web应用中已不能通过使用防火墙,SSL等网络层保护技术来阻止应用层攻击,也就是说安全边界扩展到了系统源代码。因此,必须通过防范软件代码中存在的安全漏洞,从而保障系统的安全。

(4)其他

通过在程序中对口令等敏感信息加密,(一般采用MD5函数),另外在原来的加密的基础上可以增加一些非常规的方式,即在MD5加密的基础上附带一些值 如密文=MD5 (MD5 (明文)+系统时间);编码时注意屏蔽网页上显示的异常与出错信息,并对源代码进行安全审查及软件安全测试。

安全配置服务器,包括目录最小化权限设置:给静态网页目录和动态网页目录分别设置不同权限,尽量不给写目录权限;修改或者去掉 Web 服务器上默认的一些危险命令,例如ftp、cmd等 需要时再复制到相应目录;正确配置iptables及Oracle的sqlnet.ora文件,通过IP地址限制对于数据库访问。

以上就是一文搞懂SQL注入攻击的详细内容,更多关于SQL注入攻击的资料请关注我们其它相关文章!

(0)

相关推荐

  • Nginx中防止SQL注入攻击的相关配置介绍

    防止sql注入最好的办法是对于提交后台的所有数据都进行过滤转义. 对于简单的情况,比如包含单引号' , 分号;, <, >, 等字符可通过rewrite直接重订向到404页面来避免. 用rewrite有个前提需要知道,一般用rewrite进行正则匹配只能匹配到网页的URI,也就是url中?前部分,?以后部分是请求参数. 问号后面的请求参数,在nginx用$query_string表 示,不能在rewrite中匹配到,需要用if判断 例如,对于参数中带有单引号的'进行匹配然后定向到错误页面, /

  • MyBatis下SQL注入攻击的3种方式

    目录 前言 Mybatis框架下易产生SQL注入漏洞的情况主要分为以下三种: 1.模糊查询 2.in 之后的多个参数 3.order by 之后 二.实战思路 三.总结 前言 SQL注入漏洞作为WEB安全的最常见的漏洞之一,在java中随着预编译与各种ORM框架的使用,注入问题也越来越少.新手代码审计者往往对Java Web应用的多个框架组合而心生畏惧,不知如何下手,希望通过Mybatis框架使用不当导致的SQL注入问题为例,能够抛砖引玉给新手一些思路. Mybatis的SQL语句可以基于注解的

  • 细谈php中SQL注入攻击与XSS攻击

    例如: SQL注入攻击 XSS攻击 复制代码 代码如下: 任意执行代码 文件包含以及CSRF. } 关于SQL攻击有很多文章还有各种防注入脚本,但是都不能解决SQL注入的根本问题 见代码: 复制代码 代码如下: <?php mysql_connect("localhost","root","123456")or die("数据库连接失败!"); mysql_select_db("test1"); $u

  • Yii框架防止sql注入,xss攻击与csrf攻击的方法

    本文实例讲述了Yii框架防止sql注入,xss攻击与csrf攻击的方法.分享给大家供大家参考,具体如下: PHP中常用到的方法有: /* 防sql注入,xss攻击 (1)*/ function actionClean($str) { $str=trim($str); $str=strip_tags($str); $str=stripslashes($str); $str=addslashes($str); $str=rawurldecode($str); $str=quotemeta($str)

  • ASP.NET防范SQL注入式攻击的方法

    一.什么是SQL注入式攻击?  SQL注入式攻击就是攻击者把SQL命令插入到Web表单的输入域或页面请求的查询字符串,欺骗服务器执行恶意的SQL命令.在某些表单中,用户输入的内容直接用来构造(或者影响)动态SQL命令,或作为存储过程的输入参数,这类表单特别容易受到SQL注入式攻击.常见的SQL注入式攻击过程类如: ⑴ 某个ASP.NET Web应用有一个登录页面,这个登录页面控制着用户是否有权访问应用,它要求用户输入一个名称和密码. ⑵ 登录页面中输入的内容将直接用来构造动态的SQL命令,或者直

  • PHP MYSQL注入攻击需要预防7个要点

    1:数字型参数使用类似intval,floatval这样的方法强制过滤. 2:字符串型参数使用类似mysql_real_escape_string这样的方法强制过滤,而不是简单的addslashes. 3:最好抛弃mysql_query这样的拼接SQL查询方式,尽可能使用PDO的prepare绑定方式. 4:使用rewrite技术隐藏真实脚本及参数的信息,通过rewrite正则也能过滤可疑的参数. 5:关闭错误提示,不给攻击者提供敏感信息:display_errors=off. 6:以日志的方式

  • mybatis注解动态sql注入map和list方式(防sql注入攻击)

    目录 网上的教程 我的教程(防sql注入攻击) 注入Map 注入List 封装foreach mybatis防止sql注入的循环map写法 网上的教程 配置xml 注解中写xml脚本@Select() 使用Java类中的Java方法拼写sql语句(不防sql注入攻击的纯字符串拼接) 我的教程(防sql注入攻击) 注入Map Mapper层代码 @Repository public interface ManageMapper { @SelectProvider(type = ManageProv

  • 一文搞懂SQL注入攻击

    目录 1. 前言 2. SQL注入简介 (1)SQL语言 (2)SQL注入 3. SQL注入步骤 (1)发现漏洞 (2)信息收集 (3)攻击Web系统(猜解用户名和密码) (4)获取管理员权限 4. 防范SQL注入 (1)使用参数化查询或存储过程 (2)用户输入检测 (3)SQL语法分析 (4)其他 1. 前言 随着互联网的发展和普及,网络安全问题越来越突出,网络在为用户提供越来越多服务的同时,也要面对各类越来越复杂的恶意攻击.SQL注入(SQL Injection)攻击是其中最普遍的安全隐患之

  • 一文搞懂Java JDBC中的SQL注入问题

    目录 SQL注入 什么是SQL注入 SQL注入的效果的演示 SQL注入代码 SQL注入效果 如何避免SQL注入 PrepareStatement解决SQL注入 PreparedStatement的应用 参数标记 动态参数绑定 综合案例 PreparedStatement总结 必须使用Statement的情况 SQL注入 什么是SQL注入 在用户输入的数据中有SQL关键字或语法,并且关键字或语法参与了SQL语句的编译.导致SQL语句编译后的条件为true,一直得到正确的结果.这种现象就是SQL注入

  • 如何使用IDEA开发Spark SQL程序(一文搞懂)

    目录 前言 Spark SQL是什么 1.使用IDEA开发Spark SQL 1.1.指定列名添加Schema 1.2.通过StructType指定Schema 1.3.反射推断Schema–掌握 1.4.花式查询 1.5. 相互转化 1.6.Spark SQL完成WordCount(案例) 1.6.1.SQL风格 1.6.2.DQL风格 前言 大家好,我是DJ丶小哪吒,我又来跟你们分享知识了.对软件开发有着浓厚的兴趣.喜欢与人分享知识.做博客的目的就是为了能与 他 人知识共享.由于水平有限.博

  • 技巧和诀窍防范SQL注入攻击

    [原文地址]Tip/Trick: Guard Against SQL Injection Attacks [原文发表日期] Saturday, September 30, 2006 9:11 AM SQL注入攻击是非常令人讨厌的安全漏洞,是所有的web开发人员,不管是什么平台,技术,还是数据层,需要确信他们理解和防止的东西.不幸的是,开发人员往往不集中花点时间在这上面,以至他们的应用,更糟糕的是,他们的客户极其容易受到攻击. Michael Sutton 最近发表了一篇非常发人深省的帖子,讲述在

  • 一文搞懂MySQL预编译

    1.预编译的好处 大家平时都使用过JDBC中的PreparedStatement接口,它有预编译功能.什么是预编译功能呢?它有什么好处呢? 当客户发送一条SQL语句给服务器后,服务器总是需要校验SQL语句的语法格式是否正确,然后把SQL语句编译成可执行的函数,最后才是执行SQL语句.其中校验语法,和编译所花的时间可能比执行SQL语句花的时间还要多. 如果我们需要执行多次insert语句,但只是每次插入的值不同,MySQL服务器也是需要每次都去校验SQL语句的语法格式,以及编译,这就浪费了太多的时

  • 一文搞懂MySQL XA如何实现分布式事务

    目录 前言 XA 协议 如何通过MySQL XA实现分布式事务 前言 MySQL支持单机事务的良好表现毋庸置疑,那么在分布式系统中,涉及多个节点,MySQL又是如何实现分布式事务的呢?比如开发一个业务系统,它接受外部的请求,然后访问多个内部其它系统才能执行该请求.执行时我们需要同时更新多个数据库的值(D1,D2,D3).由于系统必须处于一个一致性,也就是这三个数据库的值要么同时更新成功,要么全部不更新.不然会造成子系统有些指令成功了,有些指令尚未执行.导致对结果理解混乱. 那么,MySQL如何实

  • 一文搞懂MySQL持久化和回滚的原理

    目录 redo log 为什么要先更新内存数据,不直接更新磁盘数据? 为什么需要redo log? redo log是如何实现的? 为什么一个block设计成512字节? 为什么要两段式提交? crash后是如何恢复的? undo log 什么情况下会生成undo log? undo log是如何回滚的? undo log存在什么地方? redo log 事务的支持是数据库区分文件系统的重要特征之一,事务的四大特性: 原子性:所有的操作要么都做,要么都不做,不可分割. 一致性:数据库从一种状态变

  • 一文搞懂MySQL脏读,幻读和不可重复读

    目录 MySQL 中事务的隔离 1.READ UNCOMMITTED 2.READ COMMITTED 3.REPEATABLE READ 4.SERIALIZABLE 前置知识 1.事务相关的常用命令 2.MySQL 8 之前查询事务的隔离级别 3.MySQL 8 之后查询事务的隔离级别 4.查看连接的客户端详情 5.查询连接客户端的数量 6.设置客户端的事务隔离级别 7.新建数据库和测试数据 8.名称约定 脏读 1.脏读演示步骤1 2.脏读演示步骤2 3.脏读演示步骤3 4.不可重复读 5.

  • 一文搞懂Spring中Bean的生命周期

    目录 一.使用配置生命周期的方法 二.生命周期控制——接口控制(了解) 小结 生命周期:从创建到消亡的完整过程 bean声明周期:bean从创建到销毁的整体过程 bean声明周期控制:在bean创建后到销毁前做一些事情 一.使用配置生命周期的方法 在BookDaoImpl中实现类中创建相应的方法: //表示bean初始化对应的操作 public void init(){ System.out.println("init..."); } //表示bean销毁前对应的操作 public v

  • 一文搞懂Mysql中的共享锁、排他锁、悲观锁、乐观锁及使用场景

    目录 一.常见锁类型 二.Mysql引擎介绍 三.常用引擎间的区别 四.共享锁与排他锁 五.排他锁的实际应用 六.共享锁的实际应用 七.死锁的发生 八.另一种发生死锁的情景 九.死锁的解决方式 十.意向锁和计划锁 十一.乐观锁和悲观锁 总结 一.常见锁类型 表级锁,锁定整张表 页级锁,锁定一页 行级锁,锁定一行 共享锁,也叫S锁,在MyISAM中也叫读锁 排他锁,也叫X锁,在MyISAM中也叫写锁 悲观锁,抽象性质,其实不真实存在 乐观锁,抽象性质,其实不真实存在 常见锁类型 二.Mysql引擎

随机推荐