前言
windows内核中的对象会受到保护,每个对象都有自己的安全描述符(Security Descriptor),安全描述符用来描述此对象可以允许谁,以何种方式访问。而访问这些对象的主体就是进程和线程,每一个进程都有自己的令牌Token,此令牌就是此进程或线程的安全上下文表示此进程或线程属于哪个用户哪个组,以及有什么特权。当线程访问某个对象的时候windows系统会根据线程的安全上下文Token与对象的安全描述符对比并进行权限检查,如果检查通过则允许访问。
Access Token
Access Token是描述进程和线程安全上下文的一个对象,令牌分为两种:授权令牌(主令牌)和模拟令牌。
- 授权令牌(主令牌):每一个进程在运行的时候都会有一个默认的令牌,这个令牌就是主令牌。
- 模拟令牌:线程默认会继承进程的主令牌,但是一些线程可以自己模拟其他用户的令牌,这样线程的安全上下文就变成了这个模拟令牌而不是主令牌。
UAC
早期windows版主中只要以管理员登录那么启动的进程就可以获取到管理员权限,而很多用户都是默认使用管理员用户进行登录这样就很不安全,所以vista开始引入了UAC。如果使用标准用户登录就会系统就会分配一个标准权限的令牌,如果使用管理员用户登录会分配两个令牌Token,这两个令牌是相互关联的,一个令牌具有完全的管理员权限,另一个令牌则是权限受限的。这样默认情况下进程使用的是权限受限的令牌作为主令牌,只要在通过了UAC授权后才能使用具有完全管理员权限的令牌作为主令牌。
Privilege
每个令牌都有自己拥有的特权(Privileage),特权是一个用户或组执行一些系统操作(驱动加载,调试,改变时区)需要的权限。使用的管理员账户登录会生成两个令牌(管理员权限令牌和权限受限令牌),查看权限受限的令牌发现只此令牌只拥有很少的特权。
查看管理员权限的令牌则具有更多的特权(大部分还没有开启)。
使用管理员登录并运行一个进程不进行UAC授权,这时此进程使用的主令牌是权限受限的令牌token,windbg查看对应进程的token
如果启动一个进程并进行uac授权,这时此进程使用的主令牌就是具有管理员权限的令牌。
安全描述符(Security Descriptor)
对象的安全描述符用来表示此对象允许谁,以何种方式(权限)访问。主要包含了自主访问控制列表(DACL)和系统访问控制列表(SACL)。
- 自主访问控制列表(DACL),规定了哪些用户和组可以对这个对象执行哪些操作
- 系统访问控制列表(SACL),规定了哪些用户和组可以的操作会被记录到安全审计日志中
查看文件对应的安全描述符信息:
windbg查看一个进程内核对象的安全描述符,通过_OBJECT_TYPE的SecurityDescriptor可以得到对象的安全描述符信息。可以看到此进程对象允许哪些用户以何种权限访问,0x1fffff对应的就是PROCESS_ALL_ACCESS。
当某个进程中的线程尝试访问某个对象时,系统会通过对象的安全描述符信息与线程的安全上下文Token进行对比,通过安全描述符自主访问控制列表DACL中的每一项(ACE)进行权限判断,如果DACL为空则会直接拒绝。
测试
目的是为了测试进程内核对象EPROCESS的安全描述符(Security Descriptor)的DACL被清空后会发生什么?(因为DACL被清空了,所以用户层所有的用户和组创建的进程都无法访问此内核对象)。目标进程的PID为9820,windbg查看对应的安全描述符信息,并将DACL表清空。
用户层创建进程无论是不同用户还是管理员用户调用OpenProcess打开此进程发现无法获得句柄(打开失败)。
但是如果使用管理员用户并激活"SeDebugPrivilege"特权的话是可以正常打开的,这就说明进程安全上下文的Token使用某些特权的话是可以忽略DACL检查的。
参考:
https://wooyun.kieran.top/#!/drops/987.浅析Windows的访问权限检查机制
https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-security_capabilities