汪广舟 方少卿
(1.安徽理工大学,安徽 淮南 232001;2.铜陵职业技术学院,安徽 铜陵 244000)
随着当今的网络应用全面普及, 基于B/S 模型Web 应用系统应用越来越广泛,但是由于这个领域的入门门槛不高,程序员的水平及经验也良莠不齐,相当一部分程序员在编写代码的时候, 没有对用户输人数据的合法性进行判断和检查, 使应用程序存在极大安全隐患。
SQL 注入主要因为程序员对程序中动态SQL语句没有作严格的过滤或检测, 导致攻击者能在注入点提交非法的SQL 语句, 使得程序和服务器的信息被泄漏。注入攻击是互联网Web 安全所面临的最大威胁之一。 根据美国国家漏洞数据库(National Vulnerability Database)的统计[1],2008 年,SQL 注入漏洞占全年所有漏洞总数的19.41%,2009 年这个比例为16.85%。 OWASP 的统计结果表明[2],Web 应用十大安全漏洞中,SQL 注入漏洞的比例约为18%, 名列第二。
SQL 注入(SQL Injection)技术最早出现在1999年,微软中国技术中心从两个方面进行了描述:脚本注入式的攻击和恶意用户输入用来影响被执行的SQL 脚本。 利用SQL 注入技术来实施的网络攻击常被称为SQL 注入攻击(SQLIA,SQL Injection Attack),其本质是利用Web 应用程序中所输入的SQL 语句的语法处理,针对的是Web 应用程序开发者在编程过程中未对SQL 语句传入的参数做出严格的检查和处理所造成的漏洞。
如上面代码所示,如果用户输入的loginname 和password 的值分别为“admin”和“123456”,
服务器得到用户输入,交给login.asp 脚本处理,在脚本的第4、5 行将用户输入保存到变量中, 在第13 行将用户输入放在SQL 查询语句中。自动生成查询语句为:
select * from users where username='admin' and password='123456'
正常情况下,上述SQL 查询如果返回一条用户记录,则说明身份验证成功;反之,则说明身份验证失败。 然而,当用户的输入为“'admin' or 1=1 --”和“123456”,该服务器端脚本构造的SQL 查询语句为:
select * from users where username='admin' or 1=1 -- and password='123456'
输入的 “'” 闭合了SQL 语句的 “'”,“--”是SQL 语言中的注释。 所以“--”后面的所有内容被忽略,where 判断语句后面的 “or 1=1” 的恒成立,因此,系统将身份验证判断为成功,攻击者也即成功获得验证。
目前对SQL 注入攻击的通用防范是过滤SQL关键字或者敏感字符串, 包括:“'”,“--”,“exec”,“xp_”,“sp_”,“declare”,“union",“and”,“+”,“//”,“..”,“%”,“0x”等,然而,SQL 语句是千变万化的,一种语句可以等价成其他形式, 利用编码或数据库命令动态构造变异的SQL 语句能绕过这类防范。 如上例中“' or 1=1”可以变异成:“' or 'unusual' = 'unusual'”、“' or 'something'='some'+'thing'”、“' or something like 'some%'”、“' or 2 >1”、“'or' text' >'t'”、“'or whatever in (whatever')”、“'or 2 between 1 and 3”;而SQL 变异注入归纳起来有以下常用手段。
过滤函数通常会过滤select、update、delete 这些关键字, 但偏偏忘记区分大小写, 因此在构造SQL注入语句时可以将关键字进行大小写切换往往可以绕过程序的限制。
假设某网站有一条新闻的页面为:
http://site/news.asp?id=1
id 为参数名,1 为页面接受的参数值,攻击者可以构造如下URL:
http://site/news.asp?id=1 and (selecT count(*)from admin)>=0
猜解数据库中是否存在admin 表, 若返回页面与id=1 页面相同, 说明附加条件成立, 即表admin存在,反之,即不存在。
攻击者喜欢用“'”来测试注入漏洞。 所以也有很多程序会过滤“'”号的方法来“防止”注漏洞。 然而可以利用相关的函数,构造不含有单引号的SQL 注入语句,达到绕过程序限制的目的。如where xtype='a'。字符a 对应的ASCII 码是97, 所以可以用where xtype=char(97)代替,如果字符是中文的,比如where name=' 用户', 可以用where name=nchar (29992)+nchar(25143)代替。
URL 编码是一种浏览器用来打包表单输入的格式。 浏览器从表单中获取所有的name 和其中的值,将它们以name/value 参数编码(移去那些不能传送的字符, 将数据排行等) 作为URL 的一部分或者分离地发给服务器。
URL 编码遵循下列规则: 每对name/value 由&符分开;每对来自表单的name/value 由=符分开。 如果用户没有输入值给这个name, 那么name 还是出现,只是无值。 实质是一个字符的ASCII 码十六进制前面加上 “%”。 比如http://site/name 与http://site/nam%65 对于浏览器来说是等效的。 若注入语句为“http://site/news.asp?id=1 or 1=1”,经过编码后为:http://site/news.asp?id=1%20%6f%72%20%31%3d%31
防注入程序过滤了通过Get、Post 方式提交的数据,而忽略了Cookie 方式提交的数据。 若获取数据方式直接使用:request (" 参数名称"), 这时就产生Cookie 注入。 上例猜解数据库中是否存在admin 表注入语句可以变为:
Javascript:alert(document.cookie=”id=”+escape(1 and (select count(*) from admin)>=0)
在ASP 中Request 对象在省略具体的集合名称而直接使用“id=request(“id”)”来获取数据对,总是接Request.OueryString,Request.Form,Request.cookies,Request.servervariables 集合的顺序来搜索的,而Cookies 可以在客户端进行修改,这样一来,攻击者就可以使用诱使服务器接收Request.Cookies 方式提交变量的值,从而绕过防注入程序进行注入攻击。判定方式和Get 方式一样, 如网页返回的正常,则admin 表存在,反之则不存在。
(1)绕过空格过滤
使用注释/**/来替换空格, 类似C 语言一样,C语言在编译之前注释会被用个空格替换。 如:http://site/news.asp?id=1/**/or/**/1=1/**/,或者变异的如下:
http://site/news.asp?id=1/*o*/or/*o*/1=1/*o*/,然而许多过滤程序也会将“/”过滤掉,此种方法就行不通了,但是可以使用“( )”来分割关键字,如:http://site/news.asp?id=(1)or(1)=(1),此外空格还可以用Tab键或“+”来代替。
(2)整句赋值绕过多关键字过滤
SQL 防注入程序通常过滤掉许多关键字, 这时可套用DECLARE @S NVARCHAR(4000) SET @S=CAST(0x16 进制语句AS NVARCHAR(4000)) EXEC(@S)语句来绕过限制,比如要执行:
exec master.dbo.xp_cmdshell "net user"--
现将此句转换为十六进制,然后提交:
若返回正常的页面,则说明该语句成功执行了。
(3)xor 异或
对于SQL 注入来说, 用得最多的逻辑词就是“and”、“or”了,但是上面的逻辑词肯定会被SQL 防注入程序过滤掉。 但是除了“and”、“or”还有另外的逻辑词,如xor 异或,异或就是相同为假,不同为真。
现有防御SQL 注入技术主要基于静态程序分析和动态检测两大类, 包括: 输入过滤、 参数化查询、信息流分析[3-5]、专用API 等。
1.输入过滤往往仅凭预先定义好的敏感字符进行过滤, 比如SQL 通用防注入系统, 此种方法容易产生误报和漏报。而且,因为SQL 注入技术不断更新和发展, 如对注入的关键字进行编码, 因此基于敏感字符过滤的技术存在很多问题。同时, SQL 语句是千变万化的, 一种语句可以等价成其他形式, 利用编码或数据库命令动态构造结构字符串都可绕过这类防范。
2.在使用参数化查询的情况下,数据库服务器不会将参数的内容视为SQL 指令的一部份来处理,而是在数据库完成SQL 指令的编译后,才套用参数运行,因此就算参数中含有恶意的指令,由于已经编译完成,就不会被数据库所运行。此种方法缺点在于不是所有数据库都支持参数化查询。 目前Access、SQL Server、MySQL、SQLite、Oracle 等常用数据库支持参数化查询。
3.动态的信息流分析技术主要根据语法树推断原程序查询语句的目的, 而这类方法面对的最主要问题是能否准确分析和推断原语句的目的和注入语句目的的不同。
4.专用API 是特定的WEB 程序将常用的数据库操作封装成一些专用的API 函数,一般是一些商业系统。 这种方法可能不会存在SQL 注入的风险,但对于每个WEB 应用都采用专用API 是不可能的, 同时需要编程人员学习这些专用API 函数的调要语法。
人们的网络安全意识越来越强, 绝大多数Web站点对SQL 注入进行防范,但是各种SQL 注入变异攻击随之出现,就目前提出的一些防御SQL 攻击的方法都有各自的优缺点, 还没有一个完美的解决方案,防范SQL 注入攻击任重而道远。
[1]National Vulnerability Database.National vulnerability database(NVD) CVE statistics[EB/OL].(2012-12).http://web.nvd.nist.gov/view/vuln/statistics-results?cid=4,2012-09-10.
[2]OWASP.Top 10 2007 [EB/OL]. (2012 -11).http://www.owasp.org/index.php/Top_10_2007,2012-10-02.
[3]Sabelfeld A,Myers AC.Language -based infoumation -flow security[J]. IEEE JSA,2003.
[4]周敬利,晓 锋,等.一种新的反SQL 注入策略的研究与实现[J].计算机科学,2006,33(11):64-68.
[5]Carl Gould, Zhendong Su, and Premkumar Devanbu.Static checking of dynamically generated queries in database applications.ACM Transactions on Software Engineeringand Methodology(TOSEM)[C]. U.S.A:ACM,2007,16.