建立適當的 選擇性訪問控制清單 (DACL) 是應用程式開發的必要和重要部分。 由於 NULL DACL 允許所有使用者的所有類型的存取權,因此請勿使用 NULL DACL。
Warning
NULL DACL 會讓所有人完全存取,包括不受信任的使用者和遠端攻擊者。 切勿在任何可保護的物件上使用 NULL DACL。 如果您需要開放廣泛存取權限,請建立明確的 DACL,並授予所需的最低權限。 空的 DACL(ACE 為零的 DACL)會拒絕所有存取——如果你不確定該授予哪些權限,這是安全的預設。
下列範例示範如何正確建立DACL。 此範例包含一個函式 CreateMyDACL,它會使用 安全性描述元定義語言 (SDDL) 定義 DACL 中授與和拒絕的存取控制。 若要為應用程式的物件提供不同的存取權,請視需要修改 CreateMyDACL 函式。
在範例中:
main 函式會將 SECURITY_ATTRIBUTES 結構的位址傳遞給 CreateMyDACL 函式。
CreateMyDACL 函式會使用 SDDL 字串來:
- 拒絕來賓和匿名登入使用者的存取權。
- 允許對已驗證的用戶進行讀取/寫入/執行存取。
- 允許系統管理員擁有完全控制權。
如需 SDDL 字串格式的詳細資訊,請參閱 安全性描述元字串格式。
CreateMyDACL 函式會呼叫 convertStringSecurityDescriptorToSecurityDescriptor 函式,將 SDDL 字符串轉換成 安全性描述元。 安全性描述元是由 lpSecurityDescriptorSECURITY_ATTRIBUTES 結構的成員所指向。 CreateMyDACL 會將 ConvertStringSecurityDescriptorToSecurityDescriptor 傳回值傳送至主函式。
main 函式會使用更新的 SECURITY_ATTRIBUTES 結構,為 CreateDirectory 函式所建立的新資料夾指定 DACL。
當 main 函式使用 SECURITY_ATTRIBUTES 結構完成時,main 函式會呼叫 LocalFree 函式,釋放為 lpSecurityDescriptor 成員配置的記憶體。
注意
若要成功編譯 SDDL 函式,例如 ConvertStringSecurityDescriptorToSecurityDescriptor,您必須將_WIN32_WINNT常數定義為0x0500或更新版本。 現代應用中,至少要鎖定Windows 10(0x0A00)。
#include <windows.h>
#include <sddl.h>
#include <stdio.h>
#pragma comment(lib, "advapi32.lib")
BOOL CreateMyDACL(SECURITY_ATTRIBUTES *);
void main()
{
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.bInheritHandle = FALSE;
// Call function to set the DACL. The DACL
// is set in the SECURITY_ATTRIBUTES
// lpSecurityDescriptor member.
if (!CreateMyDACL(&sa))
{
// Error encountered; generate message and exit.
printf("Failed CreateMyDACL\n");
exit(1);
}
// Use the updated SECURITY_ATTRIBUTES to specify
// security attributes for securable objects.
// This example uses security attributes during
// creation of a new directory.
if (0 == CreateDirectory(TEXT("C:\\MyFolder"), &sa))
{
// Error encountered; generate message and exit.
printf("Failed CreateDirectory\n");
exit(1);
}
// Free the memory allocated for the SECURITY_DESCRIPTOR.
if (NULL != LocalFree(sa.lpSecurityDescriptor))
{
// Error encountered; generate message and exit.
printf("Failed LocalFree\n");
exit(1);
}
}
// CreateMyDACL.
// Create a security descriptor that contains the DACL
// you want.
// This function uses SDDL to make Deny and Allow ACEs.
//
// Parameter:
// SECURITY_ATTRIBUTES * pSA
// Pointer to a SECURITY_ATTRIBUTES structure. It is your
// responsibility to properly initialize the
// structure and to free the structure's
// lpSecurityDescriptor member when you have
// finished using it. To free the structure's
// lpSecurityDescriptor member, call the
// LocalFree function.
//
// Return value:
// FALSE if the address to the structure is NULL.
// Otherwise, this function returns the value from the
// ConvertStringSecurityDescriptorToSecurityDescriptor
// function.
BOOL CreateMyDACL(SECURITY_ATTRIBUTES * pSA)
{
// Define the SDDL for the DACL. This example sets
// the following access:
// Built-in guests are denied all access.
// Anonymous logon is denied all access.
// Authenticated users are allowed
// read/write/execute access.
// Administrators are allowed full control.
// Modify these values as needed to generate the proper
// DACL for your application.
TCHAR * szSD = TEXT("D:") // Discretionary ACL
TEXT("(D;OICI;GA;;;BG)") // Deny access to
// built-in guests
TEXT("(D;OICI;GA;;;AN)") // Deny access to
// anonymous logon
TEXT("(A;OICI;GRGWGX;;;AU)") // Allow
// read/write/execute
// to authenticated
// users
TEXT("(A;OICI;GA;;;BA)"); // Allow full control
// to administrators
if (NULL == pSA)
return FALSE;
return ConvertStringSecurityDescriptorToSecurityDescriptor(
szSD,
SDDL_REVISION_1,
&(pSA->lpSecurityDescriptor),
NULL);
}