Windows认证和安全对象的基本概念

Windows认证和安全对象的基本概念

A access B,A就是访问的主体,B就是访问的客体。

A的访问令牌和B的安全描述符决定了A是否可以访问B。

访问的主体是进程。线程是程序执行的流程,线程是没有属于自己的权限的,它的权限来源于所属的进程。

访问的客体是安全对象,所有被访问的对象都有安全描述符,如文件、管道、注册表、事件(回想创建内核对象函数中的lpSecurityAttributes参数)

Token、权限和用户标识

进程的权限继承自创建进程用户和用户所属的用户组。用户有专用数据结构来表示权限---访问令牌(Access Token)。访问令牌包括两个部分:一个是令牌所表示的用户,包括用户标识符(SID),用户所属的用户组等;另一部分是"权限"(Privilege)。

在进程访问安全对象时,会用到 SID。每个安全对象都有访问控制列表(ACL),ACL 说明了哪些用户( SID)能访问本对象,哪些不能,以及能进行哪种访问等。而"权限"在访问某个具体的安全对象时并没有作用,"权限"是表示进程是否能够进行特定的系统操作,如关闭系统、修改系统时间、加载设备驱动等。

访问令牌的类型

Windows 中有两种主要的访问令牌类型:

  • 主令牌(Primary Token):与进程关联,代表进程的默认安全上下文。每个进程都有一个主令牌,由创建该进程的用户决定。
  • 模拟令牌(Impersonation Token):与线程关联,允许线程临时以另一个用户的安全上下文执行操作。这在客户端-服务器模型中非常常见,例如服务器线程在处理客户端请求时,可以模拟客户端的身份来访问资源。

权限(Privilege)详解

权限是系统级别的操作能力,常见的权限包括:

权限名称 常量标识 说明
关闭系统 SeShutdownPrivilege 允许进程关闭系统
修改系统时间 SeSystemtimePrivilege 允许修改系统时间
加载设备驱动 SeLoadDriverPrivilege 允许加载或卸载设备驱动
调试程序 SeDebugPrivilege 允许调试任何进程
备份文件和目录 SeBackupPrivilege 允许绕过文件权限进行备份
创建令牌对象 SeCreateTokenPrivilege 允许创建主令牌

权限默认是禁用的,进程需要通过 AdjustTokenPrivileges 函数显式启用。

创建进程时指定令牌

c 复制代码
// 以指定用户的令牌创建进程
BOOL CreateProcessAsUser(
  HANDLE                hToken,          // 用户令牌句柄
  LPCTSTR               lpApplicationName,
  LPTSTR                lpCommandLine,
  LPSECURITY_ATTRIBUTES lpProcessAttributes,
  LPSECURITY_ATTRIBUTES lpThreadAttributes,
  BOOL                  bInheritHandles,
  DWORD                 dwCreationFlags,
  LPVOID                lpEnvironment,
  LPCTSTR               lpCurrentDirectory,
  LPSTARTUPINFO         lpStartupInfo,
  LPPROCESS_INFORMATION lpProcessInformation
);

// 使用指定令牌创建进程(Windows Vista+)
BOOL CreateProcessWithTokenW(
  HANDLE                hToken,
  DWORD                 dwLogonFlags,
  LPCWSTR               lpApplicationName,
  LPWSTR                lpCommandLine,
  DWORD                 dwCreationFlags,
  LPVOID                lpEnvironment,
  LPCWSTR               lpCurrentDirectory,
  LPSTARTUPINFOW        lpStartupInfo,
  LPPROCESS_INFORMATION lpProcessInformation
);

安全对象

在创建对象时都可以指定对象的安全属性,比如 CreateFile、CreatePipe、CreateProcess、RegCreateKeyEx 和 RegSaveKeyEx 等,SECURITY_ATTRIBUTES 结构用于指定对象的安全属性。

对象的安全属性是以安全描述符(Security Descriptor)的形式存在的,安全描述符中包括了访问控制列表。

SECURITY_ATTRIBUTES 结构

c 复制代码
typedef struct _SECURITY_ATTRIBUTES {
  DWORD  nLength;               // 结构大小,sizeof(SECURITY_ATTRIBUTES)
  LPVOID lpSecurityDescriptor;  // 指向安全描述符的指针
  BOOL   bInheritHandle;        // 子进程是否继承该句柄
} SECURITY_ATTRIBUTES, *PSECURITY_ATTRIBUTES;

使用示例:

c 复制代码
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = NULL;  // 使用默认安全描述符
sa.bInheritHandle = TRUE;        // 允许子进程继承句柄

HANDLE hFile = CreateFile(
    L"test.txt",
    GENERIC_READ | GENERIC_WRITE,
    FILE_SHARE_READ,
    &sa,                         // 传入安全属性
    CREATE_ALWAYS,
    FILE_ATTRIBUTE_NORMAL,
    NULL
);

安全描述符的结构

安全描述符包含以下关键信息:

  1. 所有者 SID:标识对象的所有者
  2. 组 SID:标识对象所属的主组(主要用于 POSIX 兼容)
  3. DACL(自主访问控制列表):控制谁可以访问对象以及如何访问
  4. SACL(系统访问控制列表):记录访问尝试的审计日志

ACL(访问控制列表)

ACL 是安全描述符的核心组成部分,它由一系列访问控制项(ACE)组成。每个 ACE 定义了一个用户或用户组的访问权限。

DACL 与 SACL 的区别

特性 DACL SACL
全称 自主访问控制列表 系统访问控制列表
作用 控制访问权限(允许/拒绝) 记录审计日志
默认行为 无 DACL 时允许所有访问 无 SACL 时不审计
ACE 类型 允许 ACE、拒绝 ACE 审计成功 ACE、审计失败 ACE

ACE(访问控制项)的结构

c 复制代码
typedef struct _ACCESS_ALLOWED_ACE {
  ACE_HEADER Header;       // ACE 类型、标志和大小
  ACCESS_MASK Mask;        // 访问权限掩码
  DWORD      SidStart;     // 用户/组的 SID
} ACCESS_ALLOWED_ACE;

访问权限掩码示例

c 复制代码
// 文件对象的常见访问权限
#define FILE_READ_DATA            (0x0001)
#define FILE_WRITE_DATA           (0x0002)
#define FILE_APPEND_DATA          (0x0004)
#define FILE_READ_EA              (0x0008)
#define FILE_WRITE_EA             (0x0010)
#define FILE_EXECUTE              (0x0020)
#define FILE_DELETE_CHILD         (0x0040)
#define FILE_READ_ATTRIBUTES      (0x0080)
#define FILE_WRITE_ATTRIBUTES     (0x0100)

// 标准访问权限
#define DELETE                    (0x00010000)
#define READ_CONTROL              (0x00020000)
#define WRITE_DAC                 (0x00040000)
#define WRITE_OWNER               (0x00080000)
#define SYNCHRONIZE               (0x00100000)

访问检查流程

当进程尝试访问一个安全对象时,Windows 安全引用监视器(SRM)会执行以下步骤:

  1. 获取访问令牌:从进程的主令牌中获取 SID 和权限信息
  2. 检查 DACL :遍历 DACL 中的 ACE,按顺序检查:
    • 如果遇到拒绝 ACE 匹配当前 SID → 拒绝访问
    • 如果遇到允许 ACE 匹配当前 SID → 允许对应权限
    • 如果遍历完 DACL 没有匹配项 → 拒绝访问
  3. 记录审计:如果 SACL 存在,记录访问事件到安全日志

重要规则:拒绝 ACE 优先于允许 ACE。这意味着即使后面有允许 ACE,只要前面有拒绝 ACE 匹配,访问就会被拒绝。

实际应用示例

c 复制代码
// 创建一个安全描述符,只允许管理员访问
PSECURITY_DESCRIPTOR pSD = NULL;
PACL pDacl = NULL;
DWORD dwResult;

// 初始化安全描述符
pSD = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH);
InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION);

// 创建 DACL,只允许 Administrators 组访问
SID_IDENTIFIER_AUTHORITY SIDAuth = SECURITY_NT_AUTHORITY;
PSID pAdminSID = NULL;
AllocateAndInitializeSid(&SIDAuth, 2,
    SECURITY_BUILTIN_DOMAIN_RID,
    DOMAIN_ALIAS_RID_ADMINS,
    0, 0, 0, 0, 0, 0,
    &pAdminSID);

// 创建 ACL 并添加允许 ACE
dwResult = SetEntriesInAcl(1, &(EXPLICIT_ACCESS){
    .grfAccessPermissions = GENERIC_ALL,
    .grfAccessMode = GRANT_ACCESS,
    .grfInheritance = NO_INHERITANCE,
    .Trustee = {
        .TrusteeForm = TRUSTEE_IS_SID,
        .TrusteeType = TRUSTEE_IS_GROUP,
        .ptstrName = (LPTSTR)pAdminSID
    }
}, NULL, &pDacl);

SetSecurityDescriptorDacl(pSD, TRUE, pDacl, FALSE);

// 将安全描述符应用到对象
SECURITY_ATTRIBUTES sa = {
    .nLength = sizeof(SECURITY_ATTRIBUTES),
    .lpSecurityDescriptor = pSD,
    .bInheritHandle = FALSE
};

HANDLE hFile = CreateFile(L"secure.txt", GENERIC_ALL, 0, &sa,
    CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

// 清理资源
if (pAdminSID) FreeSid(pAdminSID);
if (pDacl) LocalFree(pDacl);
if (pSD) LocalFree(pSD);

总结

Windows 的安全模型基于三个核心概念:

  1. 访问令牌(Token):标识进程的身份和权限
  2. 安全描述符(Security Descriptor):定义对象的安全属性
  3. 访问控制列表(ACL):通过 DACL 和 SACL 控制访问和审计

理解这些概念是进行 Windows 系统编程和安全开发的基础。在实际开发中,合理设置安全描述符可以有效防止未授权访问,而正确使用访问令牌则能实现精细化的权限控制。

相关推荐
LannyChung10 小时前
PowerShell 下 git log 中文乱码的完整排查与解决
windows·git
EnCi Zheng10 小时前
后端怎么把AI接口稳定安全低成本接进业务:超时重试、密钥隔离与成本熔断清单
人工智能·后端·安全·架构·api
Smoothcloud润云11 小时前
GPU远程纳管安全吗?最小权限、网络边界与日志审计实战
服务器·网络·人工智能·安全·gpu算力·gpu
长不大的杨瑞杰12 小时前
OpenCode v2 MCP 与插件体系实战:把数据库、工单和内部 API 安全接入 Agent
人工智能·安全·语言模型·软件工程·1024程序员节
万联WANFLOW13 小时前
Kimi K3.1 Pro 接口接入指南:模型选型、费用计算与零数据保留
java·spring boot·python·安全·spring·大模型
安教安全员通关宝13 小时前
2026年浙江安全员B证考试题库+答案+解析
安全
福建佰胜张工13 小时前
费希尔 FIELDVUE™ DVC6200-AC 智能阀门定位器深度解析:双作用配置、核心参数与典型应用
运维·安全·自动化
木头科技14 小时前
【AI 工程化第十八篇】Spring AI 语音 Agent 实战:实时转写、WebSocket、流式 TTS 与打断机制
java·人工智能·安全·spring·性能优化
富安达智能14 小时前
气体传感器在智慧温室大棚中的应用,助力设施农业提质增效
安全
千里念行客24015 小时前
恩威医药:第三季度扭亏为盈,经营拐点已经写在单季报表里
大数据·科技·安全·健康医疗