vlambda博客
学习文章列表

sql注入基础知识入门

好久没更新推文了= =实属太懒了,最近在学习渗透测试方向的一些东西,对sql注入部分的基础知识做一个简单的笔记记录~

something just like this From 云去吾不归 04:07



1、 相关概念

SQL注入指的是攻击者通过构造特殊的sql语句,作为参数传入到web应用程序中,入侵目标系统,致使后台数据库泄露数据的过程,其主要原因是程序没有细致地过滤用户输入的数据,致使非法数据侵入系统。

2、 相关危害

在owasp年度top 10 安全问题中,注入高居榜首对于Web应用程序而言,这是因为用户核心数据存储在数据库中,例如MySQL、SQL Server、Oracle;通过SQL注入攻击,可以获取、修改、删除数据库信息,并且通过提权来控制Web服务器等其他操作。

3、  SQL注入流程、

(1) 判断是否有SQL注入漏洞;

(2) 判断操作系统、数据库和web应用的类型;

(3)获取数据库信息,包括管理员信息及拖库;

(4) 加密信息破解,sqlmap可自动破解;

(5) 提升权限,获得sql-shell、os-shell、登录应用后台;

4、  相关环境配置

本次学习使用的目标靶机是OWASP,

由于黑底白字的画面让我实在有点适应不过来,跟着教程用了Xshell远程连接了靶机,这样就可以复制粘贴了= =

sql注入基础知识入门

用IP远程连接好目标靶机后,现在就是进入靶机设置了,先从最低级的SQL注入开始,OWASP对每个类别漏洞都提供了三个级别的安全等级,可以一步一步来。Web直接输入连接,进入可视化界面设置:

sql注入基础知识入门

看到左下角显示了用户名还有相关的安全等级,右下角View Source是可以查看源码的。这个源码指的是用PHP编写的后端源码,一般人访问网站是无法查看到WEB的后端源码的,最多只能看到用HTML编写的前端语言。OWASP为了方便学习,直接将网页的后端源码提供了。。。

sql注入基础知识入门

可以看到,该网页提供了一个输入端口,我们可以通过输入数字来获取信息,输入1查询到了用户的名字,这种数据库的操作就类似于我们平时上淘宝、京东等网购软件,搜索栏查询商品信息等。

 

sql注入基础知识入门

点右下角View Source查看该WEB后端源码是如何编写的。

sql注入基础知识入门

可以看到源码中是采用mysql中的select语句来获取输入id,并进行查询:

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

对应到我们靶机的mysql库里面,我们可以看到:当我们输入1,相当于执行了下述语句

SELECT first_name, last_name FROM users WHERE user_id = '1'

sql注入基础知识入门

如上图所示,进入dvwa库后,输入上述指令返回的的确是我们之前在web前端上看到的admin用户。

 

(1)判断是否有sql注入漏洞——错误试探

之前有提到过一般性的网站是无法让我们查看到网页后端编写的源码的,前面的OWASP我们可以通过直接查看源码判断是否有注入漏洞。下面我们先进行错误试探,即输入一个单引号‘,查看它是否报错。如果输入单引号报错,则证明包含有漏洞,如果其报错输入包含有语法错误,则明确告诉我们它使用的语法中将单引号用上了,证明web有sql注入漏洞点。

实际操作当我们输入单引号后,可以看到页面返回报错:

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''''' at line 1


(2)布尔注入

在前面我们看到了web的后端源码:$getid = "SELECT first_name, last_name FROM users WHERE user_id = '$id'"

对于我们来说,sql语句本身是无法改变的,但我们可以顺应他的漏洞,改变输入,以此来达到我们攻击的效果,例如布尔逻辑注入的思路,即构造or、and等逻辑语句,注释掉多余的代码。

因此,我们可以将输入的之前输入的1,改变为:‘ or 1=1 --zhangyan

sql注入基础知识入门

从上图可以看到,改变了输入后,我们竟然可以获取到数据库所有的用户ID。上述的过程在靶机数据库上的体现,就相当于执行了如下语句

sql注入基础知识入门

可以看到,当我们改变输入为‘ or 1=1 –zhangyan‘后,第一个单引号相当于闭合前面部分的条件,OR后面1=1条件恒成立,后面的—相当于注释掉后面的代码,这样就形成了一个攻击语言,mysql数据库执行后展示语句前面first_name, last_name等信息。虽然这样可以得到sql语句所写表里面的所有信息,但其无法获取其他表的信息,因为select已经指定了获取的只有first_name, last_name等字段。如果布尔注入能获取的信息不是我们关心的,我们如何获取其他库中其他表的信息呢?后面就要用到union注入。


(2)基于union的注入

前面布尔注入只能获取事先写好的sql语句中的指定库和表,假设我们要获得当前用户以及当前库的信息,则可将输入修改为

'  union select user(),database()  -- '

如下图,我们得到了当前用户名为dvwa靶机、当前库为dvwa

sql注入基础知识入门

在xshell中相当于执行了下述语句

可以看出,虽然事先编写的sql语句中已经指定了获取的库和表信息first_name, last_name,但我们通过在后面增加了union select,获取到了数据库内其他库和表的信息。该方式即为联合查询union。

union查询中有个规定条件是,后续我们输入的union select查询的字段数必须和前面sql语句编写的字段数一样。当前后字段数不一样时,就会报错,我们测试将输入修改为'  union select user() – ‘,只查询了user这一个字段,由于前后数量不一致进而导致了下述报错:

The used SELECT statements have a different number of columns

 

这样uinion联合查询便遇到了两个问题:我们如何知道前面有多少个字段呢?后面该如何补上相同数量的字段?

针对第一个问题,对于一般的web,我们是无法知道其后端编写的php源码的,更不用谈如何知道前面查询了多少个字段,这样我们则需要手动进行补充来测试,简单点我们可以修改输入为

‘  union select  1 – ’

‘  union select  1,2 – ’

‘  union select  1,2,3 – ’

这样一步一步往下试,我们可以看到试到第二个就不会报错了,这样试出来前面字段数后,我们再修改需要获得的库、表字段名即可。

当我们要查询的库和表数量少于前面字段数时,我们可以在后面直接添加数字来补充即可,但当我们要查询的库或表数量大于前面字段数时,我们可以通过concat来进行分组整合。

 

sql注入后续的学习笔记会继续更新的~(勤快点的话 战术性划水)