##SQL基本原理
【资料图】
---数据库查询流程
---拼接GET请求参数id直接拼接在SQL语句中,未经过任何过滤或处理
---并且使用了 LIMIT
子句来限制结果集只返回一行(即第一行)
---如何发现SQL注入(输入异常数据,会报错)
---如果未报错,不代表不存在 Sql 注入
---因为有可能页面对单引号做了过滤,这时可以使用判断语句进行注入
---sQL注入的发现,核心就是输入错误的数据,会发生报错
---这里是预定的是传入数字型变量,所以没有对参数加 ''
---SQL的注释语句:
/**/
注释:这是MySQL中的多行注释语句,单行注释则是 -- 或者 #
;%00
终止查询:在某些情况下, ;%00
被用于尝试终止查询的执行。这是因为在某些MySQL客户端和服务器配置中,分号 ;
被用作查询分隔符, %00
是空字符的编码
/*letmetest*/
注释:类似于普通注释,这是一种用户可能用来在SQL语句中添加自己的解释性注释的方式。这样做可以帮助其他人理解SQL语句的目的
---总结:--是起到注释的作用,+是启动空格的作用,在sql中用--注释后面必须加一个空格--才生效,所以我们不一定要用--+,可以用-- 加上空格在加上任意字符,都行
---SQL注入的类型
---例如在一个数据库里面存在
---ORDER BY column1 [ASC|DESC], column2 [ASC|DESC],
---order by根据指定类的升序或者降序排列(这里是倒序排列)
---limt 0,2是只显示第1列和第二列
---可以使用union进行多个表的查询
##SQL有回显注入之union注入
---step 1 :判断是否存在注入漏洞(注意:+输入在MYSQL里面是空格)
---两次回显不一样,说明存在SQL注入
---step 2:判断有当前的表多少个字段(多少列):
---注意:ORDER BY
后面应该跟着列名,以便指定要根据哪一列(字母升序排序)进行排序
---那么,就可以测试表里面存在多少列(说明这里存在三列)
---通过构造语句,查看显示位是哪一列
---前面为假,所以不执行,只执行union后面的select 1,2,3语句
---select 1,2,3发现显示的3列,通过123来判断前端页面回显的是那一列数据
---这里显示的是第二三列的数据
---注意:--后门存在数据,所有我们不需要--+,只需要--就行
---step 4 : 查询基本信息
concat(...)
:这是一个MySQL函数,用于将多个字符串连接起来。
0x3a
:这是一个十六进制表示的冒号字符 :
,在这个查询中,它被用作分隔符。
user()
:这是一个MySQL函数,用于返回当前用户的用户名。
database()
:这是一个MySQL函数,用于返回当前数据库的名称。
version()
:这是一个MySQL函数,用于返回当前MySQL服务器的版本号。
@@version_compile_os
:这是一个MySQL系统变量,用于返回MySQL服务器的操作系统编译信息
---这里就查询到数据的敏感信息
---数据库版本;操作系统是Win64;用户是root,数据库名称(security)
---下面是SQL注入常用的信息收集
##MYSQL的体系结构
INFORMATION_SCHAME库:存放整个库的结构
MYSQL库:存放用户配置等数据
其他库:用户自主创建
#INFORMATION_SCHAME库
----TABLES表:提供了关于数据库中的表的信息(包括视图)。详细表述了某个表属于哪个SCHEMA,表类型,表引擎,创建时间等信息---COLUMNS表:提供了表中的列信息。详细表述了某张表的所有列以及每个列的信息---STATISTICS表:提供了关于表索引的信息---USER_PRIVILEGES(用户权限)表:关于全程权限的信息源自授权表---SCHEMA_PRIVILEGES:给出了关于方案(数据库)权限的信息---TABLE_PRIVILEGES(表权限);COLUMN_PRIVILEGES(列权限)---CHARACTER_SETS(字符集)表:提供了MYSQL实例可用字符集的信息
---在information_的schema_name里面存在数据库的信息
---information_的table_name存储表的信息
---ROUP_CONCAT
是一种查询的聚合函数(注意是查询)。它用于将一列中的多个值连接成一个单独的字符串,并且可以在查询的结果中返回这个连接后的字符串(默认以 , 分隔)
---查看存在的数据库,通过group_comcat将查询的结果以,(逗号)链接成字符串
---但是:where table_schema=database()换成where table_schema=securty会报错
---当前数据库的表
---security数据库中存在4个表,users和emails等
---查询users表里面的列字段(注意:要添加AND去区分才行)
---显示user表的列名
---原理是information_里面存在表面、数据库名以及列名
---现在我们获取到:数据库'security',表'users',以及列:id,username,password
---构建查询语句查询用户名和密码(where的列名要加'',from后门不用加)
---查询出用户名和密码
---当然,也可以使用group_concat()将显示集中在一点(多个查询)
----效果如下
##基于报错的注入
---报错注入用在数据库的错误会回显在网页中的情况,如果联合查询不能使用,首选报错注入
---报错注入利用的是数据库的报错信息得到数据库的内容,这里需要构造语句让数据库报错
#方法1:函数参数格式错误【updatexml()】
---updatexml()函数语法:用于在 XML 数据中更新指定路径的元素值
xml_target
是待更新的 XML 数据字段。
xpath_expr
是用于指定要更新的 XML 元素的路径。
new_value
是新的值,用于替换选定的 XML 元素
---例如,假设你有一个名为 my_table
的表,其中包含一个名为 books
的 XML 类型列
---你可以使用 UPDATEXML()
函数来更新该列中的某个XML 元素的值,如下所示
---book是XML 列,/book/title 是要更新的 XML元素的路径
---把表中id为1的记录的title节点的值修改为"Learning MySQL"
---构造Xpath_string格式错误,将Xpath_string传递成不符合格式的数,mysql就会报错
---查询当前用户和版本信息
---获取当前数据库下数据表信息:
--这里只能显示一行,所以在 table_schema='security' 后加上 limit 0,1,显示第一行
---如果要看第二行则,limit1,1(第一行的往下一行,不包括第一行,即显示第二行),看第三行则limit2,1,以这个方法获取第四个表为users
---如图所示
---爆表中的字段
---如下(查询数据出现了问题,只能出现前2个用户名和密码)
#方法2:extractvalue() 函数
---EXTRACTVALUE()
函数通常是用于从 XML 类型的数据中提取特定值的函数
xml_document
是包含 XML 数据的字段或变量。
xpath_expression
是一个 XPath 表达式,用于指定您希望从 XML 中提取的特定数据
---举例来说,如果您有一个存储有以下 XML 数据的列:
---可以使用 EXTRACTVALUE()
函数来提取 <title>
元素的内容
---查询数据库
---效果如下
#方法3:floor()函数
---floor()报错注入在MySQL版本 已失效,经过测试也已失效
---FLOOR()
函数用于将一个浮点数或双精度数向下取整为最接近的整数
---设有一个名为 sales
的表,包含销售订单和订单金额。您想要对订单金额向下取整,以便进行更精确的金额比较或统计。您可以这样使用 FLOOR()
函数
----假设有一个名为 orders
的表,包含订单信息,如订单编号、客户编号和订单金额:
---如果想要按客户分组,并计算每个客户的订单总金额,可以使用以下查询:
---结果将是:
GROUP BY
子句中的列必须是 SELECT
中列出的列或聚合函数的参数。
在 GROUP BY
子句中,您可以使用多个列来定义分组,从而创建多维分组。
GROUP BY
子句通常与聚合函数一起使用,以在分组上执行汇总计算
---RAND()
函数用于生成一个介于 0 和 1 之间的随机浮点数。每次调用该函数都会生成不同的随机数。示例:从一个名为 products
的表中随机选择一个产品
---COUNT()
函数用于计算满足特定条件的行数,示例:统计一个名为 users
的表中的用户数量
----主要报错原因为:count()+rand()+group_by()导致主键重复(不是很懂)
---因为floor(rand(0)*2)的重复性(生成0|1),导致group by语句出错
---group by key的原理是循环读取数据的每一行,将结果保存于临时表中
---读取每一行的key时,如果key存在于临时表中,则不在更新临时表的数据
---如果key不在临时表中,则在临时表中插入key所在行的数据
#构建报错注入eXp
---(select database()+from+information_+limit+0,1)是查询当前数据库名称
---concat(当前数据库名称,foor(rand()*2)) as x将数据库名称和一个随机整数(0 或 1)连接起来,如当前数据库concat(security,1)是:security1,命名为x
----select count(*),security1 as x from+information_+group+by+x(查询information_的行数和数据库名称与随机数结合,并且按照x排序
---select 1 from x排序的数据 as a x排序的数据的第一列
---原理分析(count与group by的虚拟表)
---以看出1班的记录有4人 2班3人 3班6人 5班1人,与count(*)的结果相符合
---那么mysql在遇到select count(*) from student group by classid;这语句的时候到底做了哪些操作呢?
---猜测mysql遇到该group by和count(*)时会建立一个虚拟表(实际上就是会建立虚拟表),那整个工作流程就会如下图所示:先建立虚拟表,如下图(其中key是主键,不可重复):
开始查询数据,取数据库数据第一条记录,然后查看虚拟表存在classid为1的诸葛亮吗?不存在则插入新记录并计数为1,如果存在则count(*)字段直接加1
然后循环这样的操作,直到查询到最后一条记录
---那为啥用group by floor(rand(0)*2)就会报错呢?
---因为floor(rand(0)*2)计算是有固定规律的0110110011......的顺序
当使用报错语句执行查询表的第一条数据时,依据selectfloor(rand(0)*2)from student;得出的规律01101可以知道这次的值为0(这是第一次计算floor(rand(0)2)),查询虚拟表,发现虚拟表没有数据,于是将0插入虚拟表key字段,
在插入key字段时floor(rand(0)*2)会再执行一次(这是第二次计算,依据规律值为1),于是乎在key的第一个值插入的其实是1count (*)计数为1
查询第二条数据时,依据01101规律floor(rand(0)*2)结果为1(这是第三次计算),查询虚拟表,发现虚拟表已经有了key为1的记录,于是直接在count处进行加1
查询第三条数据时,依据01101规律floor(rand(0)2)的结果为0(这是第四次计算),查询虚拟表,发现虚拟表没有key为0的值,在插入key字段时floor(rand(0)2)会再执行一次(这时floor(rand(0)*2)的值成为1,这是第五次执行),因为在虚拟表中已经存在key为1的值,所以会出现虚拟表主键冲突,所以报错。
通过上面分析我们可以看出如果数据库的记录小于三条那floor报错也是无法利用的
所以我们查询的表可以是information_ 这里面应该是有大于等于三条记录的
---总结:基于 count(*) concat() x from information_ group by x报错注入
---emmm有一些似懂非懂
---常见的报错注入
##基于布尔的盲注
---布尔盲注,即在页面没有错误回显时完成的注入攻击。此时我们输入的语句让页面呈现出两种状态,相当于true和false,根据这两种状态可以判断我们输入的语句是否查询成功
---源码如下
--- 我们输入正确的id,显示You are in .....
---输入错误的语句如id=1' ,或者id=-1时,就什么都不显示。这就是布尔盲注,屏幕上能得到信息不多,就是两种状态
---构造判断语句,根据页面是否回显证实猜想
---一般用到的函数ascii() 、substr() 、length(),exists()、concat()等
---ASCII()
函数返回给定字符的 ASCII 值(字符编码)
---SUBSTR()
函数(也称为 SUBSTRING()
函数)用于提取字符串的子串,根据起始位置和长度(注意是长度)来截取字符串的一部分(从1开始)
---LENGTH()
函数用于计算字符串的长度,即字符的数量。对于多字节字符集,它返回字节数,而不是字符数
---EXISTS()
函数用于检查一个子查询是否返回任何结果。如果子查询返回至少一行数据,则 EXISTS()
返回 TRUE
,否则返回 FALSE
---CONCAT()
函数用于连接字符串,它将多个字符串连接在一起以创建一个更大的字符串
---常见的布尔盲注
---布尔盲注的思路:根据长度判断名称,根据ASCII判断
#1. 判断数据库类型
MySQL数据库表 information_
access msysobjects
SQLServer sysobjects
---用下的语句判断数据库,哪个页面正常显示,就属于哪个数据库
---这里可以发现是MYSQL数据库
#2. 判断当前数据库名
---判断当前数据库的长度,利用二分法
---大于7正常显示,大于8不显示,说明大于7而不大于8,所以可知当前数据库长度为8个字符
---2:判断当前数据库的字符,和上面的方法一样,利用二分法依次判断
---由此可以判断出当前数据库为 security
#3. 判断当前库的表名
---猜测当前数据库中是否存在admin表
---这里是不存在
---判断当前数据库中表的个数
---这里是4个表
---判断每个表的长度:
---第一个表的长度为6,第二个也为6
---判断每个字段名字的ascii值(可判断出存在表 emails、referers、uagents、users ,猜测users表中最有可能存在账户和密码
)
---判断users表的列字段
判断字段个数
判断每个字段的长度
猜每个字段的字符
--- 1:判断表中字段的个数
---2:判断每个字段的长度
---3:判断每个字段名字的ascii值
---由此可判断出users表中存在id、username、password 字段
#5. 爆字段中的数据
---users中有三个字段 id 、username 、password,我们现在爆出每个字段的数据
---1.判断数据的长度
---例如这里是id字段的
---2.判断数据的ASCII
---一般布尔盲注,手工去注入过于繁琐,不建议手工注入,可以借助于工具
##基于时间的盲注
---通过观察页面,既没有回显数据库内容,又没有报错信息也没有布尔类型状态,那么我们可以考虑用“绝招”--延时注入
---延时注入就是将页面的时间线作为判断依据,一点一点注入出数据库的信息。我们以第9关为例,在id=1后面加单引号或者双引号,页面不会发生任何改变,所以我们考虑绝招延时注入
---?id=1' and sleep(5) --+
---如果expr1的值为true,则返回expr2的值,如果expr1的值为false,则返回expr3的值
#获取数据库名称
---如果数据库名字的第一个字符的acsii值为115,则进行延时,否则返回0即什么都不返回
?id=1' and if(ascii(substr(database(),1,1))= 115,sleep(5),0) --+
---页面显示延时5 秒,说明数据库名字第一个字母的ASCII 值是115,也就是字母s
---与盲注类似,后面就是猜数,这就是延时注入
##不安全的HTTP方法
---除标准的GET和POST方法外,HTTP请求还支持使用其他各种方法
---检测服务器支持的方法:利用burp抓包
---将请求包的请求方式修改为OPTIONS,即可看到服务器允许的http请求方法
---此外,我们可以根据允许请求的信息,进行GET/POST方法之外的传参
##宽字节注入--- 宽字节注入准确来说不是注入手法,而是另外一种比较特殊的情况
---为了说明宽字节注入问题,我们以SQLi-labs 32 关为例子
---使用?id=1' 进行测试的时候,发现提交的单引号会被转义[\']
---查看源代码:发现除了对于【 \ ' " 】都进行了添加\转义
---然后对参数设置成GBK存储,那么一个字符需要占2位(2Byte)
某字符的大小为一个字节时,称其字符为窄字节.
当某字符的大小为两个字节时,称其字符为宽字节.
所有英文默认占一个字节,汉字占两个字节
常见的宽字节编码:GB2312,GBK,GB18030,BIG5,Shift_JIS等等
---查看mysql是否为GBK编码,且是否使用preg_replace()把单引号转换成\'或自带函数addslashes()进行转义(白盒检测宽字节注入)
---绕过这个转义处理,使单引号发挥作用不再被转义,有两个思路:
让斜杠(\)失去作用
让斜杠(\)消失(宽字节注入)
---转义函数会将转义字符‘\’ 转为 %5c,于是我们在他前面输入一个单字符编码与它组成一个新的多字符编码,使得原本的转义字符没有发生作用
----由于在数据库查询前使用了GBK多字节编码,即在汉字编码范围内使用两个字节会被编码为一个汉字(前一个ascii码要大于128,才到汉字的范围)
---前面加上 %df' ,转义函数会将%df’改成%df\’, 而\ 就是%5c ,即最后变成了%df%5c'
---而%df%5c在GBK中这两个字节对应着一个汉字“運” ,就是说 \ 已经失去了作用,%df ' ,被认为運' ,成功消除了转义函数的影响
---输入 ?id=1%df',按道理来说将转义符吃掉了,结果应该是 id=' 運' ' ,为什么这里转变成了中文后后面还有一个反斜杠了?(%27的是'的URL编码)
---这里需要使用:火狐浏览器 > 菜单 > 查看 > 修复文字编码
---通过order by发现存在3列
---这里发现是有回显的注入
---gb2312和gbk应该都是宽字节家族的一员,把源码中set names修改成gb2312
---结果就不能注入了,这归结于gb2312编码的取值范围,它的高位范围是0xA1~0xF7,低位范围是0xA1~0xFE,而\是0x5c,是不在低位范围中的
---所以,0x5c根本不是gb2312中的编码,所以自然也是不会被吃掉的---因此:只要低位的范围中含有0x5c的编码,就可以进行宽字符注入
---黑盒检测宽字节注入:在注入点后面加%df,然后按照正常的注入流程开始注入即可
----使用sqlmap进行检测注入的话也需要在注入点后面加%df然后再用sqlmap跑
##堆叠注入
---堆叠查询也叫堆叠注入,在SQL中,分号(;)是用来表示一条sql语句的结束
---而union injection(联合注入)也是将两条语句合并在一起,两者之间有什么区别么?
---区别就在于union 或者union all执行的语句类型是有限的,可以用来执行查询语句
----而堆叠注入可以执行的是任意的语句,以sqli-labs第38关为例
---执行堆叠注入更改密码:?id=1';update+users+set+password='123456'+where+id=1;--+
---源代码分析:mysqli_multi_query($con1, $sql) 导致的堆叠注入
---之前的代码都是使用该函数执行SQL语句:$result=mysql_query($sql);
##二次注入
---二次注入就是由于将数据存储进数据库中时未做好过滤,先提交构造好的特殊字符请求存储进数据库,然后提交第二次请求时与第一次提交进数据库中的字符发生了作用,形成了一条新的sql语句导致被执行。以sqli-labs第24关为例
---这里注册用户名为 admin'#
---查看数据库,但是admin'#
----登陆后,修改密码为cccc
---发现反倒是admin的密码被修改成了ccccc,而我们注册的用户admin'#的密码并没有被修改
---漏洞原因:
1. 在进行用户注册的允许存在'和#这种特殊字符(没有过滤)
2. 在修改密码页面的源码中,发现这里很明显存在注入漏洞
---当我们登录账号admin'#并修改密码时,这条sql语句就变成了如下
---#把后面的代码都注释掉了,所以修改了用户admin的密码为ccccc
##SQL注入文件读取
---利用条件
web目录具有写权限,能够使用单引号
知道网站绝对路径(根目录,或则是根目录往下的目录都行)
secure_file_priv没有具体值(在mysql/中查看,在mysql 版本以后 secure_file_priv 的值默认为NULL)
---secure_file_priv的值为null ,表示限制mysqld 不允许导入|导出---当secure_file_priv的值为/tmp/ ,表示限制mysqld 的导入|导出只能发生在/tmp/目录下---当secure_file_priv的值没有具体值时,表示不对mysqld 的导入|导出做限制
---方法1:load_file('绝对路径')读取敏感文件
---直接select load_file()读取
---创建表,将文件内容导入到表内
--方法2:load data local infile
---如果指定local关键词,则表明从客户主机读文件;否则则文件必须位于服务器上
---使用local需要设置local_infile开启,该变量默认为ON
---读取文件到表中
----如图所示
---方法3:system命令执行:
---在mysql版本为时,除了可以使用上方法外,还可以使用系统命令直接读取文件
#secure_file_priv=NULL 的绕过
---使用system执行系统命令和load data infile语句加local选项绕过限制
system执行系统命令适用版本为。
此方法只能在本地读取,远程连接mysql时无法使用system。
无法越权读取。
使用load data local infile语句从客户主机读取文件。
---1.查询secure_file_priv值:
---读写文件:(强调一下system执行系统命令!)
--- data local infile需要将读取的文件存储在数据表中(可以读取敏感文件)
##SQL注入文件写入
---方法1:into outfile() 方法2:into dumpfile()
INTO OUTFILE
子句用于将查询结果写入文本文件。这个文件可以是纯文本文件,也可以包含 CSV 格式或其他文本格式(上传一句话)
INTO DUMPFILE
子句用于将查询结果写入二进制文件。这个文件是 MySQL 内部格式的二进制文件,不适合直接读取或编辑(UDF提权)
---一句话十六进制转码 “ <?php eval($_REQUEST[1]);?> ”
---编码后,然后在最前面加上 0x
----如下我们将一句话木马进行十六进制编码后写入了根目录下的文件中
---拓展:SQL的os-shell会在指定的目录生成了两个文件(文件名是随机的):
用来执行系统命令
用来上传文件
---的文件内容为:通过cmd进行request传参
---系统命令执行
---使用上传文件,访问发现是一个文件上传点
##MYSQL的万能密码
---构造永真条件,得到查询条目(一般和or结合一起使用)
---利用数据库的变量类型转换
---通常和字典一起结合,进行fuzz
##一种隐蔽的注入
---思路就是将查询内容转成数字进行运算
##Mysql过长截断
---在MySQL没有开启STRICT_ALL_TABLES选项时(MySQL sql_mode默认为defalut),MySQL对插入超长的值只会提示'warning'并且插入成功,而不是error,这样会导致一些截断问题
---插入的username变成了从 'admin 1'变成了 'admin'
##sql注入各种绕过
---1.注释符号绕过
---2.大小写绕过:waf的正则对大小写不敏感的情况
---3.内联注释绕过
---把一些仅在MYSQL上的语句放在 /!../ 中,这样这些语句如果在WAF中不会检测
---4.双写绕过
---在waf中,将关键字select等只使用replace()函数置换为空,这时候可以使用双写关键字绕过
---例如select
变成seleselectct
,在经过waf的处理之后又变成select,达到绕过的要求
---5.编码绕过:如URLEncode编码,ASCII,HEX,十六进制编码绕过
---6.空格绕过:一般绕过空格过滤的方法有以下几种方法来取代空格
---7.对or and xor not 绕过
---8.对等号=绕过
---9.对单引号的绕过(另外一种是宽字节绕过)
---会使用到引号的地方一般是在最后的where子句,如下面的一条sql语句
---users的十六进制的字符串是7573657273。那么最后的sql语句就变为了:
---注入关键函数替换
---12.’".md5($pass,true)."’ 登录绕过
---很多站点为了安全都会利用这样的语句
---md5(string,true) 函数在指定了true的时候,是返回的原始 16 字符二进制格式
---为什么 6\xc9]\x99\xe9!r,\xf9\xedb\x1c 的布尔值是true呢
---在mysql里面,在用作布尔型判断时,以1开头的字符串会被当做整型数
---要注意的是必须要有单引号括起来的,比如 password=‘xxx’ or ‘1xxxxxxxxx’,那么就相当于password=‘xxx’ or 1 ,也就相当于 password=‘xxx’ or true,所以返回值就是true
----这里不只是1开头,只要是数字开头都是可以的,当然如果只有数字的话,就不需要单引号
---附录 PHP中一些常见的过滤方法及绕过方式
##SQL绕过安全SafedogWAF
#构造and 1=1
---方法1:暴力破解fuzzMysql的/**/
--直接1=1被拦截
----我们这里尝试用/*/来充当注释符
---选择暴力破解,字符集就选/!*
进行测试即可
---这里5000以下的都可以绕过(但是有一些会报错)
---筛选正常回显的:/*%2f**/
---方法2:内联注释符号,,就是/*!00000*/
这种的
---如果没有接版本号时,会直接执行里面内容
---当!后面接数据库版本号时,如果自身版本号(上述例子中的)大于等于字符数(例如上述例子中的99999和00000),就会将注释中的内容执行,否则就会当做注释来处理
---构造如下/*!000001*/=/*!000001*/
语句尝试进行绕过
#order by绕过
---直接order by,猜测是 order by和在一起会被拦截
---直接拿之前fuzz的/*%2f**/测试,发现欧克
---也可以尝试内联注释爆破
---单独的一个union和单独的select都是可以的,此时我就想利用它内联注释字符数大于版本号时将其内语句作为注释来进行一个绕过
---选择暴力破解,设置0-9依次进行爆破
---而后得到结果
#information_schema过滤绕过
---正常的爆表,但是 from 和 information_schema都会检测
---两个进行分别fuzz的话比较麻烦,而且将两者进行一起用时可能会出现仍然被过滤的情况
---方法1:传统的内联注释/*!*/
---因此想到了内联注释这种方法,可不可以用这种方法来进行绕过呢,我们先尝试一下
---结果如下
----方法2:中间加注释符再加换行,也就是/*!%23%0a*/
---本地测试
---尝试第一种,发现被拦截
---尝试第二种,也被拦截
---此时想有没有可能是过滤了%23(对应#),我们将%23换成--+
构造payload如下
---这里查询到数据库的表
#like["%23"]
---我们知道%23是注释符(#)的含义,那么在这里的时候,它这个语句到底有什么作用呢
---在查询语句添加:like ["%23"] //这里是一个约束条件
---构造语句,那它这条语句就相当于select * from users
---测试联合查询,但是检测
---此时我们将union后的空格用换行符替代(也可以使用+替换)
---总结:空格可以使用:+或者%oa替换
---总结相关绕过
---1.通过 !#/- 等来暴力破解 /* a */
---2.通过内联注释,/*!000001*/=/*!000001*/
和 0123456789 来 fuzz /*! */使其无意义,以及 database/*!()*/
这种,利用bp在括号前面加上五个数字,使其有意义
---3.内联注释的利用方法就是中间加注释符再加换行:
/*!%23%0ainformation_*/ 和
/*!%23/*%0ainformation_*/
以及
/*!--+/*%0ainformation_*/
---4.
select*from users where id=1 like "[%23]"union select *from users;
---通过fuzz的注释语句编写sqlMap的tamper脚本
---思路:就是通过replace函数对应传统的SQL单个函数进行混淆
##知识点总结:
---注入的原因:构建查询语句直接传参,没有检测和过滤(预编译)
---注入:有回显注入 和 无回显注入
---3.有回显注入: union注入 和 报错注入(updatexml()、extractvalue() 、count()+rand()+group_by()导致主键重复)以及 布尔盲注
---4.无回显注入:基于时间的注入(根据length()判断长度,根据Aecii判断值)
---5.不安全的http方法:在数据包方法options,可以看到WEb允许的传参方法
---注入的方法:post/get/request
---注入的传参点:x-forwarded / refrerer / cookie
---(存储在服务端,占用资源大) 、 cookie (sessioniD,保存在客户端易盗取,不能跨域,存在多个服务器时需要备份)、token(服务端通过密匙检验token的签名,需要查询数据库获取用户信息) 、 jwt(json格式,在Authrization设置,用户状态不再存储在服务端,自身包含一下会话信息,存在签名) 的联系与区别(类似:记录用户信息的酒店电脑的Session、房卡cookie、指纹验证token、集成用户会话信息加密的微型手机jwt)
---函数出错:堆叠注入、宽字节注入
---10、SQL注入帽子戏法:编码注入绕过'过滤、万能密码登陆、Mysql过长截断、二次注入、md5(string,true) 函数绕过
---的读取:load_file('绝对路径') 、 load data local infile '/tmp/' into table 、system cat\type ,以及load data local infile和system绕过secure_file_pri = null
---的导出:导出普通文件(上传webshell):into outfile() 导出二进制(UDF):into dumpfile()
---的os-shell,上传2个文件,一个系统命令执行,一个用于文件上传
---注入绕过:注释符号绕过、内联注释绕过、大小写绕过、双写绕过、编码绕过、=<>的替换函数绕过、空格替换绕过、and or xor not替换绕过、like和=替换绕过、sleep/ascii/group_concat/等函数替换绕过、
---绕过安全狗:思路通过0-9和!-/*等特殊符号fuzz的/**/ 和/*!*/,通过对应内联注释的变种/*!%23%0a*/
/*!%23/*%0a*/
/*!--+/*%0a*/ 以及
like "[%23]"
构造假条件
---编写tamper脚本:通过replace函数替换传统的SQL语句进行混淆
参考文章:
【1】floor报错注入原理解析:/LcveO
【2】sql注入详解(推荐):/tfJSW
【3】赛宁网安:《Web安全基础1》
【4】傻傻分不清之 Cookie、Session、Token、JWT:/post/6844904034181070861
【5】授权认证登录之 Cookie、Session、Token、JWT 详解:/vFIiH
【6】token和session与cookie详解以及应用原理:/01xNm
【7】HttpOnly 标志——保护 Cookie 免受 XSS:/t7ttc
【8】X-Forwarded-For sql注入:/5kahK
【9】MYSQL文件读写:/GVKBt
【10】sql注入各种绕过:/xYBqS
【11】从SQL注入绕过最新安全狗WAF中学习fuzz:/s/ChwHSHGMd3GJDpYN4z1c9Q