• 欢迎访问小澍的博客,编程记录,技术贴以及折腾的日常,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏我的博客吧

7.17 SQL注入基础与实战

PTE课程实录 root 1年前 (2019-07-17) 450次浏览 已收录 0个评论

Day 02

按照今日进入了SQL注入环节(基于MySQL),注入作为OWASP Top10中的 top1, 足以窥见其对安全的危害程度,挖到了数据就具有了无限价值,而SQL注入的目的就是要尽可能的将目标服务器数据库的数据全部挖掘出来,所以无论进行怎样的研究都是不过分的,今日的培训给很多人打开了新世界的大门,借着这次培训,我系统的来梳理一下SQL注入的基础以及实战环节。

sql 注入需要的基础知识

常用的一些SQL语句(基于MySQL)

想要实现注入操作,首先需要知道如何对数据进行操作,我们读者已经知道了基本的增删改查操作,常见的一些命令如下,对于一些语句我进行了注释,就不再额外进行解释了:

select database(); //用于查询当前正在使用的数据库名称
show databases; //终端中用于显示本地(服务器)所有的数据库名称
select count(*) from any_table_name;//计算指定的表中有多少行
select rand();//生成一个0-1的随机数
select floor(2.333);//取整,输出2
select floor(rand()*2) a;  //给构造查询起一个名字a
select concat(1,2,3) ;// 直接拼接  输出123
select* from xxxx into outfile "文件路径"; //查询结果放入指定文件中
select * from xxxx into dumpfile "文件路径";//查询结果放入dumpfile
select load_file("路径"); //显示读取的文件
select length(database()); //查看指定字段的长度,这句话就是看数据库名字段的长度
select substr(database(),startpoint,num);// 将指定字段从指定指定位置截取num个字符作为显示结果
select assic(substr(database(),startpoint,num));//显示指定字符的assic码
select sleep(10); //休眠10秒
select if((select database())="name",true_action, false_action)// if逻辑,真值执行true_action,假值执行false_action

在进行集训的时候,一些之前没有学过SQL的同学对这些命令晕头转向,诚然,这么多命令没有使用价值,就是一些废话,你可以看一下,继续下面的阅读,谈及一些原理的时候才需要这些语句;

MySQL的特点

自带的数据库

在自带的数据库中,自带了一个叫做 information_schema的数据库,它提供了访问数据库元数据的方式。元数据(meta data)又称中介数据、中继数据,为描述数据的数据(data about data),主要是描述数据属性(property)的信息。所以你可能猜到了,这些为了描述数据的数据所包含了什么内容,那就是关于MySQL服务器所维护的所有其他数据库的信息。如数据库名,数据库的表,表栏的数据类型与访问权限等。
我们将要用到这里的表是tables,columns,这两个表分别存放了所有的数据库中所包含的所有表名,以及对应表名中所包含的字段名称。

可嵌套执行的sql语句以及无意义语句执行原则

在MySQL中,语句只要无语法错误,均可执行且具备回显功能,比如:
blob.jpg
至于嵌套,你看一下上面的第6行语句就明白了。

这就是今天所有的基础内容,我相信你已经知道了如下几点信息:
1. MySQL 可以通过自带的数据库来查询其他数据的信息;
2. 只要语法不出错,MySQL都会回显消息,在这里强调一点,在嵌套语句中,全局逻辑出现错误导致不可执行的时候,但局部语法依旧有效的情况下,依旧可输出,这个概念在后面会用到。

下面进入实战环节

Experiments and Analysis

环境准备

令人感动的是,集训也使用了著名印度小哥开发的sqli-labs,关于配置环境可以看这里,比较推荐docker,方便,轻量。
同时,浏览器装一下hackbar(必备),这个已经是收费的了,这里就不放之前残留的免费版了,自行搜索一下吧。

实战 less1

注意:过程采用黑盒方式,即在不知道网页源代码的情况下进行完整测试。
1. 进入less-1,黄字提示:Please input the ID as parameter with numeric value ,这里需要常识,即入口,提示已经说了id是一个入口,那么在url后面直接构造?id =1 出现输出:
blob.jpg
通过更改数字,会发现可显示到不同的数据,我们可以确定这个地方可以注入
2. 确定这个语句的闭合方式,所谓闭合,即我们输入的id值在填充到后台中的sql语句中后整个语句的格式,这里我们可以看一下less-1的源码中关于sql语句构建的代码:

$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);

可以看到,我们构造的?id=1里的1其实是作为id输入进了sql中,$id 使用了一个 ”包裹起来,这个就是对变量的闭合,而如果我们在构造url的时候直接进行闭合,则可以可以写成 ?id =1′ ,这个时候对于源语句来说,就多出了半个单引号,我们需要使用注释符 –,来注释掉剩下的’,所以当我们使用了?/id=1′–+ (+代表空格),提供给后台的代码就变成了

SELECT * FROM users WHERE id='1'

现在你知道什么叫闭合了,你还是要假装不知道后台的闭合方式,常见的闭合方式可能是”,””,(”),(“”),一般情况下,确定其闭合方式可以依靠猜测或是转移字符\,我们输入?/id=1\发现下面的提示:
blob.jpg
看到圈出来的1\’ 了么?那个’实际上就是源代码中sql语句$id的后半个引号,如果网站没有对转义字符进行过滤,我们就看可以直接使用这种办法知道如何进行闭合了。在less-1中,我们确定了闭合方式是单引号闭合。
3. 确定闭合方式后,我们可以在闭合后衔接我们的sql语句来开始注入攻击。通过 union select构建语句。但是联合查询语法要求union 前的select列数和union select后面的查询列数必须一致。我们知道,当前网页一定与某个数据库中的某个表在进行交互,但我们在前端网页只看到他输出了这个表中的两列数据,但我们并不能确定这个表就只有两列,所以为了使用联合查询,我们首先要知道这个表一共有几列,我们给SQL语句加order by num来按照num列出来。首先尝试order by 5:
blob.jpg
这样显示就代表实际没有5列,我们尝试3,发现输出恢复,尝试4继续报错,所以我们就可以确定,正在交互的表一共有三列,所以在union select 后面查询保证查三列即可,构造语句 union select 1,2,3同时将前面的id替换为无效查询值:
blob.jpg
输出显示出了union select中的2,3,说明后台查询的是这个表的第二列和第三列,所以接下来我们也要在2,3中进行改动来显示我们需要的数据
4. 确定后台正在使用的数据库名,看见这个,你是不是能想起来刚才给出的命令?使用第一条就可以了,这一步很简单,对不对?:
blob.jpg
看到那个security了吗?从这一步开始,你就已经知道了作为一个正常用户不应该知道东西了,俗话说牵一发而动全身,无论是什么形式的注入,如果到了这一步能够成功执行,即已经可以通过某种手段来获知数据库元数据信息,就可以算注入成功了,不过作为培训,我们继续。。
5. 确定该数据库中所包含的所有表名,你是不是还记得刚才我们提过的information_schema这个数据库呢?我们已经拿到了security的库名,查询表名就非常容易了,在这里给出查询的语句:

select table_names from information_schema.tables where table_schema = 'security';

使用这个来构造url:
blob.jpg
但是一个库中只有一个表不太现实吧?这是因为数据需要按行输出,而这里只有一行,所以我们只能看见一行,使用group_concat函数,将所有结果全输出:
blob.jpg
6. 你应该已经知道下一步是什么了,是的,确定每个表中的字段名,代码如下:

select column_name from information_schema.columns where table_schema='security' and table_names = 'emails';

借助这个语句与group by,我们来爆破emails表格中的字段名:
blob.jpg
7. 对于一个表的最后一步,就是一句查询了,表名,字段名我们都知道了,当然可以为所欲为了:
blob.jpg
以上就是基础的注入流程了,简单总结一下7个步骤的流程,前四部是SQL注入的重中之重,寻找注入点,确定闭合方式(也可以理解为确定后台SQL语句构成),缺点查询列数,确定可执行的注入方式。

实战less-5(error-based)

less1-4的流程基本是一样的,只要确定闭合方式后就可以,到了less-5,发现执行id=1后,没有显示输出,所以我们需要新的注入方法,根据题目提示(进入网页前的题目介绍,我们需要报错注入),报错注入的原理即,根据错误提示来获取信息,这么说有点笼统,一般的方法是使用随机数rand() 取整进行比较操作来进行,就是我们一开始给出的第6个语句。在MySQL中,排序必须保证每一行数据是不同的,否则报错,报错的输出会给出重复的键值,而键值就可以作为输出给我们提供信息。步骤如下:
1. 确定闭合方式为”闭合
2. 构建基于随机数的报错语句:

select 1 from (select count(*),concat(0x3a,0x3a,(select database()),0x3a,0x3a,floor(rand()*2))a from information_schema.tables group by a)b

解释一下,a和b分别给前面的一大串代码起了给别名,所以上面的内容实际是这么个结构:

select 1 from b
//b中的结构是:
select count(*),a from information_schema.tables group by a

这样一分解就比较清楚了,也就是我们核心的操作是统计了tables的行数以及按照行数生成了这么多个随机数并取整,rand()范围是0-1,加倍后取整的值是0或1,由于数量是上百个,所以一定有重复的,所以这样构建url后,输出:
blob.jpg
看到那个熟悉的security了吗?后面的步骤就重复前面less-1的步骤就好了

less-8,9

第8题使用的是布尔注入,解释一下原理,报错不起作用后,正常输入是you are in,非正常输入不显示数据,所以可以根据这个特点,可以这样使用:
问:数据库名称第一个字符是不是a?
答:不是
问:是不是b?
答:不是
long time ago…
问:是不是s?
答:是
就这样,我们就可以确定了字符,语句是这样的:

select ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)))<105

我们使用assic来进行比较,用到的命令是11-13,15,用这个来构造URL:
blob.jpg

less 10 时间盲注

使用命令14,可以抽象成这样的原理:
问:如果数据库名第一个字符是a,你等10秒答复
答:好(用时0.1秒)
long time ago…
问:如果数据库名第一个字符是s,你等10秒答复
答:好(用时10.1秒)
这就是时间盲注了,所谓盲,我想你已经理解了,通过现象确定具体就是盲注。
使用的语句:

if((select database())="security",sleep(10),null) 

当然,这有点作弊了。。我们实现怎么可能知道一个词呢哈哈哈
blob.jpg

END

以上就是今天培训所涉及到的内容了,虽然之前已经学习和使用过,但是不得不说,手工注入虽然原始且不会在实操中使用,但是精通手工过程,我们可以根据原理来自己造轮子,对于别人的轮子也可以用的稳稳当当,明天见~

reference

[1] 什么是元数据:百度百科
[2] Mysql数据库自带四个数据库的解析


XiaoShuBlog , 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:7.17 SQL注入基础与实战
喜欢 (2)
[gaosirgoo@foxmail.com]
分享 (0)
发表我的评论
取消评论
表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址