发布于2025年12月5日12月5日 作者:crispr\r \r 在长汀牧云(云行者)团队中,有一群孜孜不倦、不断探索的研究人员,专门治疗攻防场景中的各种“疑难杂症”。 \r \r 2022年,超听科技推出“主机安全技术专栏”,分享最实用、最深入的安全研究。 \r \r \r ## 前言\r \r Windows中的提权是攻防对抗中不可避免的话题。本文总结并介绍了Windows操作系统中本地提权方法的原理和方法。权限提升是后渗透的重要一步。当权限较低时,从攻击者角度进行的内部网络安全测试、系统安全测试、应用程序安全测试等都会受到限制。 \r \r 考虑到Windows操作系统中提权方法的丰富性和多样性,本文分为基本概念和应用两部分。基础概念章节介绍了Windows提权相关的必备知识,包括SID/安全描述符/令牌等;应用章节从权限级别的角度出发,介绍了三种情况下的Win提权姿势:从普通用户到管理员用户、从服务帐户到SYSTEM、从普通用户到SYSTEM。应用章节阅读不分顺序,读者可以根据自己的需要阅读全文或按某个方向阅读。 \r \r \r 图片\r 目前,长汀牧云(云行者)主机安全管理平台已支持通用的windows提权检测。如果您也对主机安全感兴趣,请将简历发送至邮箱:[email protected]\r \r ##Windows权限提升相关的基本概念\r \r ### 安全标识符SID\r \r 安全标识符(SID) 是标识用户、组和计算机帐户的唯一编号。每个帐户都有一个由权威机构(例如Windows 域控制器)颁发并存储在安全数据库中的唯一SID。每次用户登录时,都会从数据库中检索用户的SID 并将其放入用户的访问令牌中。系统使用访问令牌中的SID 来在与Windows 安全相关的所有后续交互中识别用户。当SID 用作用户或组的唯一标识符时,它不能再用于识别另一个用户或组。 \r \r MSDN 提供了常见SID 的列表\r - S-1-5-18(本地系统)\r - S-1-5-19(本地服务)\r - S-1-5-20(网络服务)\r - S-1-5-32-544(管理员)\r - S-1-5-32-545(用户)\r - S-1-5-32-550(打印操作员)\r \r SID的简化结构如下\r \r 首先,第一位S为默认位,第二位R代表SID的版本号,第三位A代表主标识值,后面的位SA代表子标识值,其中SA1到SAn-1代表域相关的标识值,SAn为RID(相对标识符),代表相对标识值\r \r 分析S-1-5-21-1004336348-1177238915-682003330-512,可以知道\r - SID的版本号为1\r - 主ID值为5,代表NT权限\r - 与域相关的子ID 值为21-1004336348-1177238915-682003330\r - RID 是512,代表DomainAdmins\r \r 这里我们可以使用windbg来查看进程的Token。令牌包含有关用户SID 和组SID 的信息\r \r \r \r \r ###访问权限\r 访问权限是对对象执行特定操作所需的权限。例如,FILE_READ_DATA访问权限表示读取文件的权限。 \r \r 访问权限分为两种:\r - **特定访问权限**:执行单个操作的权限。例如,调试进程需要SeDebugPrivilege 权限。该权限与需要操作的对象无关,只与操作行为本身有关。详细信息请参考官方文档。 \r - **一般访问权限**:一种通用访问权限,与对象的ACL相关,例如上面的FILE_READ_DATA权限。 \r \r 在Windows系统中,当我们访问一个Object时,ACL(访问控制列表)决定当前账户/账户组的权限是否允许我们执行相应的操作。 ACL涉及多个概念,包括ACE/DACL/SACL等,这些概念的含义如下:\r - **ACL**: 访问控制列表,用于表示用户(组)权限列表,包括DACL和SACL\r - **ACE**: Access Control Entry,ACL中的访问控制实体,一个ACL可能包含0到多个ACE\r - **DACL**:当进程尝试访问安全对象时,系统会检查该对象的DACL 中的ACE \r 注意:DACL是一个ACE链表,一种数据结构。每个节点都存储访问权限等信息(这个链表比数组查找起来要快)来决定是否授予访问权限。如果对象没有DACL,系统将授予完全访问权限\r - **SACL**: 系统访问控制列表,用于记录对安全对象的访问日志\r \r 当我们访问一个文件时,系统会做出如下判断:\r - **没有DACL** 系统将允许访问\r - **如果存在DACL**,但不存在ACE,则所有访问都将被拒绝\r - **如果存在DACL** 并且存在ACE,则指定每个ACE 允许或拒绝\r \r 接下来,我们还使用windbg来获取内核对象的安全描述符。安全描述符指针放置在内核对象头的字段中。 \r \r 在windbg中启动内核调试,使用!sd查看安全描述符信息,这里借一张图\r \r \r \r 可以看到这个DACL中有3个ACE。 ACE 的类型是ACCESS_ALLOWED_ACE_TYPE。 mask为权限掩码,用于指定对应的权限。 \r \r 因此,图中第一个ACE表示允许SID为S-1-5-32-544的对象对安全对象执行0x001fffff对应的操作(Mask的权限位根据不同的对象类型有不同的含义)。具体权限位请参考下图\r \r \r \r ### 本地帐户\r \r 本地帐户存储在本地服务器上。与提权相关的本地帐号包括管理员帐号、默认本地系统帐号和服务帐号。 \r \r **管理员**\r \r 每台计算机都有一个管理员帐户,这是在Windows 安装过程中创建的第一个帐户。 \r \r 管理员帐户可以完全控制本地计算机上的文件、目录、服务和其他资源。管理员帐户可以创建其他本地用户、分配用户权限和分配权限。 \r \r 默认管理员帐户无法删除或锁定,但可以重命名或禁用。 \r \r 在Windows 10 和Windows Server 2016 中,Windows 安装程序会禁用内置管理员帐户并创建另一个属于管理员组成员的本地帐户。 \r \r **默认本地系统帐户**\r \r SYSTEM 帐户由Windows 下运行的操作系统和服务使用。 Windows 操作系统中有许多服务和进程需要能够内部登录,例如在Windows 安装期间。 \r \r SYSTEM 帐户就是为此目的而设计的。它是内部帐户,不会显示在用户管理器中,并且无法添加到任何组。 \r \r 默认情况下,SYSTEM 帐户被授予对NTFS 卷上所有文件的完全控制权限。因此,SYSTEM帐户包含了管理员帐户的功能和权限。 \r \r **网络服务帐户**\r \r NETWORK SERVICE 是服务控制管理器(SCM) 使用的预定义本地帐户。在此帐户下运行的服务允许将访问凭据提交到远程计算机。 \r \r **本地服务帐户**\r \r LOCAL SERVICE 帐户是服务控制管理器使用的预定义本地帐户,它在本地计算机上拥有最低权限,并在网络上提供匿名凭据。 \r \r 与Sqlserver、IIS等类似,都属于本地服务帐户。本地服务帐户具有特殊访问权限SeImpersonatePrivilege。至于为什么强调这个权限,下一篇文章会介绍。 \r \r ### 访问令牌\r \r WindowsToken,也称为AccessToken,是一个描述进程或线程安全上下文的对象。不同的用户登录计算机后,会生成一个AccessToken。当用户创建进程或线程时,会使用并不断复制这个Token。这也解释了用户A创建了一个进程,而该进程没有用户B的权限。\r \r 令牌的解释可以在MSDN :\r 中找到 https://docs.microsoft.com/zh-cn/windows/win32/secauthz/access-tokens?redirectedfrom=MSDN\r \r **访问令牌组成**\r \r 代币分为两类:\r - 主要令牌\r - 模拟令牌\r 注意: 当用户注销时,系统会将主令牌切换为模拟令牌,并且模拟令牌不会被清除。只有重启机器后才会被清除\r \r 主令牌是Windows 内核创建并分配给进程的默认访问令牌。每个进程都有一个主令牌,用于描述与当前进程关联的用户帐户的安全上下文。 \r \r 此外,线程可以模拟客户帐户。模拟允许线程使用客户端的安全上下文与安全对象交互。模拟客户端的线程同时拥有主令牌和模拟令牌。作者理解线程可以作为客户端与服务器进行交互,并且有权限模拟服务器的身份\r \r 令牌的主要组成部分包括以下几个部分:\r - TokenID(标识令牌的唯一ID)\r - 权限(当前token的权限,详细请查看官方文档)\r - UserAndGroups(当前用户及其所属组,实际上是一个SID数组)\r - RestrictedSids(如果该值不为空,则表示该令牌是受限令牌,也是一个SID数组)\r - TokenType(当前令牌的类型)\r - ImpersonationLevel(模拟令牌的级别)\r \r 令牌创建过程如下:\r \r \r 1.使用凭据(用户密码)进行身份验证\r 2. 登录会话创建\r 3.Windows返回用户sid和用户组sid\r 4. LSA(本地安全机构)创建Token\r 5、根据token创建进程和线程(如果在CreaetProcess时指定了Token,LSA就会使用该Token,否则会继承父进程Token并运行)\r \r **令牌模拟级别**\r \r 官方说明如下:\r https://docs.microsoft.com/zh-cn/windows/win32/secauthz/impersonation-levels \r \r 模拟级别由下面所示的SECURITY_IMPERSONATION_LEVEL 枚举表示\r \r 1: typedef 枚举_SECURITY_IMPERSONATION_LEVEL {\r 2: 安全匿名,\r 3: 安全识别,\r 4: 安全模拟,\r 5: 安全委托\r 6: } SECURITY_IMPERSONATION_LEVEL, *PSECURITY_IMPERSONATION_LEVEL;\r 模拟级别\t描述\r SecurityAnonymous\t无法获取有关客户端的识别信息并且无法模拟客户端;\r SecurityIdentification\t可以获取有关客户端的信息(例如安全标识符和权限),但无法模拟客户端\r 安全模拟\t可以在本地模拟客户端,但无法模拟远程系统上的客户端\r SecurityDelegation\t可以模拟本地和远程系统上的客户端\r 文档给出了通过用户身份创建进程的三个函数:\r 功能\t需要权限\t输入\r ***\r CreateProcessWithLogon\tnull\t域/用户名/密码\r CreateProcessWithToken\tSeImpersonatePrivilege\tPrimaryToken\r CreateProcessAsUser\tSeAssignPrimaryTokenPrivilege 和SeIncreaseQuotaPrivilege\tPrimaryToken\r 从这三个Win API我们不难发现,当我们拥有SeAssignPrimaryToken或者SeImpersonate权限时,我们可以通过模拟Primary token来创建一个新的进程来提升权限(前提是该token具有Impersonation和Delegation级别),所以如果想要通过模拟token来提升权限,一个很重要的前提是用户拥有SeImpersonate权限\r \r **如何获取令牌**\r \r Win API 提供了OpenProcessToken/openThreadToken 等函数来打开进程或线程的访问令牌。函数原型如下:\r ````\r 布尔\r OpenProcessToken\r (\r \r \r 手柄\r 进程句柄\r ,\r //访问令牌已打开的进程句柄\r \r \r 双字\r 所需访问\r ,\r \r \r 凡德尔\r 令牌句柄\r //指向函数返回时标识新打开的访问令牌的句柄的指针。 \r \r \r );\r \r \r \r 布尔\r OpenThreadToken\r (\r \r \r 手柄\r 线程句柄\r ,\r //打开访问令牌的线程的句柄。 \r \r \r 双字\r 所需访问\r ,\r \r \r 布尔\r 打开为自己\r ,\r \r \r 凡德尔\r 令牌句柄\r //指向接收新打开的访问令牌句柄的变量的指针\r \r \r );\r ````\r 通过OpenThreadToken/OpenProcessToken函数获取访问令牌。 \r \r 这里,模拟代币和主代币可以通过DuplicateTokenEx函数相互转换\r \r DuplicateTokenEx:我们最终调用CreateProcessWithToken/CreateThreadWithToken时传递的token一定是主token,而我们一般获取的token都是模拟token,所以中间流程需要通过DuplicateTokenEx函数进行转换。 \r \r 微软官方文档给出了DuplicateTokenEx创建主令牌的典型场景。服务器应用程序创建一个线程,该线程调用模拟函数之一(例如ImpersonateNamedPipeClient)来模拟客户端。然后模拟线程调用OpenThreadToken函数来获取自己的令牌,这就是模拟令牌。线程在对DuplicateTokenEx 的调用中指定此模拟令牌,并指定TokenPrimary 标志。然后,DuplicateTokenEx 函数创建一个主令牌。 \r \r 因此,一个模拟token的进程约为:\r 1.OpenProcess(获取目标进程上下文),返回的句柄将用于步骤2的参数\r 2.OpenProcessToken(获取进程访问令牌的句柄),使用该函数获取对应进程的令牌句柄\r 3. DuplicateTokenEx(创建主令牌),设置访问令牌模拟级别并复制令牌句柄\r 4.CreateProcessWithTokenW(创建进程),模拟主token的权限创建对应的进程\r \r 所以当我们拥有SeImpersonatePrivilege权限后,我们可以通过爆破进程:\r来找到满足以下条件的进程 - 进程运行用户是SYSTEM\r - 令牌级别至少为模拟级别\r - 攻击者至少以SeImpersonatePrivilege\r 运行 \r 这其实就是Token Kidnapping技术,相关介绍\r https://msrc-blog.microsoft.com/2009/04/14/token-kidnapping/\r \r 但如果不这样爆破Administrator身份,提权的成功率很低。这只是一个想法。 \r \r ## 结论\r 基本概念章节主要介绍Windows提权涉及的一些基本概念。目的是为后续应用章节提供启发,敬请持续关注。
创建帐户或登录后发表意见