前言
不管用什么语言编写的Web应用,它们都用一个共同点,具有交互性并且多数是数据库驱动。在网络中,数据库驱动的Web应用随处可见,由此而存在的SQL注入是影响企业运营且最具破坏性的漏洞之一。
一、基本介绍
结构化查询语言(StructuredQueryLanguage,缩写:SQL),是一种特殊的编程语言,用于数据库中的标准数据查询语言。1986年10月,美国国家标准学会对SQL进行规范后,以此作为关系式数据库管理系统的标准语言(ANSIX3.135-1986),1987年得到国际标准组织的支持下成为国际标准。不过各种通行的数据库系统在其实践过程中都对SQL规范作了某些编改和扩充。所以,实际上不同数据库系统之间的SQL不能完全相互通用。
SQL注入(SQLInjection)是一种常见的web安全漏洞,攻击者利用这个问题,可以访问或修改数据,或者利用潜在的数据库漏洞进行攻击。
二、产生原因
SQL注入攻击指的是通过构建特殊的输入作为参数传入Web应用程序,而这些输入大都是SQL语法里的一些组合,通过执行SQL语句进而执行攻击者所要的操作,其主要原因是程序没有细致地过滤用户输入的数据,致使非法数据侵入系统。
根据相关技术原理,SQL注入可以分为平台层注入和代码层注入。前者由不安全的数据库配置或数据库平台的漏洞所致;后者主要是由于程序员对输入未进行细致地过滤,从而执行了非法的数据查询。基于此,SQL注入的产生原因通常表现在以下几方面:①不当的类型处理;②不安全的数据库配置;③不合理的查询集处理;④不当的错误处理;⑤转义字符处理不合适;⑥多个提交处理不当。
三、类型分类
SQL注入类型大致可以分为三类:
1. 从注入手法分类可以分为:联合查询注入、报错型注入、布尔型注入、延时注入、堆叠注入;
2. 从数据类型上可以分为:字符型(即输入的输入使用符号进行过滤)、数值型(即输入的输入未使用符号进行过滤);
3.从注入位置可以分类为:GET数据(提交数据方式为GET,大多存在地址栏)、POST数据(提交数据方式为POST,大多存在输入框中)、HTTP头部(提交数据方式为HTTP头部)、cookie数据(提交数据方式为cookie)。
四、产生危害
SQL注入漏洞常见且危害性大,具体表现为:
绕过登录验证,使用万能密码登录网站后台等
获取敏感数据,获取网站管理员帐号、密码等
文件系统操作,列目录,读取、写入文件等
注册表操作,读取、写入、删除注册表等
执行系统命令,远程执行命令
五、举例
1.联合查询注入
其中最重要的是页面要有显示位,即爆出来的库信息能在页面上当作正常数据显示出来。然后爆出来的库信息要放在select后相应的位置。下面是操作步骤:
首先判断闭合类型
?id=1' and 1=1 --
?id=1' and 1=2 --
如果显示不同,所以要单引号闭合,其次判断显示位数
?id=-1' order by 4 --
最后进行联合查询注入,把显示位的数字替换为database()
http://localhost/sqli-labs-master/Less-1/?id=-1' union select 1,2,database() --
2.报错型注入
使用检测闭合类型的方法发现有关有报错信息,可以实现报错注入,下面是常见的注入步骤:
测试闭合类型为单引号闭合
输入报错注入的函数
http://localhost/sqli-labs-master/Less-5/?id=1' and extractvalue(1,concat(0x7e,database(),0x7e)) --
报错函数不单单只有extractvalue,还有updatexml和floor,下面我们说明一下使用情况和方法:
extractvalue函数:extractvalue(1,2)在xml文档中提取相应的值,第一个数值表示xml字符串,第二个是xml路径。注入的时候,使用的方式大概为?id=1 and extractvalue(111,'~sdfggfds'),发现第二位的属于会在报错代码中显示。使用的限制为对mysql版本有要Mysql5.0 以上才能使用函数。
UpdateXml函数:该函数共有三个参数,第一个参数是XML文档对象的名称,第二个参数是xml路径,第三个参数是String格式替换查找到的符合条件的数据。注入的时候,使用的方式大概为id=1 and updatexml(1,concat(0x7e,(查询的内容),0x7e),1),使用的限制为对mysql版本有要Mysql5.0 以上才能使用函数。
Floor函数:注入的时候,使用的方式大概为?id=1 and (select 1 from (select count(*),concat((select 查询的内容 from information_schema.tables limit 0,1),floor(rand()*2))x from information_schema.tables group by x)a) -- ,且适应任何mysql版本。
3.延时注入
使用sleep函数进行延时查询闭合方式,sleep()函数可以让页面延迟运行一段时间。输入?id=1' and sleep(10) --+发现页面会有延时,则说明闭合方式为单引号闭合,使用if函数判断数据库长度范围,数据库函数if(表达式,1,2)如果表达式成立输出1,不成立输出2,输入?id=1' and if(length(database())=8,sleep(10),0) -- 进行测试。最后使用ASCII码进行获取首字母,?id=1' and if(ascii(substr(database(),1,1))=115,sleep(5),0) -- ,执行时发现有延时则说明测试的ASCII对应刚好就是115。
4.堆叠注入
在SQL中,分号(;)是用来表示一条sql语句的结束。试想一下我们在 ; 结束一个sql语句后继续构造下一条语句,会不会一起执行?因此这个想法也就造就了堆叠注入。而union injection(联合注入)也是将两条语句合并在一起,两者之间有什么区别么?区别就在于union 或者union all执行的语句类型是有限的,可以用来执行查询语句,而堆叠注入可以执行的是任意的语句。例如以下这个例子。用户输入:1; DELETE FROM products服务器端生成的sql语句为:(因未对输入的参数进行过滤)Select * from products where productid=1;DELETE FROM products当执行查询后,第一条显示查询信息,第二条则将整个表进行删除。
六、防御方法
防止注入漏洞需要将数据与命令语句、查询语句分隔开来。
• 最佳选择是使用安全的API,完全避免使用解释器,或提供参数化界面的接口,或迁移到ORM或实体框架。
注意:当参数化时,存储过程仍然可以引入SQL注入,如果PL/SQL或T-SQL将查询和数据连接在一起,或者执行带有立即执行或exec()的恶意数据。
• 使用正确的或“白名单”的具有恰当规范化的输入验证方法同样会有助于防止注入攻击,但这不是一个完整的防御,因为许多应用程序在输入中需要特殊字符,例如文本区域或移动应用程序的API。
• 对于任何剩余的动态查询,可以使用该解释器的特定转义语法转义特殊字符。
注意:SQL结构,比如:表名、列名等无法转义,因此用户提供的结构名是非常危险的。这是编写软件中的一个常见问题。
• 在查询中使用LIMIT和其他SQL控件,以防止在SQL注入时大量地泄露记录。