简介

在现代应用程序架构中,站库分离是一种常见的设计模式,旨在提高系统的可扩展性、安全性和性能。然而,在实际操作中,如何有效判断应用服务器和数据库服务器是否真正分离并运行在不同的物理或虚拟机上,在一些渗透测试中尝试通过SQL注入来写入文件却失败的场景就需要考虑的点。本文将探讨如何使用SQL Server中的 host_name() 和 @@servername 函数进行判断,分析其可靠性,并提供补充的验证方法。
正文
什么是站库分离?
站库分离是指在应用系统架构中,将应用程序(站点)与数据库(库)分别部署在不同的服务器上,而不是将两者部署在同一台服务器上。这种架构设计广泛应用于中大型系统中,尤其是在需要高性能、可扩展性和安全性的环境中。
站库分离的主要特点
-
物理隔离:
- 应用服务器与数据库服务器物理上分离,通常位于不同的机器、虚拟机或云服务上。
- 通过网络连接,应用服务器与数据库服务器进行通信。
-
独立扩展:
- 应用服务器和数据库服务器可以独立进行扩展。例如,可以在业务量增加时增加更多的应用服务器实例,而不需要更改数据库服务器,或反之亦然。
-
安全性增强:
- 由于数据库服务器与应用服务器分离,可以对数据库服务器进行更加严格的访问控制,限制只有应用服务器能够访问数据库,从而提高安全性。
-
性能优化:
- 将应用程序和数据库的负载分散到不同的服务器上,有助于减少资源竞争,提高系统的整体性能。
- 数据库服务器可以专注于处理数据库查询,而应用服务器专注于业务逻辑的处理。
站库分离的实现方式
-
单独的应用和数据库服务器:
- 最基本的实现方式是将应用服务器和数据库服务器部署在不同的物理或虚拟机上。
-
使用负载均衡:
- 多个应用服务器实例共享负载,而数据库服务器作为后端服务提供数据支持。
-
分布式数据库:
- 对于非常大型的系统,可以进一步将数据库分为多个实例或分片,分别存储不同的数据集,以便更好地扩展和优化性能。
host_name() 、serverproperty 与 @@servername 简介
host_name():返回的是发起当前数据库连接的客户端主机名,也就是从哪个客户端机器连接到数据库的主机名。@@servername:返回的是数据库服务器实例的名称,这通常是在安装 SQL Server 时设置的服务器名或实例名。serverproperty: 返回关于 SQL Server 实例的一些元数据(包括服务器的机器名称),常规用法之获取机器名,SELECT SERVERPROPERTY('MachineName');-
示例:
#同一个机器上 host_name() = 'DB-SERVER' @@servername = 'DB-SERVER' #站库分离 host_name() = 'WEB-SERVER-02' @@servername = 'PROD-SQL-INSTANCE'
通过 host_name() 和 @@servername 或 serverproperty 判断站库是否分离
- 站库分离的理想情况:
host_name()和@@servername不同 - 同名不同服务器的风险:名称相同但物理上分离的情况
- 可能的误判场景及原因:
-
自定义服务器名:数据库服务器和应用服务器可以配置相同的主机名,即使它们位于不同的物理机器上。这样,
host_name()和@@servername可能会返回相同的值,虽然服务器实际上是分离的。 -
负载均衡或克隆环境:在某些架构中,多个数据库实例可能共享相同的服务器名或配置。即使这些实例分布在不同的物理服务器上,它们的
host_name()和@@servername值也可能一致。
补充验证方法
- 检查 IP 地址:使用 host_name() 和
@@servername返回的名称获取它们的 IP 地址,比较是否一致。如果 host_name() 和@@servername的 IP 地址不同,站库很可能是分离的。 - 使用其他系统信息: 可以通过查询系统表、配置文件或使用一些系统函数(如 sys.dm_exec_connections、sys.dm_exec_sessions)来获取更详细的服务器和连接信息,进一步分析是否站库分离。
实战中如何通过SQL注入点如何判断
可通过如下SQL语句来进行判断二者是否相同
?id=1; IF host_name() = @@servername WAITFOR DELAY '0:0:5'--
如果查询引起了明显的延迟(如5秒钟),则可以推断host_name()和@@servername是相同的;如果没有延迟,则它们不同。
?id=1 AND (SELECT 1 WHERE host_name() = @@servername)--
?id=1 AND (SELECT CASE WHEN host_name() = @@servername THEN 1 ELSE 0 END) = 1--
如果host_name()和@@servername相同,那么CASE语句将返回1,整个查询将成功执行,并可能返回正常的页面。如果它们不同,则CASE语句将返回0,查询可能会失败或返回一个错误页面。
?id=1 UNION SELECT CASE WHEN host_name() = @@servername THEN 'SAME' ELSE 'DIFFERENT' END--
如果查询返回SAME,则表明host_name()和@@servername的值相同;如果返回DIFFERENT,则它们不相同。
最后,欢迎大家给出更多的方式来判断MSSQL是否站库分离!
其他-SERVERPROPERTY函数补充
SERVERPROPERTY 是 SQL Server 中的一个系统函数,用于返回有关 SQL Server 实例配置和状态的信息。它可以获取很多不同的属性,下面是一些常见的属性及其含义:
常见的 SERVERPROPERTY 属性
-
ProductVersion
- 描述: 返回 SQL Server 的版本号(例如:15.0.2070.41)。
- 示例:
SELECT SERVERPROPERTY('ProductVersion');
-
ProductLevel
- 描述: 返回 SQL Server 的版本级别(RTM、SP1、SP2 等)。
- 示例:
SELECT SERVERPROPERTY('ProductLevel');
-
Edition
- 描述: 返回 SQL Server 的版本类型(例如:Enterprise, Standard, Express)。
- 示例:
SELECT SERVERPROPERTY('Edition');
-
EngineEdition
- 描述: 返回 SQL Server 引擎的版本号。常见的返回值有:
- 1 = Personal or Desktop Engine
- 2 = Standard
- 3 = Enterprise
- 4 = Express
- 5 = SQL Database
- 示例:
SELECT SERVERPROPERTY('EngineEdition');
- 描述: 返回 SQL Server 引擎的版本号。常见的返回值有:
-
MachineName
- 描述: 返回运行 SQL Server 实例的物理或虚拟机器的名称。
- 示例:
SELECT SERVERPROPERTY('MachineName');
-
IsClustered
- 描述: 返回一个值,指示 SQL Server 实例是否在群集服务器上运行。
- 1 = 是群集实例
- 0 = 不是群集实例
- 示例:
SELECT SERVERPROPERTY('IsClustered');
- 描述: 返回一个值,指示 SQL Server 实例是否在群集服务器上运行。
-
Collation
- 描述: 返回 SQL Server 实例的默认排序规则。
- 示例:
SELECT SERVERPROPERTY('Collation');
-
IsIntegratedSecurityOnly
- 描述: 返回一个值,指示 SQL Server 是否只允许集成安全性。
- 1 = 只允许集成安全性
- 0 = 允许 SQL Server 和集成安全性
- 示例:
SELECT SERVERPROPERTY('IsIntegratedSecurityOnly');
- 描述: 返回一个值,指示 SQL Server 是否只允许集成安全性。
-
IsFullTextInstalled
- 描述: 返回一个值,指示是否安装了全文搜索功能。
- 1 = 安装了全文搜索
- 0 = 没有安装全文搜索
- 示例:
SELECT SERVERPROPERTY('IsFullTextInstalled');
- 描述: 返回一个值,指示是否安装了全文搜索功能。
-
EditionID
- 描述: 返回 SQL Server 版本的内部数值标识符。
- 示例:
SELECT SERVERPROPERTY('EditionID');
-
EngineEdition
- 描述: 返回 SQL Server 引擎版本的类型。
- 示例:
SELECT SERVERPROPERTY('EngineEdition');
-
InstanceName
- 描述: 返回 SQL Server 实例的名称。如果是默认实例,则返回空字符串。
- 示例:
SELECT SERVERPROPERTY('InstanceName');
使用注意
每个属性都会返回一个特定的数据类型(通常是字符串或整数),并且根据属性不同,有时返回值会在不同的 SQL Server 版本之间有所变化。
你可以根据需求查询特定的属性,以便获取有用的信息。例如,以下查询可以一次性获取多个属性的值:
SELECT
SERVERPROPERTY('ProductVersion') AS ProductVersion,
SERVERPROPERTY('ProductLevel') AS ProductLevel,
SERVERPROPERTY('Edition') AS Edition,
SERVERPROPERTY('EngineEdition') AS EngineEdition,
SERVERPROPERTY('MachineName') AS MachineName;
这个查询将返回 SQL Server 实例的版本信息、版本级别、版本类型、引擎版本以及运行该实例的机器名称。


