打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
受限token实现xp下沙箱设计的关键概念之DAC

DAC机制:

DAC(DiscretionalAccess Control,自主访问控制),需要先了解下面三个概念:SID、Token和SD。

1、SID

Security identifier,安全标识符,标识系统中执行各种动作的实体,用户,本地用户组,域中用户组,本地计算机,域和域成员都有SID。


详细SID描述见<<深入解析Windows操作系统>>P495。

2、Token
令牌,进程或线程访问资源(文件对象,注册表对象,互斥对象,命名管道对象等)的凭证。

图 2,Token内核对象的大致内存布局。关键数据结构如下:

typedef struct_SID_AND_ATTRIBUTES{

PSID           Sid;

DWORD   Attributes;

}SID_AND_ATTRIBUTES;

 

typedef struct_LUID_AND_ATTRIBUTES{

LUID  Luid;

DWORDAttributes;

} LUID_AND_ATTRIBUTES;

大家可以对照图1和图2来了解Token。

当用户登录系统成功之后,SID和Token的逻辑关系见下图3:


3、SD

SecurityDescriptor,安全描述符,规定了谁可以在被描述的对象上执行怎么样的动作。

其内核对象的内存布局大致如下:

DAC(Discretional Access Control,自主访问控制)。

在下图5中,User4同时属于Group1和Group2。现在,假设User4要创建一个进程Trojan.exe,那么该进程的Token中就有SID1、SID2和SID4,且有特权1和特权2。

Trojan.exe在DAC机制下访问对象的过程如下:

上图5中,虽然SD中允许User4访问该对象,但是,由于拒绝的ACE在前面,Group1已经拒绝访问该对象,所以,User4还是不能访问该对象。

 Restricted token功能介绍

受限令牌是通过CreateRestrictedToken函数,在主令牌或模仿令牌的基础上创建的。受限令牌是其来源令牌的一份拷贝,有可能下面的修改:

1)  从该令牌的特权集中删除一些特权;

2)  该令牌的SID可以被标记deny-only;

3)  该令牌中的SID可以 被标记为restricted;

下面是我写的一段基于CUI的代码,其功能有:

1)创建Restricted Token;

2)在restricted token基础上,根据用户传入的程序路径创建受限进程;

// RestrictToken.cpp

//

 

#include "stdafx.h"

#include "windows.h"

 

int_tmain(int argc, _TCHAR* argv[])

{

 

//

//为BUILTIN\Administrators组创建一个SID

//

BYTE sidBuffer[256] = {0};

 

//PSID可变长度的数据结构

PSID pAdminSID = (PSID)sidBuffer;

 

/*typedef struct_SID_IDENTIFIER_AUTHORITY {

  BYTE Value[6];

} SID_IDENTIFIER_AUTHORITY,*PSID_IDENTIFIER_AUTHORITY;

*/

SID_IDENTIFIER_AUTHORITY SIDAuth =SECURITY_NT_AUTHORITY;

 

/*

BOOL WINAPIAllocateAndInitializeSid(

  __in  PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,

  __in  BYTE nSubAuthorityCount,

  __in   DWORD dwSubAuthority0,

  __in  DWORD dwSubAuthority1,

  __in  DWORD dwSubAuthority2,

  __in  DWORD dwSubAuthority3,

  __in  DWORD dwSubAuthority4,

  __in  DWORD dwSubAuthority5,

  __in  DWORD dwSubAuthority6,

  __in  DWORD dwSubAuthority7,

  __out PSID *pSid

);

*/

if( !AllocateAndInitializeSid( &SIDAuth,

                                     2,

                                     SECURITY_BUILTIN_DOMAIN_RID,

                                     DOMAIN_ALIAS_RID_ADMINS,

                                     0,

                                     0,

                                     0,

                                     0,

                                     0,

                                     0,

                                     &pAdminSID))

{

   printf( "AllocateAndInitializeSid Error%u\n", GetLastError() );

   return -1;  

}

 

 

//

// 将本地的administrator的SID改成deny-only SID

//

 

 

/*

typedef struct_SID_AND_ATTRIBUTES{

     PSID Sid;

     DWORD Attributes;

}SID_AND_ATTRIBUTES;

*/

SID_AND_ATTRIBUTES SidToDisable[1] ={0};

SidToDisable[0].Sid = pAdminSID;

SidToDisable[0].Attributes = 0;

 

//获取当前进程的Token

HANDLE hOldToken = NULL;

if(!OpenProcessToken(

   GetCurrentProcess(),                  

   TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE |

   TOKEN_QUERY | TOKEN_ADJUST_DEFAULT,

   &hOldToken))

{

   printf("OpenProcessToken failed(%lu)\n", GetLastError() );

   return -1;

}

 

 

/*

BOOL WINAPICreateRestrictedToken(

  __in     HANDLE ExistingTokenHandle,

  __in     DWORD Flags,

  __in      DWORD DisableSidCount, //禁用SID用

  __in_opt PSID_AND_ATTRIBUTES SidsToDisable,

  __in     DWORD DeletePrivilegeCount,//删除特权用

  __in_opt PLUID_AND_ATTRIBUTES PrivilegesToDelete,

  __in     DWORD RestrictedSidCount,

  __in_opt PSID_AND_ATTRIBUTES SidsToRestrict,

  __out    PHANDLE NewTokenHandle

);

*/

//根据当前进程的Token创建restrictedtoken

HANDLE hNewToken = NULL;

if(!CreateRestrictedToken(hOldToken,

   DISABLE_MAX_PRIVILEGE,

   1, SidToDisable,

   0, NULL,

   0, NULL,

   &hNewToken))

{

   printf("CreateRestrictedToken failed(%lu)\n", GetLastError());

   return -1;

}

 

if(pAdminSID)

   FreeSid(pAdminSID);

 

 

// The following codecreates a new process

// with the restrictedtoken.

PROCESS_INFORMATION pi;

STARTUPINFO si;

ZeroMemory(&si, sizeof(STARTUPINFO) );

si.cb = sizeof(STARTUPINFO);

si.lpDesktop = NULL;

 

 

//接收目标进程路径,以便创建受限进程

charszSysDir[MAX_PATH+1] = {0};

printf("pleaseinput app path for restricted token: ");

scanf("%s",szSysDir);

 

/*

BOOL WINAPI CreateProcessAsUser(

  __in_opt    HANDLE hToken,

  __in_opt    LPCTSTR lpApplicationName,

  __inout_opt LPTSTR lpCommandLine,

  __in_opt    LPSECURITY_ATTRIBUTES lpProcessAttributes,

  __in_opt    LPSECURITY_ATTRIBUTES lpThreadAttributes,

  __in        BOOL bInheritHandles,

  __in        DWORD dwCreationFlags,

  __in_opt    LPVOID lpEnvironment,

  __in_opt    LPCTSTR lpCurrentDirectory,

  __in        LPSTARTUPINFO lpStartupInfo,

  __out       LPPROCESS_INFORMATION lpProcessInformation

);

*/

 

if(!CreateProcessAsUser(

   hNewToken,

   szSysDir, NULL,

   NULL, NULL,

   FALSE, CREATE_NEW_CONSOLE,

   NULL, NULL, 

   &si, &pi))

   printf("CreateProcessAsUser failed(%lu)\n", GetLastError() );

 

CloseHandle(hOldToken);

CloseHandle(hNewToken);

return0;

 

}

RestrictedToken.EXE使用方法:

1)  cmd下回车,创建restricted token


2)  输入受限运行的App路径


下面让我们通过Process Explore来比较下受限与未受限的情况下,notepad.exe的token到底有什么区别?

1)  未受限notepad.exe的token


2)  受限notepad.exe的token

根据CreateRestrictedToken函数的参数,我们其实还可以对SID进行限制:

很明显,上面我们的RestrictedToken.exe只是禁用了Admin的SID和删除了一些特权,还没有去限制SID。下面图10,是限制了某些SID的。

微软对受限token功能的定义如下:

·  Apply the deny-onlyattribute to SIDs in the token so they cannot beused to access secured objects.

·  Remove privilegesfrom the token.

·  Specify a list ofrestricting SIDs, which the system uses when it checks the token'saccess to a securable object. The system performs twoaccess checks: one using the token's enabled SIDs, and another using thelist of restricting SIDs. Access is granted only ifboth access checks allow the requested access rights

很明显,通过微软对于受限token的描述,只要我们用受限token来创建旺旺沙箱插件进程,那么插件进程就可以在一个受限环境下去执行代码。

 受限token的挑战点

token的可模仿性

Impersonation,模仿,本来是服务器程序为降低自身安全环境,而采用模仿客户端程序安全环境的一种方法。

我想既然可以模仿,那就应该可以通过模仿来提升自己的权限。

下面我设计了一个演示程序,来说明如何通过在受限进程里,通过模仿命名管道的客户端来提升特权,从而到达访问文件的例子。

在这个例子中,涉及三个主要的程序:

1)  MfcRestrictToken.exe,受限读文件和提权后读文件。

2)  PipeClient.exe,连接命名管道的客户端程序。

3)  RestrictToken.exe,创建带有restricted token的MfcRestrictToken.exe进程。

步骤一:

用RestrictToken.exe创建带有受限token的MfcRestrictToken.exe,见下图11和图12。

图11 RestrictToken.exe创建受限MfcRestrictToken.exe

 

图12 受限MfcRestrictToken.exe界面

 

图13 受限MfcRestrictToken.exe的受限Token情况

步骤儿:

在受限情况下,点击MfcRestrictToken.exe的”读文件”功能,发现”打不开此文件”。

图14 受限MfcRestrictToken.exe打不开文件

 

步骤三:

点击”提权”按钮,MfcRestrictToken.exe会创建一个命名管道的服务端,等待有客户端连接此服务端,一旦,有客户端连接此服务端,就会模仿该客户端的token,造成在受限情况下提权。提权后,你再读文件就可以成功读取出内容了。

图15 受限MfcRestrictToken.exe提权后读文件成功

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
以程序的方式操纵NTFS的文件权限
DACL, NULL or not NULL
MFC全局函数::AfxBeginThread
线程的使用
AfxBeginThread的基本用法
VC++文件操作之最全篇
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服