Windows原理深入学习系列-访问控制列表

这是[信安成长计划]的第 19 篇文章

0x00 目录

0x01 介绍

0x02 DACL

0x03 创建DACL

0x04 文件读取测试

0x05 进程注入测试

0x06 原理分析 Win10_x64_20H2

0x07 参考文章

在最后分析的时候纠正一下网上大批分析文章中的一个错误,东西只有自己实践了才知道

0x01 介绍

在上一篇讲强制完整性控制的时候提到过,在权限检查的时候,会先进行强制完整性检查,然后再进行 DACL 检查,DACL 就是包含在这次要提到的 ACL 当中的。

访问控制列表(Access Control List,ACL),其中的每一项叫做访问控制条目(Access Control Entries,ACE)。

访问控制列表是属于安全对象的安全描述符的,根据文档可以看出来,安全描述符中包含了两个跟 ACL 相关的信息,DACL(discretionary access control list)和 SACL(system access control list)

DACL 可以对发起请求的用户或者组进行权限控制,允许或者拒绝它们的访问

SACL 使监视对受保护对象的访问成为可能,其信息会在安全日志中被记录

Windows原理深入学习系列-访问控制列表_第1张图片

那所谓的安全对象又是什么,根据微软提供的文档可以发现,文件、目录、进程、线程、注册表、服务、管道、打印机、网络共享等等都属于安全对象,也就意味着它们都拥有 DACL 和 SACL,也就说明了所有这些内容都是可以进行权限控制和日志记录的。

说了这么多,那到底 DACL 和 SACL 都是什么东西,这其实就是我们平时最常见的安全属性界面

Windows原理深入学习系列-访问控制列表_第2张图片

DACL、SACL、ACE 分别对应的就是下面这些

Windows原理深入学习系列-访问控制列表_第3张图片

接下来我们重点来说一下 DACL

0x02 DACL

对于 DACL 的不同情况,Windows 也会有不同的处理方式

如果安全描述符中没有 DACL,即 DACL 为 NULL,Windows 会允许任何用户的完全访问权限。

如果有 DACL,但是 DACL 为空,即没有 ACE,Windows 将不允许任何用户的任何访问

如果有 DACL,也有 ACE,Windows 将会依次检查 ACE,直到找到一个或多个 ACE 允许所有请求的访问权限,或者直到任何请求的访问权限被拒绝

对于前两种就不必多说了,主要来说一下第三种情况,这里就借用微软的图来说一下

Windows原理深入学习系列-访问控制列表_第4张图片

Thread A 拥有 Andrew 的访问令牌,当 Thread A 访问 Object 对象的时候,会从 DACL 中的第一个 ACE 开始检查,第一个权限是 Access denied,用户名是 Andrew,刚好与 Thread A 相同,就发生了拒绝访问。

Thread B 拥有 Jane 的访问令牌,当 Thread B 访问 Object 对象的时候,也会从第一个 ACE 开始检查,第一个并不满足;然后检查第二个,Group A 的允许写,而 Jane 是属于 Group A 的,所以获得了写的权限;然后检查第三个,Everyone 有读和执行权限,所以 Thread B 就有了读、写、执行权限。

根据上面这个例子也能够看出来,ACE 顺序的重要性,如果第一个不是对 Andrew 的禁止的话,Thread A 就已经获取到权限了。

同时 ACE 也是可以被继承的,在每个 ACE 中都有一个专门标记与继承相关信息的标志位,一般最常见的就是全继承,父对象与子对象具有相同的权限控制和审计设置。

需要注意的是,继承而来的 ACE,在子对象中是不能进行修改的,找两个例子就可以看出来了

这一项是没有被继承的,权限位是可以进行修改的

Windows原理深入学习系列-访问控制列表_第5张图片

如果是继承的话,所有的权限位直接为灰色,不可修改

Windows原理深入学习系列-访问控制列表_第6张图片

0x03 创建DACL

先说一个小插曲,刚开始的时候,我还想着 ProcessHacker 会有相关的代码,是不是可以直接拿来用了,然后在源码里翻了半天,并没有发现有相关的代码,最后在 ProcessHacker 官方论坛上发现了如下的对话

Windows原理深入学习系列-访问控制列表_第7张图片

EditSecurity 函数上面写的很清楚,这个展示页是专门让用户编辑 ACE 的,它属于一个专门的 DLL,名字是 Aclui.dll

Windows原理深入学习系列-访问控制列表_第8张图片

除了使用上面那样在图形化界面中修改之外,还可以通过 API 来进行处理

整个的流程微软也已经列出来了 https://docs.microsoft.com/en-us/windows/win32/secbp/creating-a-dacl

唯一感觉不甚友好的就是设置其权限时候所使用的 SDDL,这个可读性确实是有点差了

Windows原理深入学习系列-访问控制列表_第9张图片

这里就不实践了,相关的文档,还有一份大佬的博客,我一起放到最后的参考链接当中

还可以通过我们上一篇文章中所提到的命令行工具 icacls 来完成,它在示例当中也描述的很清楚了

Windows原理深入学习系列-访问控制列表_第10张图片

除此之外,PowerShell 真是个好东西,有一个 Get-Acl 命令也可以查询

Windows原理深入学习系列-访问控制列表_第11张图片

它也能获取注册表的访问权限

Windows原理深入学习系列-访问控制列表_第12张图片

就查看的信息而言,也更加的清晰了

Windows原理深入学习系列-访问控制列表_第13张图片

当然,也能使用 Set-Acl 命令对其进行修改,大佬的文章链接我直接贴到最后的参考文献里

0x04 文件读取测试

首先我们先看一下文件当前的 ACL

Windows原理深入学习系列-访问控制列表_第14张图片

由于当前用户属于 Administrator 组,所以读取是没有问题的

Windows原理深入学习系列-访问控制列表_第15张图片

然后手动删除掉权限,由于当前的权限都是继承过来的,所以无法直接删除

Windows原理深入学习系列-访问控制列表_第16张图片

但是在编辑框中可以很方便的禁用继承关系,我们可以直接禁用掉,最好还是选择第一个,因为当前所有的 ACE 都是继承过来的,如果删除掉所有的继承权限的话,当前的 DACL 就会变成一个空的 DACL,那将无法进行访问了!

Windows原理深入学习系列-访问控制列表_第17张图片

然后对权限进行删除,这里我只保留了 SYSTEM 权限

Windows原理深入学习系列-访问控制列表_第18张图片

访问直接就被拒绝了

Windows原理深入学习系列-访问控制列表_第19张图片

0x05 进程注入测试

与上次一样,我们还是使用 RDI 来进行测试

先起一个 notepad 进程,可以发现我们的当前账户 admin 是拥有完全控制权限的

Windows原理深入学习系列-访问控制列表_第20张图片

然后使用 RDI 来进行注入,一切正常

Windows原理深入学习系列-访问控制列表_第21张图片

接下来再找一个当前没有权限的来尝试一下注入,为了排除完整性带来的干扰,我们直接修改这个 notepad 的 ACE,直接删除当前用户

Windows原理深入学习系列-访问控制列表_第22张图片

然后再来进行测试,可以发现,直接无法打开目标进程了,返回的错误码是拒绝访问

Windows原理深入学习系列-访问控制列表_第23张图片

0x06 原理分析 Win10_x64_20H2

我们以这个 winlogon 为例

Windows原理深入学习系列-访问控制列表_第24张图片

先取到 EPROCESS 结构

Windows原理深入学习系列-访问控制列表_第25张图片

看一下对象头的结构,SecurityDescriptor 存在里面,这一点我们在刚开始的时候也说过了

Windows原理深入学习系列-访问控制列表_第26张图片

要取到当前进程的结构头,这里需要注意的是,SecurityDescriptor 与 Token 一样,最后四位都是一个快速引用的东西(虽然现在还不太明白是干什么用的)

Windows原理深入学习系列-访问控制列表_第27张图片

接着就来看一下 _SECURITY_DESCRIPTOR 结构当中到底存储了哪些内容

Windows原理深入学习系列-访问控制列表_第28张图片

虽然能够看到 SACL、DACL 等信息,但是有点问题,这些地址很明显是不正确的,它们明显不是地址,也是读不出来的

Windows原理深入学习系列-访问控制列表_第29张图片

经过查找,发现网上在碰到这里的时候,都没有看这个结构的数据,直接从首地址加上 0x30 的偏移找到 DACL,为了能更好的明白 Windows 在这个时候在做什么,可以一个与获取 DACL 有关的函数

Windows原理深入学习系列-访问控制列表_第30张图片

通过微软文档可以看到这个函数所用到的参数

Windows原理深入学习系列-访问控制列表_第31张图片

这里的 r8 寄存器就是用来存储返回的 Dacl 的指针,如果按照 _SECURITY_DESCRIPTOR 结构来验证的话,这里先取到了 Group 中的值,然后加上 _SECURITY_DESCRIPTOR 的地址,最后直接返回给了 r8,这在逻辑上是完全讲不通的

Windows原理深入学习系列-访问控制列表_第32张图片

但是就在分析的时候,无意中发现了另外的一个结构 _SECURITY_DESCRIPTOR_RELATIVE,看名字当前的位置应该都是相对偏移了,感觉有可能是正确的

Windows原理深入学习系列-访问控制列表_第33张图片

再拿刚刚的逻辑来分析一下,很明显是对的上了

Windows原理深入学习系列-访问控制列表_第34张图片

那就回到前面,继续用这个结构进行分析,可以看到 Dacl 处的 0x30 偏移,这也就是网上都在说结构错了,需要 +0x30 才能找到 Dacl 的真正原因

Windows原理深入学习系列-访问控制列表_第35张图片

按照刚刚分析函数的逻辑,可以直接取到 DACL 的地址

Windows原理深入学习系列-访问控制列表_第36张图片

因为它们还是 ACL 结构的,所以继续查看结构体,可以看到当前 ACL 的大小是 0x3c,当前 ACL 当中有 2 个 ACE

Windows原理深入学习系列-访问控制列表_第37张图片

接下来应该查找 ACE 了,但是并没有发现与 ACE 有关的结构,经过搜索,发现在 Win32 的 API 里有一个与 ACE 有关的结构 _ACE_HEADER,可以看到里面有 ACE 的类型、大小等信息

Windows原理深入学习系列-访问控制列表_第38张图片

根据类型可以找到更多的与 ACE 相关的结构,比如 ACCESS_ALLOWED_ACE

Windows原理深入学习系列-访问控制列表_第39张图片

这样就都串起来了,每一项 ACE 都有一个 ACE_HEADER,然后根据类型的不同,后面跟着的是不同的数据结构

但是还有个问题,ACE 到底该怎么取,从哪里开始取,接下来就来分析一下 RtlGetAce 函数,根据参数可以很明显的发现,他会先传入 ACL,然后根据要获取的 ACE 的索引进行查找,最后再进行返回

Windows原理深入学习系列-访问控制列表_第40张图片

上面这些判断并不是关键,下面的循环取值才是关键要看到的内容

先取到 ACL 的大小,然后偏移到 ACL 的后面

r9 是 rcx+8 的地址,目前也就是 ACL 的头的结尾位置,加二并将值赋给 eax,因为紧接着是 _ACE_HEADER 结构,所以 eax 就是当前 ACE 的大小

r8 用来循环计数,判断 AceIndex 的,我们暂且不用关心,只看它是怎么获取的

将 r9 加上大小,然后赋值回去,就返回 ace 了

这里看着是跳过了第一个 ACE,实际上是因为当 AceIndex 为 0 时,在上面 rcx+8 的时候就已经是其地址了,所以就不会进入当前的这个循环

Windows原理深入学习系列-访问控制列表_第41张图片

在分析完结构以后,继续在 WinDBG 当中看一下

第一位是 Type,第二位是 Flags,第三位是 Size,紧接着四位是 Mask,接着后面是 Sid

Windows原理深入学习系列-访问控制列表_第42张图片

Type 为 0,就是 ACCESS_ALLOWED_ACE,虽然最后的 Sid 只是一个 DWORD 类型,但是根据名字就可以看出来了,这只是记录一下地址的,总大小在前面已经有记录了

Windows原理深入学习系列-访问控制列表_第43张图片

对于 ACCESS_MASK,就是用来描述当前权限的

Windows原理深入学习系列-访问控制列表_第44张图片

它主要分为了几个部分,对于一般和标准的都有详细标记,至于特殊权限位,没有查到详细的内容,感兴趣可以挨个试一试,链接我全部放到最后的参考文章当中

Windows原理深入学习系列-访问控制列表_第45张图片

接下来就是 SID 了,它是有结构的,可以直接进行查看

Windows原理深入学习系列-访问控制列表_第46张图片

这样 ACE 也就解析出来了

第一个是 S-1-5-18 即 SYSTEM 账户允许 STANDARD_RIGHTS_ALL 和 SPECIFIC_RIGHTS_ALL 权限

第二个 SID 就是 S-1-5-32-544,可以查到他对应的是账户是 Administrators

Windows原理深入学习系列-访问控制列表_第47张图片

这也就刚开始看到的 ACE 项所对应了

Windows原理深入学习系列-访问控制列表_第48张图片

这样也就完成了整个 DACL 的查找

0x07 参考文章

1.https://docs.microsoft.com/en-us/windows/win32/secauthz/access-control-lists

2.https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-security_descriptor

3.https://docs.microsoft.com/en-us/windows/win32/secauthz/securable-objects

4.https://docs.microsoft.com/en-us/windows/win32/secauthz/securable-objects

5.https://docs.microsoft.com/en-us/windows/win32/secauthz/dacls-and-aces

6.https://docs.microsoft.com/en-us/windows/win32/secauthz/how-dacls-control-access-to-an-object

7.https://www.cnblogs.com/cdaniu/p/15630284.html

8.https://helgeklein.com/blog/permissions-a-primer-or-dacl-sacl-owner-sid-and-ace-explained/

9.https://book.hacktricks.xyz/windows/windows-local-privilege-escalation/acls-dacls-sacls-aces

10.https://secureidentity.se/acl-dacl-sacl-and-the-ace/

11.https://wj32.org/processhacker/forums/viewtopic.php?t=2568

12.https://docs.microsoft.com/en-us/windows/win32/api/aclui/nf-aclui-editsecurity

13.https://docs.microsoft.com/en-us/windows/win32/secbp/creating-a-dacl

14.https://www.cnblogs.com/iBinary/p/11399114.html#tid-HABck4

15.https://docs.microsoft.com/en-us/windows/win32/secauthz/ace-strings

16.https://myzxcg.com/2021/08/Windows-访问控制模型二/

17.https://www.redteaming.top/2020/02/03/Windows——Access-Control-List/

18.https://3gstudent.github.io/渗透技巧-Windows下的Access-Control-List

19.https://blog.csdn.net/sunyikuyu/article/details/9041067

20.https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ntifs/nf-ntifs-rtlgetdaclsecuritydescriptor

21.https://improsec.com/tech-blog/windows-kernel-shellcode-on-windows-10-part-2

22.https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-ace_header

23.https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-access_allowed_ace

24.https://docs.microsoft.com/en-us/windows/win32/secauthz/access-mask

25.https://docs.microsoft.com/en-us/windows-hardware/drivers/ifs/access-mask

你可能感兴趣的:(Windows原理深入学习系列-访问控制列表)