windows系統的安全性基礎 — 存取控制

來源:互聯網
上載者:User

最近看了一下msdn上關於windows的存取控制模型。存取控制就是“適當人使用適當的資源right persons use right resources.”

所以,

第一步,作業系統要認證Authentication, 驗證是否是使用者聲明的使用者身份。驗證通過,以後,

第二步,作業系統要授權Authorization,   使用者a要讀取一個檔案,作業系統檢查檔案的安全性描述元security descriptor;

               如果“擁有讀取許可權的使用者列表”裡面儲存了“使用者a”,那麼,作業系統繼續開始檔案的讀取操作;

               這個過程就是“授權” authorization;

這個文章主要講一下授權(Authorization),授權裡面主要看看存取控制(Access Control Model);

1) 使用者token

使用者登入以後,作業系統給使用者一個access token,裡面主要存放了使用者的許可權privileges, 比如關機,調試,備份系統等等。

使用者建立進程,這個進程就複製這個使用者的token到進程資訊中,進程建立線程(包括主線程),線程自動得到這個token,另外,線程可以“假冒”某個客戶身份,impersonate,線程得到其他使用者的token‘(登入,或者參數傳遞進來),就可以代表這個使用者去訪問只有這個使用者可以訪問的資源。

token裡面還儲存了使用者的安全性識別碼security identifier.

=======================

使用者token資訊的列印

=======================

void DumpTokenInfo(void){    HANDLE hToken = NULL;    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))        return ;    DWORD retLen = 0;    GetTokenInformation(hToken, TokenGroupsAndPrivileges, NULL, 0, &retLen);    TOKEN_GROUPS_AND_PRIVILEGES * pTgap = (TOKEN_GROUPS_AND_PRIVILEGES * )LocalAlloc(0, retLen);    GetTokenInformation(hToken, TokenGroupsAndPrivileges, pTgap, retLen, &retLen);    // 查詢sid數組資訊    printf("\n===============Sids=====================\n");    for (DWORD i = 0; i < pTgap->SidCount; ++i)    {        PSID pSid = pTgap->Sids[i].Sid;        SID_NAME_USE sidType;        char szName [MAX_PATH] = "";        DWORD dwNameLen = MAX_PATH;        char szDomain [MAX_PATH] = "";        DWORD dwDomainLen = MAX_PATH;        LookupAccountSidA(NULL            , pSid            , szName, &dwNameLen            , szDomain, &dwDomainLen            , &sidType);        printf("Sids[%d] = %s@%s\n", i, szName, szDomain);    }    // 查詢許可權資訊    printf("\n===============Priveleges=====================\n");    for (DWORD i = 0; i < pTgap->PrivilegeCount; ++i)    {        char szName [MAX_PATH] = "";        DWORD dwNameLen = MAX_PATH;        LookupPrivilegeNameA(NULL, &pTgap->Privileges[i].Luid, szName, &dwNameLen);        printf("Privileges[%d] = %s\n", i, szName);    }}/************************************************************************0:001> !token <<<<windbg列印出來的token資訊>>>>/////////////////////////////////////////////////////////////////////////Thread is not impersonating. Using process token...TS Session ID: 0User: S-1-5-21-2233661284-422353248-3399546490-500Groups: 00 S-1-5-21-2233661284-422353248-3399546490-513Attributes - Mandatory Default Enabled 01 S-1-1-0Attributes - Mandatory Default Enabled 02 S-1-5-32-544Attributes - Mandatory Default Enabled Owner 03 S-1-5-32-545Attributes - Mandatory Default Enabled 04 S-1-5-4Attributes - Mandatory Default Enabled 05 S-1-5-11Attributes - Mandatory Default Enabled 06 S-1-5-15Attributes - Mandatory Default Enabled 07 S-1-5-5-0-48147Attributes - Mandatory Default Enabled LogonId 08 S-1-2-0Attributes - Mandatory Default Enabled 09 S-1-5-64-10Attributes - Mandatory Default Enabled Primary Group: S-1-5-21-2233661284-422353248-3399546490-513Privs: 00 0x000000017 SeChangeNotifyPrivilege           Attributes - Enabled Default 01 0x000000008 SeSecurityPrivilege               Attributes - Enabled 02 0x000000011 SeBackupPrivilege                 Attributes - 03 0x000000012 SeRestorePrivilege                Attributes - 04 0x00000000c SeSystemtimePrivilege             Attributes - Enabled 05 0x000000013 SeShutdownPrivilege               Attributes - Enabled 06 0x000000018 SeRemoteShutdownPrivilege         Attributes - Enabled 07 0x000000009 SeTakeOwnershipPrivilege          Attributes - Enabled 08 0x000000014 SeDebugPrivilege                  Attributes - Enabled 09 0x000000016 SeSystemEnvironmentPrivilege      Attributes - Enabled 10 0x00000000b SeSystemProfilePrivilege          Attributes - Enabled 11 0x00000000d SeProfileSingleProcessPrivilege   Attributes - Enabled 12 0x00000000e SeIncreaseBasePriorityPrivilege   Attributes - Enabled 13 0x00000000a SeLoadDriverPrivilege             Attributes - Enabled 14 0x00000000f SeCreatePagefilePrivilege         Attributes - Enabled 15 0x000000005 SeIncreaseQuotaPrivilege          Attributes - Enabled 16 0x000000019 SeUndockPrivilege                 Attributes - Enabled 17 0x00000001c SeManageVolumePrivilege           Attributes - Enabled 18 0x00000001d SeImpersonatePrivilege            Attributes - Enabled Default 19 0x00000001e SeCreateGlobalPrivilege           Attributes - Enabled Default Auth ID: 0:c32fImpersonation Level: AnonymousTokenType: PrimaryIs restricted token: no.************************************************************************/

=======================

模仿客戶存取特殊許可權檔案

=======================

#include <sys/stat.h>#include <fcntl.h>#include <io.h>int main(int argc, char * argv[]){    char szCmd [0x20];    printf("ImpersonateLoggedOnUser? [Y/N]>");    gets(szCmd);    // 模仿使用者    if (!_strnicmp(szCmd, "Y", 1))    {        HANDLE hToken = INVALID_HANDLE_VALUE;        if (!LogonUserA("test2"                        , "."                        , "test2"                        , LOGON32_LOGON_INTERACTIVE                        , LOGON32_PROVIDER_DEFAULT                        , &hToken))        {            printf("fail to LogonUserA, error %d\n", GetLastError());            return -1;        }        if (!ImpersonateLoggedOnUser(hToken))        {            printf("fail to ImpersonateLoggedOnUser, error %d\n", GetLastError());            return -1;        }    }        // 實際上是訪問檔案所在的檔案夾資訊    struct _stat _st;    if (_stat("f:\\test.txt", &_st))        return -1;    printf("fsize=%d\n", _st.st_size);    // 真正訪問檔案    int fd = open("f:\\test.txt", O_RDONLY);    if (fd > 0)    {        printf("open file ok.\n");        close(fd);    }    else    {        printf("open failed %d.\n", GetLastError());        return -1;    }    getchar();    return 0;}

2) 安全性描述元

作業系統中的所有資來源物件(進程,線程,檔案,訊號量。。。)都有一個安全性描述元,來描述這個對象可以被哪些使用者訪問,安全性描述元存放2個列表,discretionary access control list
(DACL),sacl。

dacl中存放這ace(access control entries),一個ace包含一個sid和這個sid相關的的訪問權(拒絕,允許,審計)。

========================

安全性描述元資訊的列印

========================

#include "accctrl.h"#include "aclapi.h"#pragma comment(lib, "advapi32.lib")/*調整許可權*/BOOL SetPrivilege(                  HANDLE hToken,          // access token handle                  LPCTSTR lpszPrivilege,  // name of privilege to enable/disable                  BOOL bEnablePrivilege   // to enable or disable privilege                  ) {    TOKEN_PRIVILEGES tp;    LUID luid;    if ( !LookupPrivilegeValue(         NULL,            // lookup privilege on local system        lpszPrivilege,   // privilege to lookup         &luid ) )        // receives LUID of privilege    {        printf("LookupPrivilegeValue error: %u\n", GetLastError() );         return FALSE;     }    tp.PrivilegeCount = 1;    tp.Privileges[0].Luid = luid;    if (bEnablePrivilege)        tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;    else        tp.Privileges[0].Attributes = 0;    // Enable the privilege or disable all privileges.    if ( !AdjustTokenPrivileges(        hToken,         FALSE,         &tp,         sizeof(TOKEN_PRIVILEGES),         (PTOKEN_PRIVILEGES) NULL,         (PDWORD) NULL) )    {         printf("AdjustTokenPrivileges error: %u\n", GetLastError() );         return FALSE;     }     if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)    {        printf("The token does not have the specified privilege. \n");        return FALSE;    }     return TRUE;}int main(void){    DWORD dwRtnCode = 0;    PSID pSidOwner = NULL, pSidGroup=NULL;    PACL pDacl = NULL, pSacl = NULL;    BOOL bRtnBool = TRUE;    LPTSTR AcctName = NULL;    LPTSTR DomainName = NULL;    DWORD dwAcctName = 1, dwDomainName = 1;    SID_NAME_USE eUse = SidTypeUnknown;    HANDLE hFile;    PSECURITY_DESCRIPTOR pSD = NULL;    HANDLE hToken = NULL;    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken))        return -1;        SetPrivilege(hToken, SE_SECURITY_NAME, TRUE);    // Get the handle of the file object.    hFile = CreateFile(        TEXT("h:\\workspace\\Test\\test2\\test2\\test2.cpp"),        GENERIC_READ | READ_CONTROL | ACCESS_SYSTEM_SECURITY,        FILE_SHARE_READ,        NULL,        OPEN_EXISTING,        FILE_ATTRIBUTE_NORMAL,        NULL);    // Check GetLastError for CreateFile error code.    if (hFile == INVALID_HANDLE_VALUE) {        DWORD dwErrorCode = 0;        dwErrorCode = GetLastError();        _tprintf(TEXT("CreateFile error = %d\n"), dwErrorCode);        return -1;    }    // Get the owner SID of the file.    dwRtnCode = GetSecurityInfo(        hFile,        SE_FILE_OBJECT,        DACL_SECURITY_INFORMATION        | SACL_SECURITY_INFORMATION        | OWNER_SECURITY_INFORMATION        | GROUP_SECURITY_INFORMATION        ,         &pSidOwner,        &pSidGroup,        &pDacl,        &pSacl,        &pSD);    // Check GetLastError for GetSecurityInfo error condition.    if (dwRtnCode != ERROR_SUCCESS) {        DWORD dwErrorCode = 0;        dwErrorCode = GetLastError();        _tprintf(TEXT("GetSecurityInfo error = %d\n"), dwErrorCode);        return -1;    }    // First call to LookupAccountSid to get the buffer sizes.    bRtnBool = LookupAccountSid(        NULL,           // local computer        pSidOwner,        AcctName,        (LPDWORD)&dwAcctName,        DomainName,        (LPDWORD)&dwDomainName,        &eUse);    // Reallocate memory for the buffers.    AcctName = (LPTSTR)GlobalAlloc(        GMEM_FIXED,        dwAcctName);    // Check GetLastError for GlobalAlloc error condition.    if (AcctName == NULL) {        DWORD dwErrorCode = 0;        dwErrorCode = GetLastError();        _tprintf(TEXT("GlobalAlloc error = %d\n"), dwErrorCode);        return -1;    }    DomainName = (LPTSTR)GlobalAlloc(        GMEM_FIXED,        dwDomainName);    // Check GetLastError for GlobalAlloc error condition.    if (DomainName == NULL) {        DWORD dwErrorCode = 0;        dwErrorCode = GetLastError();        _tprintf(TEXT("GlobalAlloc error = %d\n"), dwErrorCode);        return -1;    }    // Second call to LookupAccountSid to get the account name.    bRtnBool = LookupAccountSid(        NULL,                   // name of local or remote computer        pSidOwner,              // security identifier        AcctName,               // account name buffer        (LPDWORD)&dwAcctName,   // size of account name buffer         DomainName,             // domain name        (LPDWORD)&dwDomainName, // size of domain name buffer        &eUse);                 // SID type    // Check GetLastError for LookupAccountSid error condition.    if (bRtnBool == FALSE) {        DWORD dwErrorCode = 0;        dwErrorCode = GetLastError();        if (dwErrorCode == ERROR_NONE_MAPPED)            _tprintf(TEXT("Account owner not found for specified SID.\n"));        else             _tprintf(TEXT("Error in LookupAccountSid.\n"));        return -1;    } else if (bRtnBool == TRUE)     // Print the account name.    _tprintf(TEXT("Account owner = %s\n"), AcctName);    // 列印dacl的資訊    if (NULL == pDacl || !IsValidAcl(pDacl)) return -1;    ACL_SIZE_INFORMATION asi;    if (!GetAclInformation(pDacl, &asi, sizeof(asi), AclSizeInformation))        return -1;    for (int i = 0; i < asi.AceCount; ++i)    {        void * pAce = NULL;        GetAce(pDacl, i, &pAce);        printf("Access Credential Entries[%d] is at %p\n", i, pAce);    }    return 0;}

=======================

建立帶安全屬性的對象-檔案

=======================

void CreateKeyWithSecDesc(char * filePath){    DWORD dwRes, dwDisposition;    LONG lRes;    // 為EveryOne組建立一個知名sid    SID_IDENTIFIER_AUTHORITY SIDAuthWorld         = SECURITY_WORLD_SID_AUTHORITY;    PSID pEveryoneSID = NULL;    if(!AllocateAndInitializeSid(&SIDAuthWorld, 1,                                SECURITY_WORLD_RID,                                0, 0, 0, 0, 0, 0, 0,                                &pEveryoneSID))    {        _tprintf(_T("AllocateAndInitializeSid Error %u\n"), GetLastError());        goto Cleanup;    }    // 為ACE初始化一個"顯示訪問"結構    // 這個ACE允許EveryOne讀取這個對象    EXPLICIT_ACCESS ea[2];    ZeroMemory(&ea, 2 * sizeof(EXPLICIT_ACCESS));    ea[0].grfAccessPermissions = FILE_GENERIC_READ | FILE_GENERIC_EXECUTE;    ea[0].grfAccessMode = SET_ACCESS;    ea[0].grfInheritance= NO_INHERITANCE;    ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID;    ea[0].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;    ea[0].Trustee.ptstrName  = (LPTSTR) pEveryoneSID;    // 為Administrator 群組建立一個sid    SID_IDENTIFIER_AUTHORITY SIDAuthNT         = SECURITY_NT_AUTHORITY;    PSID pAdminSID = NULL;    if(! AllocateAndInitializeSid(&SIDAuthNT, 2,                                SECURITY_BUILTIN_DOMAIN_RID,                                DOMAIN_ALIAS_RID_ADMINS,                                0, 0, 0, 0, 0, 0,                                &pAdminSID))     {        _tprintf(_T("AllocateAndInitializeSid Error %u\n"), GetLastError());        goto Cleanup;     }    // 為ACE初始化一個"顯示訪問"結構    // 這個ACE允許Administrator 群組完全控制這個對象的權力    ea[1].grfAccessPermissions = FILE_ALL_ACCESS;    ea[1].grfAccessMode = SET_ACCESS;    ea[1].grfInheritance= NO_INHERITANCE;    ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID;    ea[1].Trustee.TrusteeType = TRUSTEE_IS_GROUP;    ea[1].Trustee.ptstrName  = (LPTSTR) pAdminSID;    // 建立一個新的acl,包含以上設定的2個ACE    // ACE機器可讀的,所以用“顯示訪問”結構    // 去建立ACL    PACL pACL = NULL;    dwRes = SetEntriesInAcl(2, ea, NULL, &pACL);    if (ERROR_SUCCESS != dwRes)     {        _tprintf(_T("SetEntriesInAcl Error %u\n"), GetLastError());        goto Cleanup;    }    // 分配一個最小"安全性描述元".      PSECURITY_DESCRIPTOR pSD = NULL;    pSD = (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR,         SECURITY_DESCRIPTOR_MIN_LENGTH);     if (NULL == pSD)     {         _tprintf(_T("LocalAlloc Error %u\n"), GetLastError());        goto Cleanup;     }     // 初始化"安全性描述元"    if (!InitializeSecurityDescriptor(pSD,        SECURITY_DESCRIPTOR_REVISION))     {          _tprintf(_T("InitializeSecurityDescriptor Error %u\n"),            GetLastError());        goto Cleanup;     }     // 把ACL添加到“安全性描述元 ”    if (!SetSecurityDescriptorDacl(pSD,         TRUE,     // bDaclPresent flag           pACL,         FALSE))   // not a default DACL     {          _tprintf(_T("SetSecurityDescriptorDacl Error %u\n"),            GetLastError());        goto Cleanup;     }     // 把安全性描述元設定到安全屬性結構中    SECURITY_ATTRIBUTES sa;    sa.nLength = sizeof (SECURITY_ATTRIBUTES);    sa.lpSecurityDescriptor = pSD;    sa.bInheritHandle = FALSE;    // 使用安全屬性結構作為參數,    // 把安全性描述元資訊設定到新建立對象中    HANDLE hFile = CreateFileA(filePath        , FILE_GENERIC_READ | FILE_GENERIC_WRITE | FILE_GENERIC_EXECUTE        , FILE_SHARE_READ | FILE_SHARE_WRITE        , &sa        , CREATE_ALWAYS        , FILE_ATTRIBUTE_NORMAL        , NULL);    if (hFile != INVALID_HANDLE_VALUE)    {        CloseHandle(hFile);    }    else        _tprintf(_T("CreateFile result %u\n"), lRes );Cleanup:    if (pEveryoneSID)         FreeSid(pEveryoneSID);    if (pAdminSID)         FreeSid(pAdminSID);    if (pACL)         LocalFree(pACL);    if (pSD)         LocalFree(pSD);    return;}

3) 授權的過程

一個線程訪問一個資源,系統首先檢查這個線程的impersionate token,如果沒有就是用進程的access token,從裡面擷取到sid,然後遍曆dacl的ace,查看和這個sid相關的每一個ace,知道找的一個拒絕或者允許的ace,就返回。

http://msdn.microsoft.com/en-us/library/windows/desktop/aa374860(v=VS.85).aspx

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.