<返回更多

从mimikatz学习Windows安全之访问控制模型

2021-08-18    Hbo涵
加入收藏

「网络安全」从mimikatz学习Windows安全之访问控制模型

 

前言

在本篇文章中,主要介绍sid相关的概念,并介绍mimikatz的sid模块,着重分析sid::patch功能的原理。

SID简介

1. 安全标识符(SID)

windows操作系统中,系统使用安全标识符来唯一标识系统中执行各种动作的实体,每个用户有SID,计算机、用户组和服务同样也有SID,并且这些SID互不相同,这样才能保证所标识实体的唯一性

SID一般由以下组成:

「网络安全」从mimikatz学习Windows安全之访问控制模型

 

Windows也定义了一些内置的本地SID和域SID来表示一些常见的组或身份

SID

Name

S-1-1-0

World

S-1-3-0

Creator Owner

S-1-5-18

Local SYSTEM

S-1-5-11

Authenticated Users

S-1-5-7

Anonymous

2. AD域中的SID

在AD域中,SID同样用来唯一标识一个对象,在LDAP中对应的属性名称为objectSid:

「网络安全」从mimikatz学习Windows安全之访问控制模型

 

重点需要了解的是LDAP上的sIDHistory属性

(1) SIDHistory

SIDHistory是一个为支持域迁移方案而设置的属性,当一个对象从一个域迁移到另一个域时,会在新域创建一个新的SID作为该对象的objectSid,在之前域中的SID会添加到该对象的sIDHistory属性中,此时该对象将保留在原来域的SID对应的访问权限

比如此时域A有一个用户User1,其LDAP上的属性如下:

cn

objectSid

sIDHistory

User1

S-1-5-21-3464518600-3836984554-627238718-2103

null

此时我们将用户User1从域A迁移到域B,那么他的LDAP属性将变为:

cn

objectSid

sIDHistory

User1

S-1-5-21-549713754-3312163066-842615589-2235

S-1-5-21-3464518600-3836984554-627238718-2103

此时当User1访问域A中的资源时,系统会将目标资源的DACL与User1的sIDHistory进行匹配,也就是说User1仍具有原SID在域A的访问权限

值得注意的是,该属性不仅在两个域之间起作用,它同样也可以用于单个域中,比如实战中我们将一个用户A的sIDHistory属性设置为域管的objectSid,那么该用户就具有域管的权限

另一个实战中常用的利用,是在金票中添加Enterprise Admins组的SID作为sIDHistory,从而实现同一域林下的跨域操作,这个将在后面关于金票的文章中阐述

(2) SID Filtering

SID Filtering简单地说就是跨林访问时目标域返回给你的服务票据中,会过滤掉非目标林中的SID,即使你添加了sIDHistory属性。SID Filtering在信任中默认开启,在单林中默认关闭

 

mimikatz的sid模块

1. sid::lookup

该功能实现SID与对象名之间的相互转换,有三个参数:

「网络安全」从mimikatz学习Windows安全之访问控制模型

 

2. sid::query

该功能支持通过SID或对象名来查询对象的信息,同样有三个参数,使用时指定/sam/sid/system可选

「网络安全」从mimikatz学习Windows安全之访问控制模型

 

这个功能其原理就是直接使用LDAP查询,通过sAMAccountName查询对应的objectSid,或者通过objectSid查询对应的sAMAccountName

其核心是调用Windows一系列的LDAP操作API,主要是ldap_search_s():

「网络安全」从mimikatz学习Windows安全之访问控制模型

 

3. sid::modify

该功能用于修改一个域对象的SID,可以使用的参数有三个:

使用该功能是需要先使用sid::patch功能对xxxx进行patch(自然也需要先开启debug特权),需要在域控上执行

「网络安全」从mimikatz学习Windows安全之访问控制模型

 

修改时的操作就很简单了,调用LDAP操作的API对域对象的objectSid进行修改,主要使用的是ldap_modify_s():

「网络安全」从mimikatz学习Windows安全之访问控制模型

 

4. sid::add

该功能用来向一个域对象添加sIDHistoy属性,有两个参数:

使用该功能也要先执行sid::patch,修改时同样是操作LDAP通过ldap_modify_s()修改,不再赘述

「网络安全」从mimikatz学习Windows安全之访问控制模型

 

5. sid::clear

该功能用来清空一个对象的sIDHistory属性

「网络安全」从mimikatz学习Windows安全之访问控制模型

 

原理就是使用ldap_modify_s()将目标对象sIDHistory属性修改为空

6. sid::patch

对域控LDAP修改过程中的验证函数进行patch,需要在域控上执行,该功能没有参数

patch共分为两个步骤,如果仅第一步patch成功的话,那么可以使用sid::add功能,两步都patch成功的话才可以使用sid::modify功能

「网络安全」从mimikatz学习Windows安全之访问控制模型

 

sid::patch分析

sid::patch在系统版本 < Vista时,patch的是samss服务中ntdsa.dll的内存,更高版本patch的是ntds服务中ntdsai.dll的内存

「网络安全」从mimikatz学习Windows安全之访问控制模型

 

整个patch过程分为两步:

  1. 第一步patch的是SampModifyLoopbackCheck()的内存
  2. 第二步patch的是ModSetAttsHelperPreProcess()的内存
「网络安全」从mimikatz学习Windows安全之访问控制模型

 

我们以Windows Server 2012 R2环境为例来分析,首先我们需要找到NTDS服务所对应的进程,我们打开任务管理器选中NTDS服务,单击右键,选择“转到详细信息”就会跳转到对应进程,这里NTDS服务对应的进程是lsass.exe

「网络安全」从mimikatz学习Windows安全之访问控制模型

 

1. 域控对LDAP请求的处理

大致分析一下域控对本地LDAP修改请求的过滤与处理流程,当我们修改objectSid和sIDHistory时,SampModifyLoopbackCheck()会过滤我们的请求,即使绕过该函数修改objectSid时,仍会受到SysModReservedAtt()的限制

侵入式切换到lsass进程并重新加载用户态符号表:

「网络安全」从mimikatz学习Windows安全之访问控制模型

 

给两个检查函数打断点

「网络安全」从mimikatz学习Windows安全之访问控制模型

 

此时我们修改一个用户的描述来触发LDAP修改请求

「网络安全」从mimikatz学习Windows安全之访问控制模型

 

命中断点后的调用栈如下:

「网络安全」从mimikatz学习Windows安全之访问控制模型

 

SampModifyLoopbackCheck()函数中存在大量Check函数,通过动态调试发现修改sIDHistoy的请求经过该函数后便会进入返回错误代码的流程

「网络安全」从mimikatz学习Windows安全之访问控制模型

 

继续调试到下一个断点

「网络安全」从mimikatz学习Windows安全之访问控制模型

 

在SysModReservedAtt()执行结束后,正常的修改请求不会在jne处跳转,而当修改objectSid时会在jne处跳转,进入返回错误的流程

「网络安全」从mimikatz学习Windows安全之访问控制模型

 

2. Patch 1/2

当我们想要进行内存patch时,通常会寻找目标内存地址附近的一块内存的值作为标记,编写程序时首先在内存中搜索该标记并拿到标记的首地址,然后再根据偏移找到要patch的内存地址,然后再进行相应的修改操作

mimikatz正是使用这种方法,其在内存中搜索的标记在代码中有明确的体现:

「网络安全」从mimikatz学习Windows安全之访问控制模型

 

我们将域控的ntdsai.dll拿回本地分析,在其中搜索标记41 be 01 00 00 00 45 89 34 24 83

「网络安全」从mimikatz学习Windows安全之访问控制模型

 

这一部分内容是在函数SampModifyLoopbackCheck()函数的流程中,我们可以使用windbg本地调试对比一下patch前后的函数内容

首先我们找到lsass.exe的基址并切换到该进程上下文:

「网络安全」从mimikatz学习Windows安全之访问控制模型

 

使用lm列出模块,可以看到lsass进程中加载了ntdsai.dll,表明此时我们可以访问ntdsai.dll对应的内存了

「网络安全」从mimikatz学习Windows安全之访问控制模型

 

我们直接查看SampModifyLoopbackCheck()函数在内存中的反汇编

「网络安全」从mimikatz学习Windows安全之访问控制模型

 

为了对比patch前后的区别,我们使用mimikatz执行sid::patch,然后再查看函数的反汇编。如下图所示,箭头所指处原本是74也就是je,而patch后直接改为eb即jmp,使流程直接跳转到0x7ffc403b2660

「网络安全」从mimikatz学习Windows安全之访问控制模型

 

而0x7ffc403b2660处的代码之后基本没有条件检查的函数了,恢复堆栈和寄存器后就直接返回了,这样就达到了绕过检查逻辑的目的

3. Patch 2/2

同理,按照mimikatz代码中的标记搜索第二次patch的位置0f b7 8c 24 b8 00 00 00

「网络安全」从mimikatz学习Windows安全之访问控制模型

 

查看ModSetAttsHelperPreProcess()处要patch的内存,patch前如下图所示

「网络安全」从mimikatz学习Windows安全之访问控制模型

 

patch完成后内存如下图,其实本质是让SysModReservedAtt()函数失效,在内存中寻找到标记后偏移-6个字节,然后将验证后的跳转逻辑nop掉

「网络安全」从mimikatz学习Windows安全之访问控制模型

 

4. 解决patch失败的问题

由于mimikatz中内存搜索的标记覆盖的windows版本不全,所以经常会出现patch失败的问题。例如在我的Windows Server 2016上,第二步patch就会失败,这种情况多半是因为mimikatz中没有该系统版本对应的内存patch标记

「网络安全」从mimikatz学习Windows安全之访问控制模型

 

此时我们只需要将目标的ntdsai.dll拿下来找到目标地址

「网络安全」从mimikatz学习Windows安全之访问控制模型

 

然后修改为正确的内存标记和对应的偏移地址即可,如果新增的话记得定义好版本号等信息

「网络安全」从mimikatz学习Windows安全之访问控制模型

 

此时重新编译后就可以正常patch了

「网络安全」从mimikatz学习Windows安全之访问控制模型

 

渗透测试中的应用

在渗透测试中的利用,一个是使用SIDHistory属性来留后门,另一个是修改域对象的SID来实现域内的“影子账户”或者跨域等操作

1. SIDHistoy后门

拿下域控后,我们将普通域用户test1的sIDHistory属性设置为域管的SID:

「网络安全」从mimikatz学习Windows安全之访问控制模型

 

此时test1将具有域管权限,我们可以利用这个特性来留后门

「网络安全」从mimikatz学习Windows安全之访问控制模型

 

2. 域内“影子账户”

假设我们此时拿到了域控,然后设置一个普通域用户的SID为域管的SID

「网络安全」从mimikatz学习Windows安全之访问控制模型

 

此时我们这个用户仍然只是Domain Users组中的普通域成员

「网络安全」从mimikatz学习Windows安全之访问控制模型

 

但该用户此时已经具有了域管的权限,例如dcsync:

并且此时也可以用该用户的账号和密码登录域控,登录成功后是administrator的session。但该操作很有可能造成域内一些访问冲突(猜测,未考证),建议在生产环境中慎用

3. 跨域

通常我们拿到一个域林下的一个子域,会通过黄金票据+SIDHistory的方式获取企业管理员权限,控制整个域林

除了这种方法,我们也可以直接修改当前子域对象的sIDHistory属性,假设我们现在拿到一个子域域控,通过信任关系发现存在一个父域,此时我们无法访问父域域控的CIFS

「网络安全」从mimikatz学习Windows安全之访问控制模型

 

但我们给子域域管的sIDHistory属性设置为父域域管的SID

「网络安全」从mimikatz学习Windows安全之访问控制模型

 

此时就可以访问父域域控的CIFS了:

「网络安全」从mimikatz学习Windows安全之访问控制模型

 

声明:本站部分内容来自互联网,如有版权侵犯或其他问题请与我们联系,我们将立即删除或处理。
▍相关推荐
更多资讯 >>>