跳转至

MSSQL 事件排查

MSSQL 应急排查部分已经有微步在线应急响应团队、深信服千里目实验室写得非常详细了,本部分基本也就是对其文章的提炼,建议大家阅读 《知攻善防~SQL Server 应急分析(上&下)》、《MSSQL数据库攻击实战指北 | 防守方攻略》

https://mp.weixin.qq.com/s/omDWZ0MK-WRTICXK3K9dZA

https://mp.weixin.qq.com/s/zfUJnAiSzm-gwYVWxGT7Cw

https://mp.weixin.qq.com/s/ug5LmTIbrd_jVG-euNr8aw

0x00 固定证据

在发生任何安全事件时,确定安全事件真实存在以后,第一步都建议固定证据,固定证据一般有以下几种类型,受害单位可以根据实际需求选择

  • 系统快照 - 一般云环境比较方便这么做
  • 磁盘取证
  • 针对性取证 - 例如日志文件、网络信息、数据库等
  • 内存取证

系统快照

这种主要是云环境或虚拟化环境比较方便,目前似乎这类方式取证出来的内容都会丢失内存信息,属于是关机-快照-导出

虚拟机软件似乎支持例如暂停、冻结等功能,具体根据实际情况决定

磁盘取证

磁盘取证有很多工具可以考虑

  • dd
  • FTK Imager

针对性取证

这部分推荐我们自己的 NOPTrace-Collector

https://github.com/Just-Hack-For-Fun/NOPTrace-Collector

我们还推出了一套数字取证和应急响应规范,可以根据此规范自己开发取证程序

https://github.com/Just-Hack-For-Fun/OpenForensicRules

内存取证

  • DumpIt
  • FTK Imager

取证后,对证据进行分析时,需要先单独复制一份,保持所有安全人员分析的基础是相同的

0x01 简介

MSSQL 是微软官方的一款数据库管理程序,常用于 Windows 操作系统中 .net 开发的系统中,也是攻击者常常利用的攻击点,在非常早期的时候,往往是网站与数据库放在同一个操作系统上,而且 MSSQL 的端口(默认 1433)对外暴露,导致很多安全问题,甚至一些早期黑客还为它专门开发了“1433抓鸡”程序

现在安全防护水平提升了,MSSQL 面临的威胁主要是以下这些内容:

  • 弱口令
  • SQL 注入
  • 权限提升
  • 数据泄露
  • 隐藏后门

这里可以看出,我们只需要对以下几种内容进行关注

  • MSSQL 登录日志
  • MSSQL 数据库操作日志
  • MSSQL 相关的基础组件
    • 作业(Job)
    • 存储过程
    • OLE 对象接口
    • 程序集
    • 备份与恢复过程

0x02 用户及会话分析

我们可以查看的是当前可登录的用户以及会话情况

获取用户信息

SELECT * FROM 
    sys.server_principals
WHERE 
    type IN ('S', 'U') -- 'S' for SQL Server authentication, 'U' for Windows authentication
ORDER BY 
    name;

image-20240709221743039

其中 is_disabled 为 1 的用户被禁止了,其中 helper 是我的测试电脑的用户的名字,实际情况可能不一样,当前身份认证模式是混合模式

也可以通过图形化的方式进行查看

安全性 -> 登录名 

image-20240710000324777

获取当前会话情况

SELECT 
    session_id,
    login_time,
    host_name,
    login_name,
    program_name,
    status,
    last_request_start_time,
    last_request_end_time
FROM 
    sys.dm_exec_sessions
WHERE 
    status NOT IN ('sleeping', 'background');

image-20240709221833278

0x03 MSSQL 登录日志分析

这部分内容在 暴力破解 -> 0x06 MSSQL 暴力破解 章节已经详细阐述,这里简单介绍一些位置之类的

MSSQL 2016 中,使用 SSMS 进行数据库连接和管理

image-20240709154933891

在 管理 -> SQL Server日志中可以看到具体的日志信息

image-20240709155203414

默认情况下似乎不记录登录成功的日志,除非额外配置审计日志

当然,在这里我们还可以勾选其他日志,一起进行查看

0x04 SQL执行日志分析

默认情况下,其实也不会记录执行的 SQL 语句,即使是出错的 SQL 语句也不会执行

这也很好理解,增删改查的量这么大,记录起来会严重影响性能并且额外占用资源

但某些单位自研或者采购的日志记录或者安全设备可能会记录部分或完整的 SQL 日志,比较常见的是记录哪些安全设备认为是可疑或者恶意的请求,这样记录量就会小很多,所以在寻找蛛丝马迹的时候不要忘了安全设备

如果记录了全量的SQL日志,可以关注除了常规的增删改查以外的日志,尤其是包含以下关键字:

  • SQL注入相关

    • 字符串拼接:+, ||, CONCAT(), CONCAT_WS()

    • 特殊字符和转义序列:', --, /*, */, ;, #, \

    • 错误触发:UNION, SELECT, FROM, WHERE, AND, OR, GROUP BY, HAVING, ORDER BY

    • 数据库元信息泄露:DATABASE(), USER(), VERSION(), SYSTEM_USER(), SESSION_USER(), CURRENT_USER(), @@VERSION, @@SERVERNAME

    • 存储过程调用:EXEC, EXECUTE, SP_EXECUTESQL, xp_cmdshell, sp_OACreate,xp_regwrite, xp_regread, addextendedproc

    • 文件系统访问:LOAD_FILE(), READTEXT(), WRITETEXT(), BULK INSERT

    • 内置函数滥用:ASCII(), CHAR(), CHR(), MID(), SUBSTR(), SUBSTRING(), HEX(), UNHEX()

    • 非常规的执行时间:特别长的查询执行时间可能表明有异常行为
    • 频繁的错误尝试:多次失败的登录尝试,或者带有错误信息的查询,可能意味着暴力破解或基于错误的SQL注入攻击尝试
  • 数据泄漏相关

    • 大量数据导出:SELECT语句后面跟着大量列名或使用*选择所有列,尤其是与敏感数据相关的表。

    • 文件写入操作:INTO OUTFILE, INTO DUMPFILE, BULK INSERT, OPENROWSET()

  • 提权与绕过访问控制

    • 权限更改:GRANT, REVOKE, DENY, ALTER AUTHORIZATION

    • 用户管理:CREATE USER, ALTER USER, DROP USER, LOGIN, LOGOUT

    • 密码重置或修改:ALTER LOGIN, ALTER USER SET PASSWORD

  • 数据库结构修改相关

    • 表和索引管理:CREATE TABLE, DROP TABLE, ALTER TABLE, CREATE INDEX, DROP INDEX

    • 存储过程和函数修改:CREATE PROCEDURE, ALTER PROCEDURE, DROP PROCEDURE, CREATE FUNCTION, ALTER FUNCTION, DROP FUNCTION

  • 信息收集相关

    • 系统信息查询:INFORMATION_SCHEMA.*, sys.* (如sys.databases, sys.tables, sys.columns)

    • 枚举数据库和表:SHOW DATABASES, SHOW TABLES, SHOW COLUMNS FROM

  • 配置相关

    • TRUSTWORTHY 一个数据库级别的配置选项,当设置为ON时,允许数据库中的代码执行不受限制的操作,包括读取文件系统、注册表和其他数据库。
    • show advanced options 这个命令用于显示SQL Server的一些高级配置选项,其中一些可能影响服务器的安全性。这些选项通常不会直接导致安全问题,但它们的不当配置可能会引入风险。
    • RECONFIGURE 该命令用于在不重启服务的情况下更新SQL Server的运行时配置。这可以立即应用某些配置更改,但如果被攻击者利用,也可以用于迅速改变服务器的安全设置。
    • sp_configure 攻击者常使用该方法开启 xp_cmdshell
  • 程序集相关

    • Unsafe assembly
  • 高危 DLL
    • xplog70.dll 可用于恢复xp_cmdshell等存储过程
    • xpstar.dll 可用于恢复xp_sqlagent_notify
    • xpsqlbot.dll 可用于恢复xp_qv
    • odsole70.dll 可用于恢复Sp_OACreate

0x05 存储过程排查

只要是看过 Web 安全相关书籍的朋友们肯定听过存储过程这个词,也几乎都听到过 xp_cmdshell 这个词,但对于什么是存储过程可能并不完全了解,当然,这可能并不影响排查

简单来说存储过程就像是一个写好的函数,它实现了特定的功能,接收我们传递给它的参数,之后按照预期执行,给我们返回结果。需要注意的是,存储过程本身也是可能存在 SQL 注入的

存储过程分为以下几种

  • 系统存储过程(System Stored Procedures):

    • 这些存储过程由数据库管理系统提供,以sp_为前缀。它们主要用于管理数据库和获取关于数据库的信息,如执行维护任务、查看数据库结构或用户信息。例如,sp_help 可以用来获取对象的帮助信息,sp_helpdb 则可以报告数据库的信息。
  • 扩展存储过程(Extended Stored Procedures):

    • 这些存储过程通过动态链接库(DLLs)实现,以xp_为前缀。它们提供了超出标准SQL语言之外的功能,允许直接调用操作系统级的函数,例如xp_cmdshell 就可以用来执行操作系统命令。扩展存储过程需要特别注意安全,因为它们可以执行潜在危险的操作。
  • 用户定义的存储过程(User-defined Stored Procedures):

    • 这些存储过程由数据库用户创建,用于执行特定的业务逻辑或数据操作任务。它们可以接受输入参数,返回输出参数,以及执行复杂的事务处理和错误处理。
  • 临时存储过程(Temporary Stored Procedures):

    • 临时存储过程在会话期间存在,可以创建局部或全局的临时存储过程。局部临时存储过程名称以#开头,仅在创建它的会话中可见;全局临时存储过程名称以##开头,对所有会话都可见。
  • 远程存储过程(Remote Stored Procedures):

    • 这种类型的存储过程在不同的数据库服务器上执行,但可以从本地数据库服务器上调用。这种特性在分布式数据库系统中非常有用。
  • CLR存储过程(Common Language Runtime Stored Procedures):

    • 在 SQL Server 2005 及更高版本中,可以使用 .NET Framework 的 CLR 来编写存储过程,这提供了更丰富的编程模型和更高的执行效率。CLR 存储过程可以用 C#、VB.NET 等语言编写。

MSSQL 不是一个数据库,而是数据库管理系统,也就是它管理着多个数据库,其中系统存储过程 (sp_ 为前缀的) 由 SQL Server 系统提供的,可以在任何数据库上下文中调用,用于执行各种管理任务或获取信息。这些存储过程实际上是存在于master数据库中的,但由于它们的特殊性质,你可以在任何数据库中直接调用它们,而无需显式地指定数据库名称

扩展存储过程 (主要以 xp_ 为前缀的,也存在 sp_ 为前缀的) 是作为动态链接库(DLL)文件存在于文件系统上的,这些DLL文件是被SQL Server在运行时加载的,它们并不存储在数据库文件中,也不属于任何一个具体的数据库。当在SQL Server中注册一个扩展存储过程时,这个注册信息实际上是保存在master系统数据库中的sys.dllssys.server_permissions 表里。这意味着一旦注册,扩展存储过程就可以在SQL Server实例下的所有数据库中被调用,只要相应的用户具有足够的权限。

除了上面两个存储过程以外,其他存储过程均由每个数据库自己维护一份,因此我们排查的时候也是需要挨个数据库排查

1. 排查系统存储过程

系统存储过程存储在 master 数据库中

image-20240709182402334

然而比较尴尬的是,默认的系统存储过程有 1000 多个,每一个管理员权限都是可以编辑的,每一个都看一遍的话,时间上来不及,所以我们采取两种方案进行排查

  • 排查最新修改的系统存储过程
  • 根据系统存储过程执行记录,排查相关的系统存储过程
SELECT name, type_desc, create_date, modify_date
FROM sys.all_objects
WHERE type = 'P' AND name LIKE 'sp_%'
ORDER BY modify_date DESC;

可以通过在 master 数据库中执行上述语句,找出所有系统存储过程,并按照修改时间倒序排序

image-20240709183254616

假设我们想查看最新修改的这个系统存储过程,可以使用以下语句看一下其定义

USE YourDatabaseName; -- 替换为实际的数据库名
SELECT OBJECT_DEFINITION(OBJECT_ID(N'YourProcedureName')) AS ProcedureDefinition;

image-20240709184742462

经过查询发现,其实 sp_MScleanupmergepublisher 这个系统存储过程是sys.sp_MScleanupmergepublisher_internal 系统存储过程的别名,所以我们使用 sys.sp_MScleanupmergepublisher_internal 进行查询

image-20240709184951164

这回就出现了该系统存储过程的定义,我们复制出来格式化一下

-- Name: sp_MScleanupmergepublisher_internal
-- Description: This procedure currently performs the following function(s):
--              1) Cleans up all the stale dynamic snapshot views
--              in all databases enabled for merge replication. This
--              procedure should normally be called at merge publisher startup.
--
-- Notes: 1)This procedure is enabled as a startup procedure when a database is
--        enabled as a first merge publisher database on the server and it
--        will be unmarked as a startup procedure when the last merge publisher
--        database is disabled.
--        2)Errors within the SP are mostly ignored.
--        3)This procedure can also be used by admins/securityadmins to perform
--        manual cleanup of all dynamic snapshot views. Note that cleaning up the
--        dynamic snapshot views can disrupt dynamic snapshots that are being generated.
--
-- Returns: (undefined)
--
-- Security: Only members of the sysadmin fixed server role can execute this
--           procedure successfully. So for this procedure to function properly
--           as a startup procedure, the MSSQLServer service account must be a
--           member of the sysadmin role.
-- Requires Certificate signature for catalog access
CREATE PROCEDURE sys.sp_MScleanupmergepublisher_internal
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE @status_mask INT;
    DECLARE @published_mask INT;
    DECLARE @published_database_name SYSNAME;
    DECLARE @command NVARCHAR(4000);

    -- Security check: sysadmin only
    IF (ISNULL(IS_SRVROLEMEMBER('sysadmin'), 0) = 0)
    BEGIN
        RAISERROR(14260, 16, -1);
        RETURN (1);
    END;

    -- Masks off the databases with status that we don't want to deal with
    SELECT @status_mask = 32 | -- loading
                       64 | -- pre recovery
                       128 | -- recovering
                       256 | -- not recovered
                       512 | -- offline
                       1024; -- read only

    SELECT @published_mask = 4; -- Merge published

    DECLARE hPublishedDatabase CURSOR LOCAL FAST_FORWARD FOR
    SELECT name FROM sys.databases
    WHERE (status & @status_mask) = 0
    AND (category & @published_mask) <> 0;

    OPEN hPublishedDatabase;
    FETCH hPublishedDatabase INTO @published_database_name;

    WHILE (@@FETCH_STATUS <> -1)
    BEGIN
        SELECT @command = QUOTENAME(@published_database_name) + '.sys.sp_MScleanupmergepublisherdb';
        EXEC @command;

        -- Ignore errors
        FETCH hPublishedDatabase INTO @published_database_name;
    END;

    CLOSE hPublishedDatabase;
    DEALLOCATE hPublishedDatabase;
END;

但其实根本没必要,我们是可以直接通过左侧找到该存储过程,右键修改来查看

image-20240709183525097

排查系统存储过程的执行记录

默认 MSSQL 不会记录系统存储过程的执行,我们以 sp_who2 为例

USE master;
GO
EXEC sp_who2;
GO

image-20240709190542876

执行成功,我们看一下日志中是否存在记录

image-20240709190952955

并没有相关记录

目前还没有发现能够自动化判断是否存在恶意系统存储过程的工具,有的话,后续会添加进手册

2. 排查扩展存储过程

USE YourDatabaseName; -- 替换为实际的数据库名
SELECT name, type_desc, create_date, modify_date
FROM sys.all_objects
WHERE type = 'X'
ORDER BY modify_date DESC;

image-20240709201052752

MSSQL 中默认扩展存储过程不只是 xp_ 开头的存储过程,还有 sp_ 开头的存储过程,它们都是 DLL 起的,所以右键没有修改选项

image-20240709201208235

我们测试一下,执行扩展存储过程是否会留下记录

EXEC master..xp_dirtree 'C:\', 1, 1;

image-20240709193013388

看来 xp_dirtree 默认还是可以使用的,不需要 EXEC sp_configure 'xp_cmdshell', 1;RECONFIGURE;

我们看一下是否会留下日志

image-20240709193341119

也没有留下日志

直接使用 xp_cmdshell 会留下什么日志?

EXEC master..xp_cmdshell 'dir C:\';

image-20240709201901952

image-20240709201940969

可以看到,留下了两条日志,内容一样,这也就意味着如果攻击者贸然执行了 xp_cmdshell 是有可能在日志里留下痕迹的

如果以管理员权限配置可以执行 xp_cmdshell ,会留下什么日志

-- 启用 xp_cmdshell
EXEC sp_configure 'show advanced options', 1;
RECONFIGURE;
EXEC sp_configure 'xp_cmdshell', 1;
RECONFIGURE;

EXEC master..xp_cmdshell 'dir C:\';

image-20240709202214039

成功执行,我们去看一下日志情况

image-20240709202321159

产生了四条日志,本质上是两条,就告诉我们 show advanced options 配置项由 0 转为 1 ;xp_cmdshell 配置项由 0 转为 1

所以我们的排查也就分为两个方向

  • 根据日志排查
  • 根据常见和修改时间排查

根据修改时间排查的语句为

USE master;
GO

SELECT name, create_date, modify_date
FROM sys.all_objects
WHERE type = 'X'
ORDER BY modify_date DESC;

image-20240709202643408

像刚才的配置更改与创建和修改时间没关系,不会影响排查结果

假设 xp_prop_oledb_provider 是近期修改过的,与前面的时间截然不同,我们如何找到对应的 DLL 呢?

EXEC sp_helpextendedproc 'xxxxxxx';

image-20240709224932298

可以看到这里只有 dll 文件的名字,没有路径,它所在位置为

C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\Binn\XPStar.DLL

image-20240709225050665

路径里包含 MSSQL 版本信息,所以根据实际情况更改,该目录下的 DLL 文件基本都有签名

image-20240709225505975

如果是攻击者制定的 DLL 创建的存储过程,可能会显示出绝对路径

image-20240709225348800

对于扩展存储过程,无法直接修改其内容,直接右键删除就好,或者通过以下命令

USE master;
GO
EXEC sp_dropextendedproc N'YourMaliciousProc';
GO

image-20240709225739216

删除后,可以通过以下命令确定结果

SELECT 
    name, 
    type_desc 
FROM 
    sys.server_principals 
WHERE 
    type = 'X' 
AND 
    name = N'YourMaliciousProc';

image-20240709225838398

加载扩展存储过程会留下日志

image-20240709230013761

3. 用户自定义存储过程

用户自定义存储过程是每个数据库单独定义的,所以在检查的时候也要检查所有的数据库的用户自定义存储过程

数据库 -> 数据库名字 -> 可编程性 -> 存储过程

image-20240709231256717

默认情况下,只有系统存储过程一个节点,如果还有其他的,例如本案例中的 dbo.usp_GetCustomerInfo 就是用户自定义的存储过程,可以直接编辑并且可以删除

查找每一个数据库的自定义存储过程进行一一确认即可

0x06 程序集排查

在 Microsoft SQL Server 2016 中,程序集(Assemblies)是指托管代码(Managed Code)程序集,可以使用 .NET 框架编写并在 SQL Server 中托管和执行。通过使用程序集,开发人员可以编写复杂的逻辑,并将其集成到 SQL Server 中,以扩展其功能。

简单来说就是使用 .Net 语言编写程序,编译成DLL,之后加载进 MSSQL 中,之后 MSSQL 就可以使用该 DLL 中的功能,创建存储过程或者函数。

在 Microsoft SQL Server 中,程序集(Assemblies)是每个数据库单独使用的,而不是所有数据库共用的。每个数据库有自己的程序集空间,程序集在一个数据库中创建后,只能在该数据库内使用。

1. 查找当前数据库中的程序集

SELECT * FROM sys.assemblies;

image-20240709232327511

Microsoft.SqlServer.Types 应该是每个数据库默认的程序集,我们可以通过图形化的方式查看程序集

数据库 -> 数据库名称 -> 可编程性 -> 程序集

image-20240709232524047

2. 查找程序集对应的文件

SELECT * FROM sys.assembly_files;

image-20240709232616562

该文件所在路径为

C:\Windows\assembly\GAC_MSIL\Microsoft.SqlServer.Types\13.0.0.0__89845dcd8080cc91

image-20240709233232471

3. 添加恶意程序集日志

将以下 C# 代码保存为 MyStoredProcedures.cs

using System;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;

public class MyStoredProcedures
{
    [SqlProcedure]
    public static void HelloWorld()
    {
        SqlContext.Pipe.Send("Hello, world!");
    }
}

使用 csc.exe 编译成 DLL

csc /target:library /out:MyStoredProcedures.dll MyStoredProcedures.cs

image-20240709235231419

导入程序集

-- 导入程序集
CREATE ASSEMBLY MyStoredProcedures
FROM 'C:\Path\To\MyStoredProcedures.dll'
WITH PERMISSION_SET = SAFE

image-20240709234859286

刷新一下

image-20240709234922295

在程序集处成功显示出来,观察一下日志

image-20240709235040639

这里的日志显示的是 AppDomain 2 (MyDatabase.dbo[ddl].1)已卸载。

4. 删除程序集

image-20240709235516490

直接右键删除即可

或者通过 SQL 命令

-- 删除程序集
DROP ASSEMBLY MyStoredProcedures;

image-20240709235612110

刷新页面

image-20240709235712033

删除程序集不会记录日志

0x07 作业 (Job)

“作业”(Jobs)是一种自动化任务的机制,允许数据库管理员(DBA)和开发人员调度和执行一系列预定义的操作。这些作业可以在特定的时间点或根据预定的时间表自动运行,也可以由用户手动触发。

一个 SQL Server 作业通常包含以下组成部分:

  1. 作业名称:用来标识作业的唯一名称。
  2. 所有者:指定作业的拥有者,通常是 SQL Server 登录账户或 Windows 用户账户。
  3. 步骤:作业的一个步骤是一组可以执行的操作,比如运行 T-SQL 语句、执行存储过程、导入导出数据、发送电子邮件等。一个作业可以包含多个步骤,步骤之间可以有依赖关系,前一个步骤的执行结果可以决定后续步骤是否执行。
  4. 计划:定义作业何时运行的时间表,可以是一次性的,也可以是周期性的,比如每天、每周、每月等。
  5. 警报:可以配置作业在特定条件下触发警报,例如当作业失败时通知管理员。
  6. 通知:作业可以配置通知选项,以便在作业开始、完成或失败时发送电子邮件或短信给指定的收件人。
  7. 历史记录:SQL Server 作业保留执行历史记录,包括开始时间、结束时间、持续时间以及作业的状态(如成功、失败或正在运行)。
  8. 安全性:可以设置作业的安全级别,例如限制哪些用户可以查看或修改作业。

作业是由 SQL Server Agent 统一管理,这意味着作业是跨所有数据库的,或者说是在 SQL Server 实例级别的。SQL Server Agent 是一个服务,它负责调度和执行预先定义的任务,即作业

1. 获取所有的作业(Job)

USE msdb;
GO
SELECT * FROM dbo.sysjobs;
GO

image-20240710000920066

可以看到有一条作业,查看该作业详细信息

通过 job_id 查询更多信息

查询作业步骤

USE msdb;
GO

-- 作业步骤信息
SELECT *
FROM dbo.sysjobsteps
WHERE job_id = '267BA740-1476-49E2-9F5C-B3CDD78B1B9C';

image-20240710001405504

查询作业执行历史

USE msdb;
GO

SELECT *
FROM dbo.sysjobhistory
WHERE job_id = '267BA740-1476-49E2-9F5C-B3CDD78B1B9C';

image-20240710001502132

看来该作业从来没有执行过

当然也可以通过图形化获取作业信息

image-20240710001623101

可以看到,默认情况下被禁用了,我们右键启动

image-20240710001816255

image-20240710001911474

可以通过点击直接查看作业列表,并查看作业的详细信息,syspolicy_purge_history 是默认存在的

可以通过作业活动监视器查看作业活动情况

image-20240710002120255

可以通过错误日志查看作业产生的错误

image-20240710002201413

2. 新建作业

image-20240710002254043

查看日志

image-20240710002358723

并不会记录新建作业的日志

3. 删除作业

image-20240710002504735

0x08 函数排查

在 SQL Server 2016 中,用户可以创建两种类型的自定义函数:标量值函数和内聚表值函数(Table-Valued Functions)。标量值函数返回一个单一值,而表值函数可以返回一个结果集,类似于一个表。

每个数据库有自己的函数,MSSQL 2016 默认情况下,默认数据库以及新建的数据库均无以下函数

  • 标量值函数
  • 表值函数
  • 聚合函数

image-20240710003425105

0x09 数据库触发器

在 MSSQL 2016 中默认情况下默认数据库以及新建数据库均无数据库触发器

image-20240710003531794

0x10 其他内容

其他内容的排查就需要将受害现场与纯净的数据库管理系统进行对比了,对比出现的差异与开发、运维等相关人员确认