SQLi-Labs(Basic Challenges)
- 本篇文章参考自:
lcamry
的博客 - https://www.cnblogs.com/lcamrylcamry
的文章 - https://files.cnblogs.com/files/lcamry/mysql-injection.pdf(MySQL
注入天书)- 国光的文章 - https://www.sqlsec.com/2020/05/sqlilabs.html
注:这里引用自 lcamry 的前言,简单修改了一下,也比较符合自己的处境。
前言
- 最初看到
SQLi-Labs
也是好几年之前了,依稀记得是在2019
年,那时候玩了前面的几个关卡,就没有继续下去了。 - 前几年又因为夯实基础,回头把
SQLi-Labs
刷完了,并写成文档放在了语雀上。 - 最近因某种原因有需要用到
SQLi-Labs
,所以翻出来看了一下。看着熟悉的代码,仿佛看着当初刚学安全的自己。 - 当初学习安全老累了,网上能找到的资料并不多,不像现在这样的信息爆炸。前几天迪总为了打击盗版,还把自己的课公开了,以前哪有这种好事儿。大伙都是藏着掖着,也很正常,正所谓教会徒弟饿死师傅。
- 最近也是脑门一热,决定在自己的教学生涯上留下点东西(或许糟粕或许精华),决定将通过攻略写到博客上,方便查看。
- 本来还想着录课传
B
站,但近期课也多。其次,按照B
站现在的视频数量,播放量堪忧,吃力不讨好。 - 本篇文章主要是利用课余时间和工作之外时间来写的,时间会比较的仓促,同时个人实力有限,望各位批评指正。
- 最后希望能对后面参考该文档的人有帮助,不枉此作。
为什么要写?
SQL
注入攻击并不是新的攻击手法,它最早出现在1990
年代末,随着Web
应用程序和在线数据库的广泛应用而出现。尽管安全研究人员和开发者们已经花费了大量的时间和资源来防止这种攻击,但是由于许多因素,包括开发人员的安全意识不足、复杂的代码库以及不断变化的攻击技术,SQL
注入仍然是一种常见且危险的攻击手法。- 现在我们还可以在各大 SRC 平台看见 SQL 注入的身影:
- 很多的人觉得
SQL
注入是如此的简单,同时大部分人都是眼高手低的。 - 对
SQL
注入的理解到底有多深,决定了你对此漏洞的利用方式有多么变幻莫测。 - 当然了,
SQL
注入涉及的内容非常非常之多,我感觉这个内容完结至少要写10W+
字。 - 最后,以前的自己在学习
SQL
注入的时候真的太过于痛苦,大部分的人入门的时候通过SQL
走进来。 - 这也造就了一种现象:
- 面试官:你熟悉哪些
Web
漏洞? - 面试者:
SQL
注入! - 面试官:讲一讲
SQL
注入的原理、分类、修复方案。 - 面试着:
emmmmm
,好像也不是很熟。
- 面试官:你熟悉哪些
- 同时,
SQL
注入的世界真的很精彩,当你看到别人用智慧构成的Payload
时,你会感触颇多。 - 所有学习是什么?通过掌握所学,形成自己的漏洞理解和利用方法,而不是生搬硬套。
- 此处希望通过该文档帮助到正在学习
SQL
注入的人。
如何去完成?
- 平时工作也忙,不知道有没有时间和精力能够写完,毕竟写文档相对于录课来说会麻烦很多。
- 借鉴
lcamry
大佬的思路,可以将其分为三个部分:- 源码分析:通过源码和手工的方式,将所有的注入方式和造成漏洞的原因找出来,并进行学习。此处要求是对每一个类型的注入进行“深刻”的了解,了解其原理和可能应用到的场景。
- 工具使用:通过工具进行攻击,我们此处推荐使用 SQLmap。此过程中,了解 SQLmap 的使用方法,要求掌握 SQLmap 的流程和使用方法,精力较足的话,针对一些问题会附 SQLmap 的源码分析。
- 自动化利用:自己实现自动化攻击,这一过程我们根据常见的漏洞,自己写脚本来进行攻击。此处推荐 Python 语言。同时 SQLi-Labs 系统是 PHP 写的,这里个人认为可以精读一下每关的源码,同时针对有些关卡,可以尝试着添加一些代码来增强安全性。
该怎么去学?
- 大致可以分为如下三点,这也学习任何技术都需要的:
- 动手实践:实践是检验真理的唯一标准,这句话可以应用在任何场景
(除了益生菌,哈哈哈)。安装环境后动手实验,实践中遇到问题才能更大的激发起兴趣。 - 查找资料:遇到不会查资料,或者可以请教别人,虚心请教,不耻下问,所谓三人行必有我师焉!
- 努力勤奋:书山有路勤为径,学海无涯苦作舟,勤奋是最快的一条路也是唯一的一条路。
- 动手实践:实践是检验真理的唯一标准,这句话可以应用在任何场景
需要哪些能力?
SQL
注入毕竟是新手的第一道门槛,要求内容不多:PHP
语法:了解简单的PHP
语法,并会连接MySQL
数据库;HTTP
协议:了解HTTP
请求与响应流程;SQL
语法:了解MySQL
增删改查的语法;- 常见工具使用:
BurpSuite
、Hackbar
、Proxy
、Docker/PhpStudy
。
准备工作
Firefox + Hackbar + Proxy
- 毕竟是
Web
服务,还是需要有个浏览器的,之所以没写Chrome
是因为,Chrome
的插件安装需要科学上网,比较麻烦。 Hackbar
安装可以参考文章:Hackbar 安装。Proxy
安装可以参考文章:BurpSuite & Firefox 代理配置。
BurpSuite
- 学安全的不知道
BurpSuite
说不过去,参考文章:BurpSuite 版本破解使用。
SQLi-Labs
SQLi-Labs 介绍
SQLi-Labs
是一个用于学习和实践SQL
注入攻击的靶场,旨在提供一个安全的环境,供安全研究人员、学生和开发人员进行SQL
注入攻击和防御的实践。它包含了一系列具有不同难度级别的漏洞场景,以帮助用户逐步学习和理解SQL
注入攻击的原理、技术和防御方法。- 以下是一些 SQLi-Labs 靶场的特点和介绍:
- 漏洞场景:
SQLi-Labs
提供了多个漏洞场景,每个场景都涵盖了不同类型的SQL
注入漏洞。这些场景包括基于GET
和POST
请求的注入、盲注、时间延迟注入等等。每个场景都有相应的漏洞描述、目标和任务。 - 难度级别:
SQLi-Labs
提供了多个难度级别,从简单到复杂。初学者可以从简单的注入场景开始,逐渐提高难度,以提高对 SQL 注入攻击的理解和技能。 - 安全环境:
SQLi-Labs
是为了学习和实践目的而设计的,提供了一个安全的环境来进行SQL
注入攻击。用户可以在该环境中进行实验和测试,而不会对真实系统造成任何损害。
- 漏洞场景:
SQLi-Labs
是一个印度程序员老哥写的,博客地址为:https://dummy2dummies.blogspot.com/,以现在的眼光去看,博客稍微有点简陋。同时作者自己也录制了一套对应的演示视频,但口音有点奇怪,哈哈。- 个人接触的
SQLi-Labs
靶场有两个:- 正统:https://github.com/Audi-1/sqli-labs,但是不支持
PHP7
。 - 修订:https://bitbucket.org/SevenBy/xface_sqli_labs/src/master/,支持
PHP7
。 - 自改:https://github.com/Y0n9zh/sqli-labs_php7,将
PHP7
版传到了GitHub
上。
- 正统:https://github.com/Audi-1/sqli-labs,但是不支持
SQLi-Labs 安装
SQLi-Labs
搭建的几种方式:- 本地搭建:
PhpStudy + SQLi-Labs
- 好处:搭建快速,也不需要进行多么复杂的操作,基本相当于傻瓜式安装了。
- 坏处:现在谁的服务还搭在
Windows
上(狗头),多熟悉熟悉Linux
操作吧。
- 虚拟机搭建:
CentOS + BT + SQLi-Labs
- 好处:这套搭建模式可以在云服务器上套用,也是个人安装博客的大致流程,重点宝塔自带有
PHP Xdebug
插件,可以进行动态代码调式,深入理解漏洞成因。 - 坏处:搭建巨麻烦,没点基础安装不来。
- 好处:这套搭建模式可以在云服务器上套用,也是个人安装博客的大致流程,重点宝塔自带有
- Docker 搭建:
Docker + SQLi-Labs
- 好处:搭建极其快速,等同于一键启动。
- 坏处:代码调试,极其麻烦
(Win Docker + VScode 当我没说)。
- 本地搭建:
- 这里使用
Docker
搭建:
1 | docker run -itd --name sqli-lab -p 80:80 acgpiano/sqli-labs:latest |
- 修改下本地的
hosts
文件,避免后续IP
地址变动:
1 | root at kali in ~ |
- 如图所示(记得创建数据库):
SQLi-Labs(Basic Challengs)
Less-1*
HTTP 请求方式 | 可注入类型 | SQL 拼接方式 |
---|---|---|
GET |
联合、报错、盲注 | id = '$id' |
- 源码简单分析:
1 | # 单引号拼接 |
- 一个非常简单的
SQL
查询语句,没有做任何的过滤直接拼接。 - 第一关可尝试的
SQL
注入方式基本覆盖全了,这里主要演示一下联合/报错注入,后续相似的题型不会详述。
联合查询注入
1 | # 判断闭合 |
报错注入
MySQL
中的报错函数有很多,依次尝试哪个能有就行,这里使用updatexml
进行演示。
1 | # 判断闭合 |
SQLMap
- 这里可以使用
SQLMap
直接进行注入,命令如下:
1 | root at kali in ~ |
Less-2
HTTP 请求方式 | 可注入类型 | SQL 拼接方式 |
---|---|---|
GET |
联合、报错、盲注 | id = $id |
- 和
Less-1
利用方式一致,只是闭合方式不一样而已,这里不再阐述。
Less-3
HTTP 请求方式 | 可注入类型 | SQL 拼接方式 |
---|---|---|
GET |
联合、报错、盲注 | id = ('$id') |
- 和
Less-1
利用方式一致,只是闭合方式不一样而已,这里不再阐述。
Less-4
HTTP 请求方式 | 可注入类型 | SQL 拼接方式 |
---|---|---|
GET |
联合、报错、盲注 | id = ("$id") |
- 和
Less-1
利用方式一致,只是闭合方式不一样而已,这里不再阐述。
Less-5
HTTP 请求方式 | 可注入类型 | SQL 拼接方式 |
---|---|---|
GET |
报错、盲注 | id = '$id' |
- 源码简单分析:
1 | $sql = "SELECT * FROM users WHERE id='$id' LIMIT 0,1"; |
- 查询成功后显示固定的字符串,这就导致不可以使用联合查询的注入方式,但是并不影响正常使用报错、布尔盲注和延时盲注。
- 和
Less-1
利用方式一致,可以参考报错注入,这里不再阐述。
Less-6
HTTP 请求方式 | 可注入类型 | SQL 拼接方式 |
---|---|---|
GET |
报错、盲注 | id = "$id" |
- 和
Less-1
利用方式一致,只是闭合方式不一样而已,可以参考报错注入,这里不再阐述。
Less-7
HTTP 请求方式 | 可注入类型 | SQL 拼接方式 |
---|---|---|
GET |
盲注 | id = (('$id')) |
- 源码简单分析:
1 | $sql = "SELECT * FROM users WHERE id=(('$id')) LIMIT 0,1"; |
- 和
Less-5
不同之处在于将原始报错信息改为了固定报错信息,所以就不可以使用报错注入了,这个时候只能使用布尔盲注和延时盲注,后续相似的题型不会阐述。
布尔盲注
- 布尔盲注非常的麻烦,一般是采用如
SQLMap
的自动化工具或BurpSuite
的半自动工具,这里只做当前库名的演示。
1 | # 判断闭合 |
时间盲注
- 时间盲注更加的麻烦,一般是采用如
SQLMap
的自动化工具或BurpSuite
的半自动工具,这里只做当前库名的演示。
1 | # 判断闭合 |
文件读写
- 虽然可以使用盲注完成,但本关的标题是
dump into outfile
,意思是本关我们利用文件导入的方式进行注入。 - 命令如下:
注:虽然说不能进行联合查询注入,但是文件读写也只有在联合查询注入下才能完成。
1 | ?id=1')) union select 1,2,load_file('/etc/passwd') --+ # 读取 /etc/passwd 文件,不回显没啥用 |
- 权限问题解决:
1 | 进入容器 |
SQLMap
- 这里可以使用
SQLMap
直接进行注入,命令如下:
1 | root at kali in ~ |
- 也可以使用
SQLMap
进行文件写入:
1 | root at kali in ~ |
Less-8
HTTP 请求方式 | 可注入类型 | SQL 拼接方式 |
---|---|---|
GET |
盲注 | id = '$id' |
- 源码简单分析:
1 | $sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1"; |
- 和
Less-7
不同之处在于查询成功不返回字符串了,利用方式一致,只是闭合方式不一样而已,这里不再阐述。
Less-9
HTTP 请求方式 | 可注入类型 | SQL 拼接方式 |
---|---|---|
GET |
时间盲注 | id = '$id' |
- 源码简单分析:
1 | $sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1"; |
- 和
Less-7
不同之处在于不论查询成功或者失败都是返回同样的字符串,所以就不可以使用布尔盲注了,可以参考时间盲注,这里不再阐述。
Less-10
HTTP 请求方式 | 可注入类型 | SQL 拼接方式 |
---|---|---|
GET |
时间盲注 | id = "$id" |
- 和
Less-9
利用方式一致,只是闭合方式不一样而已,这里不再阐述。
Less-11
HTTP 请求方式 | 可注入类型 | SQL 拼接方式 |
---|---|---|
POST |
联合、报错、盲注 | username = '$uname' |
- 源码简单分析:
1 | $uname=$_POST['uname']; |
- 一个简单的后端接收的
PHP
代码,和Less-1
不同之处在于由GET
型变成了POST
型。
万能密码
- 由于这里涉及到用户登录,所以可以尝试万能密码:
注:万能密码种类很多,这里只简单写几个。
1 | # 已知用户,不知密码 |
注:这是一个 POST 型注入,表单提交时会自动进行 URL 编码。
SQLMap
- 这里可以使用
SQLMap
直接进行注入,有以下三种方式:-r
:指定HTTP Response
文件;--data
:指定HTTP
请求体数据内容;--form
:寻找表单提交参数。
- 命令如下:
1 | root at kali in ~ |
Less-12
HTTP 请求方式 | 可注入类型 | SQL 拼接方式 |
---|---|---|
POST |
联合、报错、盲注 | username = ("$uname") |
- 和 Less-11 利用方式一致,只是闭合方式不一样而已,这里不再阐述。
Less-13
HTTP 请求方式 | 可注入类型 | SQL 拼接方式 |
---|---|---|
POST |
报错、盲注 | username = ('$uname') |
- 源码简单分析:
1 | $uname=$_POST['uname']; |
- 因为没有输出查询后的信息的原因,所以相对于
Less-11
来说就少了联合查询的注入方式,这里不再阐述。
Less-14
HTTP 请求方式 | 可注入类型 | SQL 拼接方式 |
---|---|---|
POST |
报错、盲注 | username = "$uname" |
- 和
Less-13
利用方式一致,只是闭合方式不一样而已,这里不再阐述。
Less-15
HTTP 请求方式 | 可注入类型 | SQL 拼接方式 |
---|---|---|
POST |
盲注 | username = '$uname' |
- 源码简单分析:
1 | $uname=$_POST['uname']; |
- 相较于
Less-13
将报错信息也给注释了,所以相对于Less-13
来说就少了联合查询的注入方式,这里不再阐述。
Less-16
HTTP 请求方式 | 可注入类型 | SQL 拼接方式 |
---|---|---|
POST |
报错、盲注 | username = ("$uname") |
- 和
Less-15
利用方式一致,只是闭合方式不一样而已,这里不再阐述。
Less-17
HTTP 请求方式 | 可注入类型 | SQL 拼接方式 |
---|---|---|
POST |
报错、盲注 | password = '$passwd' |
- 源码简单分析:
1 | $uname=check_input($_POST['uname']); |
select
语句只查询了uname
参数,但是被gpc
过滤了。- 而后发现
update
语句使用单引号拼接了passwd
,但因为没有打印数据所以不能使用联合查询注入。 - 因为输入了报错日志,所以是可以进行报错注入的,前提是账号存在的情况。
报错注入
1 | # 判断闭合 |
SQLMap
- 这里可以使用
SQLMap
直接进行注入,命令如下:
1 | root at kali in ~ |
Less-18*
HTTP 请求方式 | 可注入类型 | SQL 拼接方式 |
---|---|---|
POST |
报错、盲注 | VALUES ('$uagent') |
- 源码简单分析:
1 | # 获取请求的 uagent 和 ip 地址 |
- 这个代码漏洞点出在了
insert
语句,这里没有对uagent
和ip_address
进行过滤,并且输出了mysql
的报错信息。 - 这里的
IP
是无法被伪造的,这里只能通过修改user-agent
来进行注入,考虑到insert
语句的特殊性,这里使用闭合方式来闭合掉后面的语句,因为输出了mysql
报错日志了,这里尝试报错注入效率会更高一点:
注:只能使用 and ‘1’=’1,不能用注释,注释会把后面的语句删除导致报错。
1 | User-Agent: 1' and '1'='1 |
- 和
Less-17
利用方式一致,只是闭合方式不一样而已,这里不再阐述。
Less-19
HTTP 请求方式 | 可注入类型 | SQL 拼接方式 |
---|---|---|
POST |
报错、盲注 | VALUES ('$uagent') |
- 和
Less-18
利用方式一致,只是这里的漏洞点出在了referer
里面,这里不再阐述。
Less-20
HTTP 请求方式 | 可注入类型 | SQL 拼接方式 |
---|---|---|
POST |
联合、报错、盲注 | username = '$cookee' |
- 源码简单分析:
1 | if cookie 中不存在 uname 参数: |
- 从
cookie
中读取的uname
参数值 并直接拼接到了SQL
语句中了,这就导致了注入点的产生,并且还输出了查询信息,所以这里是可以进行联合查询注入的:
1 | Cookie: uname=-admin' union select 1,2,database() --+ |
- 和
Less-1
利用方式一致,这里不再阐述。
SQLMap
- 这里可以使用
SQLMap
直接进行注入,命令如下:
1 | root at kali in ~ |
Less-21
HTTP 请求方式 | 可注入类型 | SQL 拼接方式 |
---|---|---|
POST |
联合、报错、盲注 | username = ('$cookee') |
- 简单的源码分析:
1 | if cookie 中不存在 uname 参数: |
- 从源码中分析可得,和
Less-20
基本上是一毛一样,只是Cookie
这里是经过base64
加密的,所以我们只需要传入加密后的payload
给cookie
的uname
即可。
1 | # 编码前 |
- 和
Less-1
利用方式一致,这里不再阐述。
SQLMap
- 这里可以使用
SQLMap
直接进行注入,命令如下:
1 | root at kali in ~ |
sqlmap
本身不会混淆发送的payload
,混淆payload
的话可以使用sqlmap
自带的payload
库。
Less-22
HTTP 请求方式 | 可注入类型 | SQL 拼接方式 |
---|---|---|
POST |
联合、报错、盲注 | username = "$cookee" |
- 和
Less-21
利用方式一致,只是闭合方式不一样而已,这里不再阐述。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Yongz丶!