前言
在刚学习SQL注入的过程中非常艰难,查资料的时间有一周这么长,点开的网页也不下一千,认真读的也最少有两百,可是能引导入门的真的没几篇,都是复制来复制去的,没意思,感觉就是在浪费时间。有很多知识点都很散,很少能考到一片吧所有知识点总结在一块,最少也要三四个知识点也好呀,可惜太少了,大部分大佬写的都是基于他们现有的技术写的,写的很笼统,不适合新手看。可以发现很多大佬的文章看不懂就是这个原因,没有基础看的很懵的。所以我就想着写两三篇来总结我学习过的SQL注入知识点。
学习web系列推荐先学习MySQL、HTML这两个知识点,先学会怎么使用先,看文章就会更明白,可以去菜鸟教程学,也可以去bilibil找视频学习。
前文学习
[CTF系列自学篇]一、CTF是什么
编辑不易,转载请联系说明用途,并标记作者姓名和文章来源!
MySQL简介
在学习SQL注入前先讲解一下MySQL到底是什么东西?有些人把SQL和数据库搞混,觉得SQL就是数据库,数据库就是SQL,为了让你更好的理解MySQL,你需要先理解 数据库 和 SQL 两个概念,你如果都懂,那你可以跳过这一段。
1、什么是数据库
我们每天都在不知不觉的用数据库。
- 当你想听你喜欢的歌曲,你打开你的手机中的曲目,其实你已经在用数据库了。
- 当你上传文件到百度云,你的百度云就是数据库。
- 当你在淘宝查询物品,你就是在使用淘宝的数据库。
数据库就是用来存放东西用的,就像冰箱,冰箱就是来储存食物的,食物就是数据,冰箱就是数据库。
是不是觉得跟平时存放数据的Excel表很像呀!对头,你可以认为数据库就是Excel表的升级版。
相对于Excel,数据库可以存放大量数据,又可以多人同时使用存放的数据。
举个栗子:excel好比是一个移动硬盘,你使用了这个移动硬盘其他人就用不了了。
数据库好比是网盘,很多人可以同时访问里面里的数据。
而且网盘比移动硬盘能放更多的数据。
2、什么是SQL
SQL,指结构化查询语言(数据库语言),全称是 Structured Query Language。SQL 让您可以访问和处理数据库。
SQL 是一种 ANSI(American National Standards Institute 美国国家标准化组织)标准的计算机语言。
SQL能做什么
- SQL 面向数据库执行查询
- SQL 可从数据库取回数据
- SQL 可在数据库中插入新的记录
- SQL 可更新数据库中的数据
- SQL 可从数据库删除记录
- SQL 可创建新数据库
- SQL 可在数据库中创建新表
- SQL 可在数据库中创建存储过程
- SQL 可在数据库中创建视图
- SQL 可以设置表、存储过程和视图的权限
3、MySQL是什么
MySQL由 My 和 SQL组成
MySQL是数据库管理系统,能够帮助你管理关系型数据库,并且是开源的,意味着这是免费的,如果必要,你可以修改源代码。
尽管MySQL是开源软件,你需要买社区版才能得到专项服务。
MySQL 对比Oracle和 SQL server 有非常大的优势。.
- MySQL 可以在几乎所有平台上运营UNIX, Linux, Windows,小到你可以安装服务器在自己的pc中,而且,可靠,可拓展,运行速度飞快。
- 如果你开发web或者webapp,mySQL 是明智的选择,因为他拥有LAMP堆栈, 包含Linux, Apache, MySQL, 和 PHP。
4、MySQL应该记住的内容
MySQL数据库
MySQL 是一个关系型数据库管理系统,由瑞典 MySQL AB 公司开发,目前属于 Oracle 公司。MySQL 是一种关联数据库管理系统,关联数据库将数据保存在不同的表中,而不是将所有数据放在一个大仓库内,这样就增加了速度并提高了灵活性。
- MySQL 是开源的,所以你不需要支付额外的费用。
- MySQL 支持大型的数据库。可以处理拥有上千万条记录的大型数据库。
- MySQL 使用标准的 SQL 数据语言形式。
- MySQL 可以运行于多个系统上,并且支持多种语言。这些编程语言包括 C、C++、Python、Java、Perl、PHP、Eiffel、Ruby 和 Tcl 等。
- MySQL 对PHP有很好的支持,PHP 是目前最流行的 Web 开发语言。
- MySQL 支持大型数据库,支持 5000 万条记录的数据仓库,32 位系统表文件最大可支持 4GB,64 位系统支持最大的表文件为8TB。
- MySQL 是可以定制的,采用了 GPL 协议,你可以修改源码来开发自己的 MySQL 系统。
引自:MySQL教程 | 菜鸟教程
什么是SQL注入?
SQL注入即是指web应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息。
什么是合法性的输入数据,就是正常的输入中文英文数字,而',@,#,$,%
这样的字符通常就是非合法
举个栗子:
<?php
$conn = mysqli_connect($servername, $username, $password, $dbname);
if (!$conn) {
die("Connection failed: " . mysqli_connect_error());
}
$username = $_POST['username'];
$password = $_POST['password'];
$sql = "select * from user where username = '$username' and password='$password';";
$rs = mysqli_query($conn,$sql);
if($rs->fetch_row()){
echo "成功";
}else{
echo "失败";
}
?>
以上的代码就是接受username
和password
这两个post进来的数据,将这两条输入插入已经编写好的SQL代码中,达到修改数据库数据的功能。
可是代码中没有对post数据(username
和password
)进行过滤或者判断,而是直接放进SQL代码中。
通常情况下用户输入的数据应该是username=admin
和password=123456
,这是SQL代码会变成:
$sql = "select * from user where username='admin' and password='123456'";
那么我们插入的数据就是为username=admin
和password=123456
。
可是输入的数据不是以上两个数据呢,比如我输入username=admin'#
和password=123456
,SQL代码会变成:
$sql = "select * from user where username='admin'#' and password='123456'";
这里的#是单行注释符,可以将后边的内容给注释掉。那么此条语句的语义将发生了变化,用户可以不需要判断密码,只需一个用户名,即可完成登录操作,这与开发者的初衷相悖。
还是不懂? 那我们用我练习时的数据库来演示一遍
首先查询一下数据库中a表的内容如下
我们用select * from a where username='admin' and password='123456';
查询发现只有一条,因为符合username='admin'
和password='123456
的只有一条。
但是,如果我们输入的是select * from a where username='admin' # ' and password='123456';
查询的条件就变成了username='admin'
这一个条件,而password='123456
被#
屏蔽了,后面的分号;
也被屏蔽了,可以看到下面它还需要我们输入一个;
才能结束语句才能搜索。
如果还不懂可以参照一下雪梅零落的文章
MySQL注入方式
在MySQL中,常见的数据处理操作有:增、删、查、改,这四样占了MySQL数据处理操作的90%。
而在SQL注入中查是第一步,也是不可或缺的一步,为什么呢?因为如果你没查,那就很难知道这条SQL语句有没有漏洞,漏洞在哪里,以及利用漏洞获取的数据怎么显示出来等问题。所以,查不可或缺,除非你是大佬。
查
在使用MySQL中会发现什么情况下都会有返回结果,哪怕是没有这条数据,也会有结果。在CTF中的大多都是用PHP调取MySQL来执行命令的,而在SQL注入在PHP页面中会有两种形态:有回显和无回显。
有回显
什么叫有回显?当你在浏览网页的时候,其URL为index.php?id=1
或者在搜索框里搜索的时候,这时的SQL代码可能为select * from index where id='$id'
。而这时页面显示了通过SQL代码返回的信息,这就叫做有回显。
那有回显的SQL注入有哪些呢?
联合查询注入
报错注入(部分人觉得是无回显)
无回显
什么叫无回显?在上面有个例子,成功则返回成功
,失败则返回失败
,这就是一个无回显的例子,因为只出现成功和失败,没有其它信息可以利用。还有一种是延迟无回显,只能通过时间来判断是否有注入点。
那无回显的SQL注入有哪些呢?
报错注入
盲注
- 布尔盲注
- 延时注入(时间盲注)
总结
注入位置
通常在web表单、url链接、登录框、搜索栏、留言板,其中留言板多是xxs注入。
常用
常用的是联合查询注入、报错注入、盲注
,其它的几个很少用的上,因为这几三种方法可以学习到数据库
的使用和利用的方法。
从时间成本上:联合查询注入<报错注入<盲注
。盲注是最耗时间的。
注入步骤
一、查看注入点
首先查看有没有可能出现注入点
bugku-成绩单,以下图片可以看到通过输入1,2,3就可以获得成绩,这可能就是我们注入的地方。
再例如bugku-sql注入2,可以看见登录框,一般这里也是个注入点。
例如墨者学院靶场的通告,可以发现上面的url中有个id=1
的内容,也可以通过这里进行注入。
二、判断注入点提交方式
GET注入
提交数据的方式是GET,注入点的位置在GET参数部分。比如有这样的一个链接 http://xxx.com/news.php?id=1
, id 是注入点,一般注入点是url为主。
POST注入
使用 POST 方式提交数据,注入点位置在 POST 数据部分,常发生在表单中,如登录框、搜索框之类的。
Cookie注入
HTTP请求的时候会带上客户端的Cookie, 注入点存在 Cookie 当中的某个字段中。这种情况可以在控制台中查看Cookie,查看的时候可以看一下是否与平常见到的Cookie有所不同。
HTTP头部注入
注入点在 HTTP 请求头部的某个字段中。比如存在 User-Agent 字段中。严格讲的话,Cookie 其实应该也是算头部注入的一种形式。因为在 HTTP 请求的时候,Cookie 是头部的一个字段。
总结
大部分都是GET注入和POST注入,只需要在url或则输入框中输入就好了,而Cookie注入和HTTP头部注入通常需要抓包才能修改,也很少能遇到这种情况。
三、必知的闭合和注释手段(判断是否可以注入)
闭合和注释
闭合
数字型不需要'
闭合,而字符型和搜索型则需要,而且需要研究好怎么闭合才不会报错。
注释
通常语句为select * from main username=$username and password =$password;
#
-- //后面需要空格
--+
在我们判断可以注入后,通常使用#
来进行注释后面的信息。如:select * from main username=admin #; and password =$password;
可以发现我们在输入username=admin
后输入#;
,后面的信息就不会执行了,就达到了绕过的效果。
判断是否可以注入
假如URL为http://www.xxx.com/index.php/id=X
,这时不知道是字符型还是数字型,字符型用引号大法,而数字型用and大法,都是在X
后面添加。
引号大法
在注入点后面添引号和注释'#
,一般用于字符型,利用三个引号导致SQL语句报错,使网页无法正常显示内容,这时就存在注入点。
and大法
在注入点后面分别添加and 1=1 #
和and 1=2 #
,一般用于数字型,在id用1=1
来使内容正确,而1=2
来使内容错误,对比一下就可以发现是否存在注入。
四、判断注入类型
无论如何分类如何多,都可以归纳为数字型和字符型形式。
数字型
猜测SQL语句为:select * from main where id=$id;
http://www.sql.com/xxx.php?id=1 假设ID为存在注入的参数
发现可以使用id=1就可以判断mysql语句为:
select * from users where id=1 +XX; XX为其它条件,不关此问题,所以后面用
http://www.sql.com/xxx.php?id=1' 用中文逗号使其语句报错(报错是为了判断是否为数字型)
http://www.sql.com/xxx.php?id=1 and 1=1 页面正常返回结果
http://www.sql.com/xxx.php?id=1 and 1=2 页面返回错误
字符型
猜测SQL语句为:select * from main where id='$id';
http://www.sql.com/xxx.php?id=1 假设ID为存在注入的参数
http://www.sql.com/xxx.php?id=1' 语句报错
发现可以使用id=1就可以判断mysql语句为:
select * from users where id='X' +XX; X为要输入的值,XX为其它条件,不关此问题,所以后面用
http://www.sql.com/xxx.php?id=1' and 1=1 and '1'='1 页面正常返回结果
http://www.sql.com/xxx.php?id=1' and 1=2 and '1'='1 页面返回错误
很多人不理解为什么第二步加个'
会报错,因为在猜测的SQL语句中最后面有一个';
,如果你输入的是单个1'
,那么SQL语句就会变成select * from main where id='1'';
,一个语句中怎么可能出现三个'
分号呢,这就是报错的原因,也是字符型容易漏掉的点。
搜索型
一个很少用得到的知识点。
猜测SQL语句为:select * from main where id=like '%k%';
http://www.sql.com/xxx.php?search=test 假设search为存在注入的参数
http://www.sql.com/xxx.php?search=test' 语句报错
输入后发现结果为%test%可以运行,就可发现有可能存在注入点
http://www.sql.com/xxx.php?search=test%' and 1=1 and '%'=' 页面正常返回结果
http://www.sql.com/xxx.php?search=test%' and 1=2 and '%'=' 页面返回错误
五、区分数字型和字符型
一般SQL语句无非就是以select * from users where id=AAA+XXX;
为基础进行修改的。
如select * from users where id="admin" and pass="123456";
或则select * from users where id=admin and pass=123456;
准备
环境:sql-libs-1
url为http://127.0.0.1/sqli-labs/less-1/index.php?id=1
猜测SQL语句为select * from users where id='1'+XXX;
或select * from users where id=1+XXX;
1.初始化
根据题目提示是让我们输入id,所以我们就以id=1
为基础开始
此时的url为http://127.0.0.1/sqli-labs/less-1/index.php?id=1
而我们猜测的SQL语句为select * from users where id='1'+XXX;或select * from users where id=1+XXX;
2.单闭合(判断是否需要单引号)
接下来,我们判断此SQL注入是基于数字型还是基于字符型。
在原始URL后添加单引号(’),此时页面显示错误,由此可见我们输入的单引号被后台数据库成功执行:
数字型
字符型
此时的url为http://127.0.0.1/sqli-labs/less-1/index.php?id=1'
而我们猜测的SQL语句为select * from users where id='1'' + XXX ;或 select * from users where id=1'+XXX;
3.双引号(判断为什么类型)
数字型
在原始URL后添加两个单引号(’ ‘),此时依旧页面显示错误,由此可见我们输入的两个单引号也被后台数据库成功执行:
此时的url为http://127.0.0.1/sqli-labs/less-1/index.php?id=1''
而我们猜测的SQL语句为select * from users where id=1'' +XXXXX;
字符型
在原始URL后面添加两个单引号(’‘),此时页面显示正常:
此时的url为http://127.0.0.1/sqli-labs/less-1/index.php?id=1''
而我们猜测的SQL语句为select * from users where id='1''' +XXXXX;
由于双引号中间为空,自动跳过,由此可以判断为字符型。
这里和上面的判断注入类型中的方法不同,个人喜欢用单引号来判断,如果不喜欢,也可以用上面的and 1=1 and '1'='1
之类的来判断什么类型
六、判断有无回显
利用上面的知识点来判断有无回显。(查中的有回显和无回显,判断是否可以注入)
七、确定注入方法
根据以上返回的信息选择需要使用的方法
联合查询注入
报错注入
延时注入
布尔注入
其实还有其它的注入,如:宽字节注入、堆叠注入、偏移注入、DnSlog注入、反弹注入等等
但归根结底都是原理相同的,一般掌握了联合查询注入、报错注入、延时注入、布尔注入做其他注入只需查看一下原理就懂了。
这部分将为每一方法单开一章。