注入攻击(SQL注入)

注入攻击是web安全领域中一种最为常见的攻击方式。注入攻击的本质,就是把用户输入的数据当做代码执行。这里有两个关键条件,第一是用户能够控制输入,第二个就是原本程序要执行的代码,将用户输入的数据进行了拼接,所以防御的思想就是基于上述两个条件。

SQL注入第一次为公众所知,是在1998年的著名黑客杂志<<Phrack>>上,一位名叫rfp的黑客发表了一片题为“NT Web Technolog Vulnerabities”的文章。

一个简单的SQL注入的典型例子:

var username;
username=Request.form(username);
var sql="select * from UserTable where name =' "+username+" ' ";

变量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值为:

2 UNION SELECT IF(SUBSTRING(current,1,1)=CHAR(119),BENCHMARK(5000000,ENCODE('MSG','by 5 seconds')),null)
FROM(Select Database() as current) as tbl;

这段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'

上一篇:xhost和DISPLAY


下一篇:CREATE DATABASE RoomReservation