本实验要求实验者具备如下的相关知识。

      SQL 注入是一种攻击方式,在这种攻击方式中,恶意代码被插入到字符串中,然后将该字符串传递到 SQL Server 的实例以进行分析和执行。任何构成 SQL 语句的过程都应进行注入漏洞检查,因为 SQL Server 将执行其接收到的所有语法有效的查询。一个有经验的、坚定的攻击者甚至可以操作参数化数据。

      SQL 注入的主要形式包括直接将代码插入到与 SQL 命令串联在一起并使其得以执行的用户输入变量。一种间接的攻击会将恶意代码注入要在表中存储或作为元数据存储的字符串。在存储的字符串随后串连到一个动态 SQL 命令中时,将执行该恶意代码。

      注入过程的工作方式是提前终止文本字符串,然后追加一个新的命令。由于插入的命令可能在执行前追加其他字符串,因此攻击者将用注释标记“—”来终止注入的字符串。执行时,此后的文本将被忽略。

    

      下面用一个简单的例子来详细阐述该产生过程。

      用户通过浏览器发出http://www.test.com/product.aspx?id=1连接请求,位于逻辑层的WEB服务器从文件系统中加载脚本并将其传递给解析脚本引擎,脚本使用数据库连接程序连接到存储层并对数据库执行SQL语句,数据库将查询到的数据返回给数据库连接程序并传递给脚本引擎。逻辑层执行相关业务逻辑规则或直接将web页面返回给表示层的web浏览器。所有操作会在数秒内完成,对于使用用户来讲是透明的。

      一个未经过滤的SQL查询程序段示例:

//查询字符串

string query = “SELECT * FROM Products WHERE id = ‘num’”;

//创建数据库连接

Database database = DatabaseFactory.CreateDatabase();

//创建查询语句

DbCommand sqlStringCommand = database.GetSqlStringCommand(query);

//执行查询

Result = databse.ExecuteQuery(sqlStringCommand);

 (在这一过程中query的值并没有进行判断,直接带入执行,导致漏洞产生)

//返回查询结果

return Result

     SQL注入过程示例:

     恶意构造的HTTP请求

     http://www.test.com/product.aspx?id=1 and 1=2

     由于没有对字段id的值进行判断,而这个值用户又可以操作,因此执行了下列查询

     SELECT * FROM Products WHERE id = 1 and 1=2;

     这段语句将不会执行返回id=1的商品信息,因为在查询的and操作数中1=2,1=2是不成立的,而and操作符的条件是只要有一个表达式为假,即返回假。因此执行这段查询后不会返回任何商品信息。

      盲注,意味着页面不会显示SQL语句的错误,要通过一定的手段来判断构造的注入语句是否正确执行。有两种方式:布尔型和时间型。布尔型是根据页面是否正确显示来判断构造的语句是否正确执行,时间型则是根据页面加载时间是否变化来判断的。

     盲注需要掌握一些MySQL的相关函数:

     length(str):返回str字符串的长度。如执行select

     length(database())则会返回当前数据库名称的长度。而单独select

     database()则回返回当前数据库的名称。

     substr(str, pos, len):从pos位置取出str字符串的len个字符。如

     select substring('abcde', 4, 2)则返回de,pos为负则倒数pos个位置,如select substring('abcde', -4, 2);返回bc。

     ASCII(str):返回字符串str的最左面字符的ASCII代码值。如果str是空字符串,返回0。如果str是NULL,返回NULL。如select ASCII('a')返回97。

     将上面几个函数组合一下就有布尔值出现。如

     Select ascii(substr(database(),2,1)) = 101;当database()即当前数据库的名称中,正数第二个字符为e,则会返回1,当为其他字符时会返回0。逐级替换2为其他数字,就可以逐字猜数据库名称了。其中的=号还可以换成<或者>。

     if ((exp1, exp2, exp3):为条件判断语句。当exp1的值为true时候,返回exp2,否则返回exp3。如  select if ((select database())='secur',sleep(10),null)即为判断当当前数据库的名字为secur的时候,数据库程序会休眠10秒。

     POST是HTTP/1.1协议中的一种资源请求方法。其向指定资源提交数据,请求服务器进行处理(例如提交表单或者上传文件)。数据被包含在请求本文中。这个请求可能会创建新的资源或修改现有资源,或二者皆有。很大一部分的表单都是通过POST方式发送到处理页面的。

     http header信息头是HTTP协议的重要组成部分,包含了一数据段来于服务器进行通信。这里主要是利用三个:UA、X-Forwarded-For和Referer。UA是包含了操作系统版本,浏览器版本信息的一组字符串,很多网站用他来判断操作系统和浏览器类型,来展示对应的页面。也有很多通过UA来判断访问是否合法,是用户访问还是程序访问等。

     X-Forwarded-For被认为是客户端通过HTTP代理或者负载均衡器连接到web服务端获取源ip地址的一个标准。部分网站通过它来辨别访问者的IP信息。Referer是来源信息,在防盗链中使用广泛。HTTP(HyperTextTransferProtocol)即超文本传输协议,目前网页传输的的通用协议。HTTP协议采用了请求/响应模型,浏览器或其他客户端发出请求,服务器给与响应。就整个网络资源传输而言,包括message-header和message-body两部分。首先传递message- header,即http header消息 。http header 消息通常被分为4个部分:general header, request header, response header, entity header。但是这种分法就理解而言,界限不太明确。


0x00
  1)打开桌面上的火狐浏览器,在“GET注入-显错注入”下找到“GET - 基于错误 - 单引号 - 字符型”,根据提示完成注入。关键代码为:

$id = $_GET['id'];

$sql = "SELECT * FROM users WHERE id='$id' LIMIT 0,1";

     构造语句显示所有的用户名和密码:%27 union select * from users --+