注入攻击是web安全领域中一种最为常见的攻击方式。注入攻击的本质,就是把用户输入的数据当做代码执行。这里有两个关键条件,第一是用户能够控制输入,第二个就是原本程序要执行的代码,将用户输入的数据进行了拼接,所以防御的思想就是基于上述两个条件。
SQL注入第一次为公众所知,是在1998年的著名黑客杂志<<Phrack>>上,一位名叫rfp的黑客发表了一片题为“NT Web Technolog Vulnerabities”的文章。
一个简单的SQL注入的典型例子:
变量username为用户所提交,正常情况下,假如用户输入“XiaoMing”,那么SQL语句会执行:
select * from UserTable where username='XiaoMing';
若用户输入一段有特别含义的SQL语句,比如:
XiaoMing' ;drop table UserTable--
那么SQL语句在实际执行时就会如下:
select * from UserTable where username='XiaoMing';drop table UserTable--'
现在变成了查询后,再执行一个drop表的操作,而这个操作,使用户构造了恶意数据的结果。
在SQL注入的过程中,如果网站的Web服务器开启了消息回显,则可以根据回显的错误消息,探测网站用的是什么数据库,例如:错误提示Microsoft.JET Database Engine错误,则说明是通过JET引擎连接数据库,表明数据库为ACESS数据库,如果是ODBC的话,则说明是MSSQL数据库。
数据库的判断方法有很多,这里大致说下我了解到的几种方法思路,不详细展开。
第一种基于特定函数:不同的数据库对应着的函数名称不一样,如len()和length(),@@version()和version()在MSSQL,Mysql数据库中不一样,substring()和substr()在oracle和Mysql中不一样
第二种基于辅助符号的判断: “ / * ”是Mysql中的注释符。 “ --”是Oracle和MSSQL支持的注释符,";"子查询标识符,Oracle不支持多行查询。结合以上符合多种作何判断。
第三种基于错误回显信息判断:针对数据库引擎的判断。
盲注(Blind Injection)
在没有回显消息的时候,可以进行SQL盲注,最常见的盲注验证方法就是构造简单的条件语句,根据返回页面是否发生改变,来判断SQL语句是否得到了执行。
1.简单的 and 1=1 和 and 1=2
例如攻击者构造如下条件的语句:
http://newspaper.com/items.php?id=2 and 1=2
SQL语句由于“1=2”是个假命题,所以攻击者看到页面将为空或者是一个出错的页面。
为了进一步确定注入是否存在,攻击者必须再次验证这个过程:
http://newspaper.com/items.php?id=2 and 1=1
如果这个请求页面正常返回了,则说明SQL语句的"and"成功执行,那么就可以判断“id”参数存在SQL注入漏洞了。
在这个攻击过程中,服务器虽然关闭了错误回显,但是通过攻击者简单的条件构造,再对比返回结果的差异,就可以判断出SQL注入漏洞是否存在,这就是盲注的工作原理。
Timing Attack(边信道攻击)
在Mysql中,有一个benchmark()函数,用来测试函数性能的,benchmark(count,expr)函数的执行结果就是将expr表达式执行count次数。因此,利用这个函数,可以让同一个函数执行若干次,使得结果返回时间比平时要长;通过时间长短的变化,可以判断出注入语句是否执行成功。这是一种边信道攻击,这个技巧在盲注中称为Timing Attack。
接下来我们使用这种技巧完成攻击,先构造攻击参数id值为:
这段Payload判断数据库名的第一个字母是否为小写的w。如果判断为真,则会通过BENCHMARK()函数造成较长的时延;如果不为真,则该语句将很快执行完。攻击者遍历所有字母,直到将整个数据库名称全部验证完成为止。与此相似的还可以通过以下函数获得一些额外信息:
database():当前连接的数据库名称
system_user():数据库的系统用户
current_user():登录到数据库的当前用户
last_insert_id():最后一次进行插入操作数据库的事务id
若当前数据库用户(current_user)有写权限。可以将信息写入本地磁盘中。比如写入web目录中,攻击者就可以下载这些文件:
2 Union All SELECT * FROM information_schema.tables where table_schema='mysql' ORDER BY table_name DESC INTO OUTFILE
'/path/location/on/server/www/schema.txt '
或者是写入一个webshell:
2 Union All SELECT "<? system($_REQUEST['cmd']); ?>" ,2,3,4 INTO OUTFILE
"var/www/html/temp/c.php" --
在不同数据库中,有着类似benchmark()函数,可以被Timing Attack利用。例如:
MySql数据库中的 benchmark(1000000,expr)和sleep(5)
PostgreSQL数据库中的PG_SLEEP(5)和GENERATE_SERIES(1,1000000)
MSSQL Server中的 WAITFOR DELAY '0:0:5'