MSSQL学习
来学习一下MSSQL相关的安全知识,不能只学MySQL
这里找到一位大佬的文章,跟着这个来逐步学习:https://github.com/aleenzz/MSSQL_SQL_BYPASS_WIKI
MSSQL介绍
简介
MSSQL也叫Microsoft SQL Server。
SQL Server是由Microsoft开发和推广的**关系数据库管理系统(DBMS)**;
SQL Server使用方便,伸缩性好与相关软件集成程度高;
SQL Server 数据库引擎为关系型数据和结构化数据提供了更安全可靠的存储功能。
SQL Server各服务作用
- SQL Server(MSSQLSERVER)是必须要开启的,这个是数据库引擎服务,它就像汽车的发动机一样,缺它不可。
- SQL Server代理(MSSQLSERVER)是代理服务,比如你有一些自动运行的,定时作业,或者是一些维护计划,比如定时备份数据库等操作,那么就要打开,否则,就不会备份数据库了。
- SQL Server Analysis Services (MSSQLSERVER)是分析服务,一般不用开启,除非你做多位分析,和数据挖掘,才需要开启。
- SQL Full-text Filter Daemon Launcher (MSSQLSERVER)是全文检索服务,如果你没有使用全文检索技术,那么也不需要开启。
- SQL Server VSS Writer MicrosoftSQLServer的SQL编写器服务,允许备份和还原应用程序以便在VolumeShadowCopyService(VSS)框架中进行操作。
- Sql Browser 服务 一般你要进行远程访问,不需要开启sql browser,通过:服务器ip,端口 这种方式就可以访问远程的服务器。
下面安装MSSQL2008的版本用来学习。
MSSQL基础知识
一些默认库
- master //用于记录所有SQL Server系统级别的信息,这些信息用于控制用户数据库和数据操作。
- model //SQL Server为用户数据库提供的样板,新的用户数据库都以model数据库为基础
- msdb //由 Enterprise Manager和Agent使用,记录着任务计划信息、事件处理信息、数据备份及恢复信息、警告及异常信息
- tempdb //它为临时表和其他临时工作提供了一个存储区。
sqlserver使用的两个端口,TCP-1433,UDP-1434
mssql注入常要打交道的库也就是 master,其中储存了所有数据库名与存储过程。类比于 MySQL 中的
information_schema
元数据库权限:2008之前,为system、2008及其以后权限不再为system
下面命令可以查询所有数据库名:
|
下列命令用来查询对象名及其类型:
|
下面是一些在 SQL Server 中用于描述对象类型的缩写或标识符。它们通常在系统表中使用,以区分不同种类的数据库对象。
|
存储过程
储存过程是一个可编程的函数,它在数据库中创建并保存。它可以有SQL语句和一些特殊的控制结构组成。当希望在不同的应用程序或平台上执行相同的函数,或者封装特定功能时,存储过程是非常有用的。数据库中的存储过程可以看做是对编程中面向对象方法的模拟。它允许控制数据的访问方式。
可以理解为一个函数调用的过程
常用的危险存储过程及其作用
|
一些字符
注释符
|
空白符
|
特殊一点的运算符
|
语法定义符号
|
常用函数
- 聚合函数:
SUM()
:计算某列的总和。COUNT()
:计算某列的行数。AVG()
:计算某列的平均值。MIN()
:找到某列的最小值。MAX()
:找到某列的最大值。
- 字符串函数:
LEN()
:返回字符串的长度。UPPER()
:将字符串转换为大写。LOWER()
:将字符串转换为小写。SUBSTRING()
:提取部分字符串。CONCAT()
:将多个字符串连接在一起。ASCII()
: 将字符转换成对应的ASCII码- char(): 将ASCII转换成对应的字符
- 日期和时间函数:
GETDATE()
:返回当前日期和时间。DATEPART()
:返回日期或时间部分的值(如年、月、日、小时、分钟等)。DATEDIFF()
:计算两个日期之间的差值。DATEADD()
:在日期上添加或减去指定的时间间隔。
- 数学函数:
ABS()
:返回数值的绝对值。ROUND()
:将数值四舍五入到指定的小数位数。FLOOR()
:返回不大于指定数值的最大整数。CEILING()
:返回不小于指定数值的最小整数。POWER()
:计算一个数的指定次幂。
- 逻辑函数:
IF()
或IIF()
:根据条件返回不同的值。CASE
表达式:根据条件选择不同的结果。
mssql还有一个特有的函数用来延迟一段时间,mysql则是用sleep
|
信息搜集
基本信息
|
判断是否站库分离
|
或者可以通过xp_cmshell来判断,这里先开启xp_cmdshell
|
xp_cmdshell是默认关闭的为0,需要先开启它才行
使用sp_cocnfigure 可以修改服务器配置
我们通过使用xp_cmdshell就可以判断出当前用户的权限,比如MSSQL2005的权限一般是system 而2008是nt authority\network service,在上图中也有显示。
判断当前是否为mssql
|
权限判断
IS_SRVROLEMEMBER('role' [, 'login'])
函数是 SQL Server 中的一个内置函数,用于检查指定登录名(login)是否属于指定的服务器角色(role),不指定用户名就默认当前登录用户名。用来判断服务器角色
下面是一些固定角色:
服务器级的固定角色 | 描述 |
---|---|
sysadmin | sysadmin 固定服务器角色的成员可以在服务器上执行任何活动。 |
serveradmin | serveradmin 固定服务器角色的成员可以更改服务器范围的配置选项和关闭服务器。 |
securityadmin | securityadmin 固定服务器角色的成员可以管理登录名及其属性。 他们可以 GRANT 、DENY 和 REVOKE 服务器级权限。 他们还可以 GRANT 、DENY 和 REVOKE 数据库级权限(如果他们具有数据库的访问权限)。 此外,他们还可以重置 SQL Server 登录名的密码。 重要说明: 如果能够授予对 数据库引擎 的访问权限和配置用户权限,安全管理员可以分配大多数服务器权限。 securityadmin 角色应视为与 sysadmin 角色等效。 |
processadmin | processadmin 固定服务器角色的成员可以终止在 SQL Server 实例中运行的进程。 |
setupadmin | setupadmin 固定服务器角色的成员可以使用 Transact-SQL 语句添加和删除链接服务器。 (使用 Management Studio 时需要 sysadmin 成员资格。) |
bulkadmin | bulkadmin 固定服务器角色的成员可以运行 BULK INSERT 语句。 |
diskadmin | diskadmin 固定服务器角色用于管理磁盘文件。 |
dbcreator | dbeator 固务器角色的成员可以创建、更改、删除和还原任何数据库。 |
puic | 每个 SQL Server 登录名都属于 public 服务器角色。 如果未向某个服务器主体授予或拒绝对某个安全对象的特定权限,该用户将继承授予该对象的 public 角色的权限。 只有在希望所有用户都能使用对象时,才在对象上分配 Public 权限。 你无法更改具有 Public 角色的成员身份。 注意plic 与其他角色的实现方式不同,可通过 public 固定服务器角色授予、拒绝或调用权限。 |
数据库级别角色使用IS_MEMBER('role')来判断
固定数据库角色名 | 描述 |
---|---|
db_owner | db_owner 固定数据库角色的成员可以执行数据库的所有配置和维护活动,还可以删除 SQL Server中的数据库。 (在 SQL 数据库 和 SQL 数据仓库中,某些维护活动需要服务器级别权限,并且不能由 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_denydatawriter | db_denydatawriter 固定数据库角色的成员不能添加、修改或删除数据库内用户表中的任何数据。 |
db_denydatareader | db_denydatareader 固定数据库角色的成员不能读取数据库内用户表中的任何数据。 |
返回类型:
返回值 | 描述 |
---|---|
0 | login 不是 role 的成员。 |
1 | login 是 role 的成员。 |
NULL | role 或 login 无效,或者没有查看角色成员身份的权限。 |
MSSQL注入流程
由于网上没有现成靶场需要自己搭一个测试,参考文章:https://macchiato.ink/web/web_security/mssql_injection_setup/#0x03-web%E6%9C%8D%E5%8A%A1%E5%AE%89%E8%A3%85
开iis的时候记得要勾选.net扩展不然解析不了
最后搭好大概就是这样
注入流程
- 获取数据库名
- 获取数据库的表名
- 获取数据库的字段名
- 获取对应的数据
主要系统表
- sysdatabases :这张表保存在master数据库中,里边的name字段下存放的是所有数据库的库名。
- sysobjects:这张表保存的是数据库的表的信息,里边的id字段存放的是表的id,name为表名,xtype 字段存放的是表的类型,u代表为用户创建的表,s表示该表是系统表。
- syscolumns:这张表存放的是数据库中字段的信息,id 为表的id,该id可以通过sysobjects获得。name为字段名称。
报错注入
获取数据库名
利用db_name()来获取
|
还可以使其报错来获取库名
|
爆表名
|
爆列名
|
爆数据
|
|
报错注入只能查询一个一个值,但是mssql没有limit这种东西,就只能用top加上判断来遍历数据。
但是这里的message_id和数字类型一样就要换其他类型来进行报错回显,但是试了一下发现不行,应该要是查询的那部分出错才会显示出来
但是当联合查询可用又知道列数时可以直接像上面一样全部查出,可以利用order by来判断列数。
order by 5不报错证明就有5列数据。
显式转换报错
上面的都是隐式转换类型来报错获得信息,mssql中还有两个函数用于显式转换
|
下面拿一个varchar数据来进行示例
|
联合注入
联合注入前先使用order by判断列数,上面有提到过。
查询的时候如果发现数据类型不兼容可以用NULL替换。
获取数据库名
|
这里除了数据类型要一样每个列的排序规则也要一样不然会报错,上面的COLLATE就是用来转换排序规则的,不转换就会报下面的错误
获取数据库表名
|
获取指定表的字段名
|
获取字段具体的值
|
盲注
判断数据库个数
|
获取数据库信息
|
类似mysql盲注一样,遍历字符的布尔盲注
其余的查询就不写了,在上面的联合注入中一个字符一个字符遍历即可
简单的绕过注入
这里介绍一个declare函数,他是mssql声明局部变量的函数,可以用它来绕过waf对一些关键词的拦截。
一般语法
|
可以给变量赋初始值,也可以不赋值。
声明多个变量
|
用法示例
|
|
绕过示例
|
嘶怪了,在浏览网页的时候不报错,单独测试了一下每个命令都是执行了的啊,而且在SSMS中又是有效的,不知道为啥。
变量的值是支持hex和ascii码的,当过滤引号时可以把我们的语句编码一下
|