Tell us about your PDF experience. Best Practices for the Security APIs Article • 01/26/2022 • 2 minutes to read To help develop secure software, we recommend that you use the following best practices when developing applications. For more information, see Security Developer Center . Security Development Life Cycle The Security Development Life Cycle (SDL) is a process that aligns a series of securityfocused activities and deliverables to each phase of software development. These activities and deliverables include: Developing threat models Using code-scanning tools Conducting code reviews and security testing For more information about the SDL, see the Microsoft Security Development Lifecycle . Threat Models Conducting a threat model analysis can help you discover potential points of attack in your code. For more information about threat model analysis, see Howard, Michael and LeBlanc, David [2003], Writing Secure Code, 2d ed., ISBN 0-7356-1722-8, Microsoft Press, Redmond, Washington. (This resource may not be available in some languages and countries.) Service Packs and Security Updates Build and test environments should mirror the same levels of service packs and security updates of the targeted user base. We recommend that you install the latest service packs and security updates for any Microsoft platform or application that is part of your build and test environment and encourage your users to do the same for the finished application environment. For more information about service packs and security updates, see Microsoft Windows Update Authorization and Microsoft Security . You should create applications that require the least possible privilege. Using the least possible privilege reduces the risk of malicious code compromising your computer system. For more information about running code in least possible privilege level, see Running with Special Privileges. More Information For more information about best practices, see the following topics. Topic Description Running with Special Privileges Discusses security implications of privileges. Avoiding Buffer Overruns Provides information about avoiding buffer overruns. Control Flow Guard (CFG) Discusses memory corruption vulnerabilities. Creating a DACL Shows how to create a discretionary access control list (DACL) by using the Security Descriptor Definition Language (SDDL). Handling Passwords Discusses security implications of using passwords. How to Optimize Your Discusses options for searching Security SDK content on MSDN MSDN Library Search Library. Dynamic Access Control Basic orientation to some of the developer extensibility points for the developer extensibility new Dynamic Access Control solutions. Running with Special Privileges Article • 01/07/2021 • 2 minutes to read Some functions require special privileges to run correctly. In some cases, the function can only be run by certain users or by members of certain groups. The most common requirement is that the user be a local administrator. Other functions require the user's account to have specific privileges enabled. To reduce the possibility of unauthorized code being able to get control, the system should run with the least privilege necessary. Applications that need to call functions that require special privileges can leave the system open to attack by hackers. Such applications should be designed to run for short periods of time and should inform the user of the security implications involved. For information about how to run as different users and how to enable privileges in your application, see the following topics: Running with Administrator Privileges Asking the User for Credentials Changing Privileges in a Token Assigning Privileges to an Account Running with Administrator Privileges Article • 01/07/2021 • 2 minutes to read The first step in establishing which type of account your application needs to run under is to examine what resources the application will use and what privileged APIs it will call. You may find that the application, or large parts of it, do not require administrator privileges. Writing Secure Code, by Michael Howard and David LeBlanc offers an excellent description of how to carry out this assessment and is highly recommended. (This resource may not be available in some languages and countries.) You can provide the privileges your application needs with less exposure to malicious attack by using one of the following approaches: Run under an account with less privilege. One way to do this is to use PrivilegeCheck to determine what privileges are enabled in a token. If the available privileges are not adequate for the current operation, you can disable that code and ask the user to logon to an account with administrator privileges. Break into a separate application functions that require administrator permissions. You can provide for the user a shortcut that executes the RunAs command. For detailed instructions on how to set up the shortcut, search for "runas" in Help. Programmatically, you can configure the RunAs command under the AppId Key registry key for your application. Authenticate the user by calling CredUIPromptForCredentials (GUI) or CredUICmdLinePromptForCredentials (command line) to obtain user name and password. For an example, see Asking the User for Credentials. Impersonate the user. A process that starts under a highly privileged account like System can impersonate a user account by calling ImpersonateLoggedOnUser or similar Impersonate functions, thus reducing privilege level. However, if a call to RevertToSelf is injected into the thread, the process returns to the original System privileges. If you have determined that your application must run under an account with administrator privileges and that an administrator password must be stored in the software system, see Handling Passwords for methods of doing this safely. Asking the User for Credentials Article • 01/07/2021 • 2 minutes to read Your application may need to prompt the user for user name and password information to avoid storing an administrator password or to verify that the token holds the appropriate privileges. However, simply prompting for credentials may train users to supply those to any random, unidentified dialog box that appears on the screen. The following procedure is recommended to reduce that training effect. To properly acquire user credentials 1. Inform the user, by using a message that is clearly part of your application, that they will see a dialog box that requests their user name and password. You can also use the CREDUI_INFO structure on the call to CredUIPromptForCredentials to convey identifying data or a message. 2. Call CredUIPromptForCredentials. Note that the maximum number of characters specified for user name and password information includes the terminating null character. 3. Call CredUIParseUserName and CredUIConfirmCredentials to verify that you obtained appropriate credentials. The following example shows how to call CredUIPromptForCredentials to ask the user for a user name and password. It begins by filling in a CREDUI_INFO structure with information about what prompts to use. Next, the code fills two buffers with zeros. This is done to ensure that no information gets passed to the function that might reveal an old user name or password to the user. The call to CredUIPromptForCredentials brings up the dialog box. For security reasons, this example uses the CREDUI_FLAGS_DO_NOT_PERSIST flag to prevent the operating system from storing the password because it might then be exposed. If there are no errors, CredUIPromptForCredentials fills in the pszName and pszPwd variables and returns zero. When the application has finished using the credentials, it should put zeros in the buffers to prevent the information from being accidentally revealed. CREDUI_INFO cui; TCHAR pszName[CREDUI_MAX_USERNAME_LENGTH+1]; TCHAR pszPwd[CREDUI_MAX_PASSWORD_LENGTH+1]; BOOL fSave; DWORD dwErr; cui.cbSize = sizeof(CREDUI_INFO); cui.hwndParent = NULL; // Ensure that MessageText and CaptionText identify what credentials // to use and which application requires them. cui.pszMessageText = TEXT("Enter administrator account information"); cui.pszCaptionText = TEXT("CredUITest"); cui.hbmBanner = NULL; fSave = FALSE; SecureZeroMemory(pszName, sizeof(pszName)); SecureZeroMemory(pszPwd, sizeof(pszPwd)); dwErr = CredUIPromptForCredentials( &cui, // CREDUI_INFO structure TEXT("TheServer"), // Target for credentials // (usually a server) NULL, // Reserved 0, // Reason pszName, // User name CREDUI_MAX_USERNAME_LENGTH+1, // Max number of char for user name pszPwd, // Password CREDUI_MAX_PASSWORD_LENGTH+1, // Max number of char for password &fSave, // State of save check box CREDUI_FLAGS_GENERIC_CREDENTIALS | // flags CREDUI_FLAGS_ALWAYS_SHOW_UI | CREDUI_FLAGS_DO_NOT_PERSIST); if(!dwErr) { // Put code that uses the credentials here. // When you have finished using the credentials, // erase them from memory. SecureZeroMemory(pszName, sizeof(pszName)); SecureZeroMemory(pszPwd, sizeof(pszPwd)); } Related topics CredUICmdLinePromptForCredentials CREDUI_UINFO Changing Privileges in a Token Article • 01/07/2021 • 2 minutes to read You can change the privileges in either a primary or an impersonation token in two ways: Enable or disable privileges by using the AdjustTokenPrivileges function. Restrict or remove privileges by using the CreateRestrictedToken function. AdjustTokenPrivileges cannot add or remove privileges from the token. It can only enable existing privileges that are currently disabled or disable existing privileges that are currently enabled. For examples, see Enabling and Disabling Privileges in C++. To assign privileges to a user account, see Assigning Privileges to an Account. CreateRestrictedToken has more extensive capabilities as follows: Removing a privilege. Note that removing a privilege is not the same as disabling one. After a privilege is removed from a token, it cannot be put back. Attaching the deny-only attribute to SIDs in the token. This has the effect of disallowing specific groups or accounts, for example, denying the Everyone group delete access to a particular file. For more information on restricting SIDs, see SID Attributes in an Access Token. Specifying a list of restricting SIDs in the token. For information about restricting SIDs, see Restricted Tokens. Assigning Privileges to an Account Article • 01/07/2021 • 2 minutes to read You can assign privileges to accounts either by using the Local Security Policy Microsoft Management Console (MMC) snap-in (Secpol.msc) or by calling the LsaAddAccountRights function. Assigning a privilege to an account does not affect existing user tokens. A user must log off and then log back on to get an access token with the newly assigned privilege. To assign privileges by using the Local Security Policy MMC snap-in, edit the list of users for each privilege listed under Security Settings/Local Policies/User Rights Assignment. Avoiding Buffer Overruns Article • 01/07/2021 • 2 minutes to read A buffer overrun is one of the most common sources of security risk. A buffer overrun is essentially caused by treating unchecked, external input as trustworthy data. The act of copying this data, using operations such as CopyMemory, strcat, strcpy, or wcscpy, can create unanticipated results, which allows for system corruption. In the best of cases, your application will abort with a core dump, segmentation fault, or access violation. In the worst of cases, an attacker can exploit the buffer overrun by introducing and executing other malicious code in your process. Copying unchecked, input data into a stack-based buffer is the most common cause of exploitable faults. Buffer overruns can occur in a variety of ways. The following list provides a brief introduction to a few types of buffer overrun situations and offers some ideas and resources to help you avoid creating new risks and mitigate existing ones: Static buffer overruns A static buffer overrun occurs when a buffer, which has been declared on the stack, is written to with more data than it was allocated to hold. The less apparent versions of this error occur when unverified user input data is copied directly to a static variable, causing potential stack corruption. Heap overruns Heap overruns, like static buffer overruns, can lead to memory and stack corruption. Because heap overruns occur in heap memory rather than on the stack, some people consider them to be less able to cause serious problems; nevertheless, heap overruns require real programming care and are just as able to allow system risks as static buffer overruns. Array indexing errors Array indexing errors also are a source of memory overruns. Careful bounds checking and index management will help prevent this type of memory overrun. Preventing buffer overruns is primarily about writing good code. Always validate all your inputs and fail gracefully when necessary. For more information about writing secure code, see the following resources: Maguire, Steve [1993], Writing Solid Code, ISBN 1-55615-551-4, Microsoft Press, Redmond, Washington. Howard, Michael and LeBlanc, David [2003], Writing Secure Code, 2d ed., ISBN 07356-1722-8, Microsoft Press, Redmond, Washington. 7 Note These resources may not be available in some languages and countries. Safe string handling is a long-standing issue that continues to be addressed both by following good programming practices and often by using and retrofitting existing systems with secure, string-handling functions. An example of such a set of functions for the Windows shell starts with StringCbCat. Control Flow Guard for platform security Article • 02/08/2022 • 3 minutes to read What is Control Flow Guard? Control Flow Guard (CFG) is a highly-optimized platform security feature that was created to combat memory corruption vulnerabilities. By placing tight restrictions on where an application can execute code from, it makes it much harder for exploits to execute arbitrary code through vulnerabilities such as buffer overflows. CFG extends previous exploit mitigation technologies such as /GS, DEP, and ASLR. Prevent memory corruption and ransomware attacks. Restrict the capabilities of the server to whatever is needed at a particular point in time to reduce attack surface. Make it harder to exploit arbitrary code through vulnerabilities such as buffer overflows. This feature is available in Microsoft Visual Studio 2015, and runs on "CFG-Aware" versions of Windows—the x86 and x64 releases for Desktop and Server of Windows 10 and Windows 8.1 Update (KB3000850). We strongly encourage developers to enable CFG for their applications. You don't have to enable CFG for every part of your code, as a mixture of CFG enabled and non-CFG enabled code will execute fine. But failing to enable CFG for all code can open gaps in the protection. Furthermore, CFG enabled code works fine on "CFG-Unaware" versions of Windows and is therefore fully compatible with them. How Can I Enable CFG? In most cases, there is no need to change source code. All you have to do is add an option to your Visual Studio 2015 project, and the compiler and linker will enable CFG. The simplest method is to navigate to Project | Properties | Configuration Properties | C/C++ | Code Generation and choose Yes (/guard:cf) for Control Flow Guard. Alternatively, add /guard:cf to Project | Properties | Configuration Properties | C/C++ | Command Line | Additional Options (for the compiler) and /guard:cf to Project | Properties | Configuration Properties | Linker | Command Line | Additional Options (for the linker). See /guard (Enable Control Flow Guard) for additional info. If you are building your project from the command line, you can add the same options. For example, if you are compiling a project called test.cpp, use cl /guard:cf test.cpp /link /guard:cf. You also have the option of dynamically controlling the set of icall target addresses that are considered valid by CFG using the SetProcessValidCallTargets from the Memory Management API. The same API can be used to specify whether pages are invalid or valid targets for CFG. The VirtualProtect and VirtualAlloc functions will by default treat a specified region of executable and committed pages as valid indirect call targets. It is possible to override this behavior, such as when implementing a Just-in-Time compiler, by specifying PAGE_TARGETS_INVALID when calling VirtualAlloc or PAGE_TARGETS_NO_UPDATE when calling VirtualProtect as detailed under Memory Protection Constants. How Do I Tell That a Binary is under Control Flow Guard? Run the dumpbin tool (included in the Visual Studio 2015 installation) from the Visual Studio command prompt with the /headers and /loadconfig options: dumpbin /headers /loadconfig test.exe. The output for a binary under CFG should show that the header values include "Guard", and that the load config values include "CF Instrumented" and "FID table present". How Does CFG Really Work? Software vulnerabilities are often exploited by providing unlikely, unusual, or extreme data to a running program. For example, an attacker can exploit a buffer overflow vulnerability by providing more input to a program than expected, thereby over-running the area reserved by the program to hold a response. This could corrupt adjacent memory that may hold a function pointer. When the program calls through this function it may then jump to an unintended location specified by the attacker. However, a potent combination of compile and run-time support from CFG implements control flow integrity that tightly restricts where indirect call instructions can execute. The compiler does the following: 1. Adds lightweight security checks to the compiled code. 2. Identifies the set of functions in the application that are valid targets for indirect calls. The runtime support, provided by the Windows kernel: 1. Efficiently maintains state that identifies valid indirect call targets. 2. Implements the logic that verifies that an indirect call target is valid. To illustrate: When a CFG check fails at runtime, Windows immediately terminates the program, thus breaking any exploit that attempts to indirectly call an invalid address. PE metadata Article • 01/07/2021 • 16 minutes to read This article provides additional details for Control Flow Guard (CFG) metadata in PE images. Familiarity with the structure for CFG metadata in PE images is assumed. See the PE Format topic for high-level documentation for CFG metadata in PE images. Functions that are valid indirect call targets are listed in the GuardCFFunctionTable attached to the load configuration directory, sometimes termed the GFIDS table for brevity. This is a sorted list of relative virtual addresses (RVA) that contain information about valid CFG call targets. These are, generally speaking, address taken function symbols. An image that wants CFG enforcement must enumerate all address taken function symbols in its GFIDS table. The RVA list in the GFIDS table must be sorted properly or the image will not be loaded. The GFIDS table is an array of 4 + n bytes, where n is given by ((GuardFlags & IMAGE_GUARD_CF_FUNCTION_TABLE_SIZE_MASK) >> IMAGE_GUARD_CF_FUNCTION_TABLE_SIZE_SHIFT). “GuardFlags” is the GuardFlags field of the load configuration directory. This allows for extra metadata to be attached to CFG call targets in the future. The only currently defined metadata is an optional 1-byte extra flags field (“GFIDS flags”) that is attached to each GFIDS entry if any call targets have metadata. There are two GFIDS flags defined: IMAGE_GUARD_FLAG_FID_SUPPRESSED/0x1 Call target is explicitly suppressed (do not treat it as valid for purposes of CFG) IMAGE_GUARD_FLAG_EXPORT_SUPPRESSED/0x2 Call target is export suppressed. See Export suppression for more details For future compatibility, tools should not set GFIDS flags that have not yet been defined and should not include additional GFIDS extra metadata bytes beyond the 1-byte currently defined since the meanings for other flags or additional metadata are not yet assigned. You can find examples of images that include extra metadata bytes by dumping the GFIDS table of binaries such as Ntdll.dll on a modern Windows 10 OS version. Tools should only declare function symbols as valid call targets which may merit additional consideration for assembler code where labels might be address taken. For historical reasons, assembler code may rely on code labels other than PROC or .altentry as not being converted into CFG call targets by the linker. Also for historical reasons, code may deliberately declare code as data to avoid inclusion in the GFIDS table. For example, one object file may implement a symbol as code while another may declare it as data in order to take the address of the symbol without generating a valid CFG target record. For compatibility, it is recommended that toolsets support this practice. Images that support CFG and that want or perform CFG checks should set the IMAGE_GUARD_CF_INSTRUMENTED and IMAGE_GUARD_CF_FUNCTION_TABLE_PRESENT GuardFlags bits, and should set the IMAGE_DLLCHARACTERISTICS_GUARD_CF DllCharacteristics bit in the image headers. The load configuration directory advertises two function pointers: GuardCFCheckFunctionPointer and GuardCFDispatchFunctionPointer (the latter is only supported for certain architectures such as AMD64). These function pointers should point to read only memory for CFG security to be effective; the operating system’s DLL loader will reprotect the memory transiently during image loading to store the function pointers. Typical usage might be to merge these into the same section that contains the Import Address Table (IAT). The GuardCFCheckFunctionPointer provides the address of an OS-loader provided symbol that can be called with a function pointer in the first integer argument register (ECX on x86) which will return on success or will abort the process if the call target is not a valid CFG target. The GuardCFDispatchFunctionPointer provides the address of an OS-loader provided symbol that takes a call target in register RAX and performs a combined CFG check and tail branch optimized call to the call target (registers R10/R11 are reserved for use by the GuardCFDispatchFunctionPointer and integer argument registers are reserved for use by the ultimate call target). The default address of the CFG symbols in an image should point to a function that just returns (GuardCFCheckFunctionPointer) or that returns a guard-suppressed symbol (or is preferably entirely omitted from the GFIDS table symbol) that executes a “jmp rax” instruction. For AMD64 GuardCFDispatchFunctionPointer, when an image is loaded on a CFG-aware operating system, and CFG is enabled, the OS DLL loader will install appropriate function pointers, which facilities backwards compatibility. An image can supply 0 for the GuardCFDispatchFunctionPointer in the load config if it does not intend to use the CFG dispatch facility. This should be done for non-AMD64 architectures for future compatibility, in case these architectures eventually support the CFG dispatch mechanism in some form. Note that Windows 8.1 AMD64 did not support CFG dispatch and would leave the default function pointer in place for GuardCFDispatchFunctionPointer. CFG dispatch is only supported on Windows 10 and later operating systems. User mode CFG might only be enforced for images that are marked as address space layout randomization (ASLR) compatible (specified by the /DYNAMICBASE option with the Microsoft linker). This is due to how the OS internally handles CFG where it is essentially wired in to the ASLR infrastructure. In general, users of CFG should enable ASLR for their images as a first step. Tools should not assume that the OS will always ignore CFG without ASLR set but should generally set both at the same time. Compiler directives Call targets can be marked as explicitly suppressed with the __declspec(guard(suppress)) modifier, or with the /guardsym:symname,S linker directive (for asm code for example). This causes the call target to be included in the GFIDS table but marked in such a way that the OS will treat the call target as not valid. Some non-production scenarios, such as with certain application verifier instrumentation enabled on some older operating systems, may enable suppressed call targets to be treated as valid, but in general these scenarios are not expected to be production scenarios. This directive is useful for annotating “dangerous” functions that should not be considered as valid call targets, even though the normal CFG rule would include them. Code can indicate CFG checks are not wanted with the __declspec(guard(nocf)) modifier. This directs the compiler to not insert any CFG checks for the entire function. The compiler should take care to propagate this directive to any code contributed by an inlined function that is marked as not wanting CFG checks. This approach is typically used only sparingly in specific situations where the programmer has manually inserted “CFG-equivalent” protection. The programmer knows that they are calling through some read only function table whose address is obtained through read only memory references and for which the index is masked to the function table limit. This approach may also be applied to small wrapper functions that are not inlined and that do nothing more than make a call through a function pointer. Since incorrect usage of this directive can compromise the security of CFG, the programmer must be very careful using the directive. Typically, this usage is limited to very small functions that only call one function. Import handling Calls through the IAT should not use CFG protection. The IAT is read only in modern images (assuming that the IAT is declared in the PE headers in which case it must be on its own pages). The IAT can be used to reach functions that are guard suppressed, so this is a correctness requirement. Read only memory protection through the IAT supersedes that of CFG since the call target binding is immutable after the image import snaps are resolved, and the binding resolution is fine grained. Protected delay load: Calls through the delay load IAT should not use CFG protection, for the same reasons as the standard IAT. The delay load IAT should be in its own section and the image should set the IMAGE_GUARD_CF_PROTECT_DELAYLOAD_IAT GuardFlags bit. This indicates that the operating system’s DLL loader should change protections for the delay load IAT during export resolution if using the operating system’s delay load support native to Windows 8 and later operating systems. The synchronization of this step is managed by the operating system DLL loader if native operating system delay load support is in use (e.g. ResolveDelayLoadedAPI) so no other component should reprotect the pages spanning the declared delay load IAT. For backwards compatibility with older pre-CFG operating systems, tools may enable the option to move the delay load IAT into its own section (canonically “.didat”), protected as read/write in the image headers, and additionally set the IMAGE_GUARD_CF_DELAYLOAD_IAT_IN_ITS_OWN_SECTION flag. This setting will cause CFG-aware operating system DLL loaders to reprotect the entire section containing the IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT table to read only memory during image loading. The option to place the delay load IAT in its own section may not be required if you do not care about running an image on operating systems that predate CFG support, but tools should make that decision based on the minimum operating system support that an image needs. If an image does not use the operating system’s native delay load support, it can still set the protected delay load related GuardFlags bits. In this configuration, the operating system loader will just provide support to protect the delay load IAT as read only at runtime if supported by the platform, and it becomes the responsibility of the image’s internal delay load resolution stubs to synchronize and manage protection of the delay load IAT. Provided that the load configuration table is stored in read only memory (which is recommended), the presence or absence of the protected delay load IAT bit in the image’s GuardFlags field might be useful as an internal hint to the image’s internal delay load resolution stubs to indicate whether or not it should protect the delay load IAT. It is recommended that protected delay load be enabled by default if CFG is enabled. Images that run on older operating system versions and that use the operating system’s native delay load support, as noted, may use the delay load IAT in its own section support for backwards compatibility. This is opposed to marking the delay load IAT as read only and merging it with another section, which would break on older operating system’s that do not understand protected delay loads and which provide native delay load resolution support. All Windows 10 releases and the first Windows 8.1/Windows Server 2012 R2 builds that supported CFG (meaning the November 2014 update) introduce support for protected delay load in the operating system. Function alignment Functions that are address taken and are therefore included in the GFIDS table should be made 16-byte aligned, if possible. This may not always be possible. For example, for non-COMDAT functions that are a part of object files assembled together as one unit by non-CFG aware tools, which some assemblers may produce, the user of the tool that produced the files must appropriately set the alignment. Tools may elect to issue a diagnostic warning in this situation so that the user can take appropriate corrective action. The reason for this is that CFG marks call targets as valid or not valid on 16-byte boundaries for efficiency of fast CFG checks. If a function is not 16-byte aligned, then the entire 16-byte slot must be marked as valid, which is not as secure since you can call misaligned into code that is not at the very start of a function. This scenario is supported for ease of interoperability when first bringing CFG up for a project. Non-CFG aware images are similarly marked as valid for any call target alignment for compatibility. As before, having misaligned call targets reduces the security benefits of CFG, so tools should automatically align to a 16-byte boundary for anything in the GFIDS table when CFG is desired for an image. Symbols that are not in the GFIDS table do not need to have particular alignments for CFG. Export suppression CFG export suppression (CFG ES) is an optional mode that enables a process to indicate that call targets which were only valid because they were dllexport symbols, and which have not yet been dynamically resolved by GetProcAddress, will be considered as not valid for purposes of CFG. This reduces the surface area of CFG from system DLL exports. Export suppression involves communicating eligible “export suppressed” dllexport call targets by marking them with the IMAGE_GUARD_FLAG_EXPORT_SUPPRESSED GFIDS flags. Dllexport symbols and the PE image entry point should be implicitly considered address taken by tools for purposes of generating the GFIDS table. If an export symbol is 16-byte aligned and it is address taken for no other reason than being a dllexport, then it can be marked with the export suppressed GFIDS flag in the function table. Call targets that are not 16-byte aligned must not be marked with the IMAGE_GUARD_FLAG_EXPORT_SUPPRESSED GFIDS flag and cannot be restricted to only being dynamically enabled as valid call targets at GetProcAddress time. An image that supports CFG ES includes a GuardAddressTakenIatEntryTable whose count is provided by the GuardAddressTakenIatEntryCount as part of its load configuration directory. This table is structurally formatted the same as the GFIDS table. It uses the same GuardFlags IMAGE_GUARD_CF_FUNCTION_TABLE_SIZE_MASK mechanism to encode extra optional metadata bytes in the address taken IAT table, though all metadata bytes must be zero for the address taken IAT table and are reserved. The address taken IAT table indicates a sorted array of RVAs of import thunks which have the imported as a symbol address taken call target. This construct supports address taken symbols that exist in a remote module, and which are dllexports, with CFG ES in use. An example of such a code construct would be: mov rcx, [__imp_DefWindowProc] call foo ; where foo takes the actual address of DefWindowProc. All such address taken import thunks must be enumerated so that the operating system loader can find them and make the appropriate call targets valid when loading an image and snapping its imports. The table and count can be 0 if there are no import thunks that were address taken. A module sets the IMAGE_GUARD_CF_EXPORT_SUPPRESSION_INFO_PRESENT GuardFlags bit to indicate that it has enumerated all address taken thunks in its address taken IAT table and that all exports that are CFG ES eligible are marked with the IMAGE_GUARD_FLAG_EXPORT_SUPPRESSED GFIDS flag. Note that there may be zero such thunks and that there may also be zero such dllexport symbols. Failure to maintain the address taken IAT table can be a correctness issue as some call targets might not be made valid when they should be at DLL load time. A module sets the IMAGE_GUARD_CF_ENABLE_EXPORT_SUPPRESSION GuardFlags bit to indicate that it wants to enable CFG ES for the process. In practice, this is only meaningful for EXEs today. A process enabling CFG ES should not load DLLs not built with CFG ES or runtime failures may occur because of undesignated address taken IAT symbols. Support for enabling CFG ES should be a separate optin option from enabling CFG. Providing CFG ES metadata is safe and recommended by default with CFG, though toolsets must take care to ensure they produce correct metadata. If not, their generated images may not run properly in a CFG ES process. Such support should be thoroughly tested in a test process that enforces CFG ES. The operating system built-in system DLLs support CFG ES metadata for modern Windows 10 operating system versions that understand CFG ES. Operating system versions prior to this support do not understand CFG ES at all and will ignore any CFG ES related directives in the image. Such images are still backwards compatible to older operating system versions. CFG ES support is optional from a toolset perspective, but it is recommended that toolsets at least include support to enumerate enough information for images to run in a process that desires CFG ES. As mentioned, it is critical that toolset support be thoroughly tested to ensure that it is compatible with CFG ES, as most processes don’t yet enable CFG ES. Exception handling and unwinding Language specific handlers like __C_specific_handler, as designated by the exception handler information in a .pdata registration, should not be marked as valid call targets in the GFIDS table. They are instead looked up by traversing read only memory. Similarly, the Microsoft C language specific handler uses read only memory searches to locate funclets for exception handlers and thus does not declare its funclets as valid call targets in the GFIDS table. Long jump handling (for non-x86 targets like AMD64): Toolsets compiling with CFG and supporting setjmp()/longjmp() should implement long jump as “safe long jump” that interoperates with structured exception handling (SEH). This means long jump is implemented as a call to RtlUnwindEx with STATUS_LONGJUMP as the status code in the supplied exception record and a standard _JUMP_BUFFER pointed to by ExceptionInformation[0]. The jump unwind target should be the TargetIp of the unwind. The jump buffer represents the register context that is restored by the operating system after the long jump has completed. RtlUnwind(Ex) when called with STATUS_LONGJUMP has special significance unique to CFG. The long jump target (_JUMP_BUFFER.Rip or _JUMP_BUFFER.Lr on ARM64) is looked up in the loaded module list maintained by the operating system in read only memory. If the containing module for the jump target (the “target module”) has the IMAGE_GUARD_CF_LONGJUMP_TABLE_PRESENT flag set in its GuardFlags field, then the load configuration directory has a GuardLongJumpTargetTable whith an element count specified by the load configuration GuardLongJumpTargetCount field. This table is structurally formatted the same as the GFIDS table and uses the same GuardFlags IMAGE_GUARD_CF_FUNCTION_TABLE_SIZE_MASK mechanism to encode optional extra metadata bytes in the long jump table. All metadata bytes must be zero for the long jump table and are reserved. The long jump table represents a sorted array of RVAs that are valid long jump targets. If a long jump target module sets IMAGE_GUARD_CF_LONGJUMP_TABLE_PRESENT in its GuardFlags field, then all long jump targets must be enumerated in the LongJumpTargetTable. Even if a module has zero long jump targets, it should still set the IMAGE_GUARD_CF_LONGJUMP_TABLE_PRESENT flag if the toolset supports long jump hardening for CFG. This explicitly means that the image has no long jump targets and is not an old image that the operating system must assume could have valid long jump targets at unmarked locations for which it cannot perform long jump target checking. Long jump hardening is recommended to be enabled by default if CFG is supported. This is the disposition of Microsoft compilers. Operating systems that do not understand long jump hardening (pre-Windows 10 or older Windows 10 versions) will not perform long jump hardening checks and ignore any long jump hardening metadata, so long jump hardening is backwards compatible with older operating system releases. For kernel mode images, the guard long jump target table should not be included in a discardable section. The guard long jump target table should always be stored in read only memory for its security properties to be effective. COFF information There are object file markings to declare whether an object file conforms to CFG or not. An object file that conforms to CFG will list the valid call targets that it produces, explicitly, as well as any address taken IAT metadata. An object file that does not conform to CFG must have call targets inferred by examining the COFF relocations of the obj file to find relocations that point to the start of a function symbol. This may overapproximate valid CFG call targets so it is desirable that tools mark their obj files that are CFG-aware and include the CFG obj file metadata if compiling with CFG. There are object file markings to declare long jump targets for CFG hardened long jump which should be populated for CFG compilation mode. Creating a DACL Article • 01/07/2021 • 2 minutes to read Creating a proper discretionary access control list (DACL) is a necessary and important part of application development. Because a NULL DACL permits all types of access to all users, do not use NULL DACLs. The following example shows how to properly create a DACL. The example contains a function, CreateMyDACL, that uses the security descriptor definition language (SDDL) to define the granted and denied access control in a DACL. To provide different access for your application's objects, modify the CreateMyDACL function as needed. In the example: 1. The main function passes an address of a SECURITY_ATTRIBUTES structure to the CreateMyDACL function. 2. The CreateMyDACL function uses SDDL strings to: Deny access to guest and anonymous logon users. Allow read/write/execute access to authenticated users. Allow full control to administrators. For more information about the SDDL string formats, see Security Descriptor String Format. 3. The CreateMyDACL function calls the ConvertStringSecurityDescriptorToSecurityDescriptor function to convert the SDDL strings to a security descriptor. The security descriptor is pointed to by the lpSecurityDescriptor member of the SECURITY_ATTRIBUTES structure. CreateMyDACL sends the return value from ConvertStringSecurityDescriptorToSecurityDescriptor to the main function. 4. The main function uses the updated SECURITY_ATTRIBUTES structure to specify the DACL for a new folder that is created by the CreateDirectory function. 5. When the main function is finished using the SECURITY_ATTRIBUTES structure, the main function frees the memory allocated for the lpSecurityDescriptor member by calling the LocalFree function. 7 Note To successfully compile SDDL functions such as ConvertStringSecurityDescriptorToSecurityDescriptor, you must define the _WIN32_WINNT constant as 0x0500 or greater. C++ #define _WIN32_WINNT 0x0500 #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; // // // if { Call function to set the DACL. The DACL is set in the SECURITY_ATTRIBUTES lpSecurityDescriptor member. (!CreateMyDACL(&sa)) // Error encountered; generate message and exit. printf("Failed CreateMyDACL\n"); exit(1); } // // // // if { Use the updated SECURITY_ATTRIBUTES to specify security attributes for securable objects. This example uses security attributes during creation of a new directory. (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); } Handling Passwords Article • 01/07/2021 • 2 minutes to read Currently, user name and password credentials are the most common credentials used for authentication. Even though other types of credentials, such as certificates and biometrics, are starting to find their way into the world of systems and networking, they are often backed up by passwords. And, even where certificates are used, their encryption keys must be protected. So, user names and passwords will continue to be used for credentials well into the foreseeable future. Given that passwords and encryption keys are going to be around a while, it is important that software systems use them in a secure fashion. If a network or computer system is to remain secure, passwords must be protected from would-be intruders. This might, at first, seem trivial. However, system after system and network after network have been compromised because an attacker has been able to sniff out users' passwords. The problems range from users sharing their passwords with someone, to software that can be penetrated by an attacker. It is impossible to store secret information in software in a completely secure fashion. And because storing passwords and encryption keys in a software system can never be completely secure, it is recommended that they not be stored in a software system. However, when passwords must be stored in a software system, which is usually the case, there are precautions that can be taken. The primary precaution is to make it as difficult as possible for an intruder to discover a password. Just like locking your house doors, if someone is determined to break in, it is nearly impossible to prevent them from doing so. But hopefully, you will have raised the level of difficulty sufficiently that the would-be intruder would rather find easier prey. There are many ways to make an attacker's job of discovering passwords harder. However, the extent of what can actually be done is usually a trade-off with what the users of the network or system are willing to live with. For example, take the case where "single sign on" is not used, and the user is prompted for a password every time an application is started. In most cases, this would create a significant burden on the users, and they would probably complain. Not only that, but lack of a single sign on is inefficient and would degrade the productivity of the users. So, practically speaking, a password generally is not collected from a user except at the time of log on. Given that passwords must usually be stored on the software system, it becomes important to ensure that passwords are kept as secure as possible and that convenience for users is maintained. For more information, see the following topics: Password Threat Assessment Threat Mitigation Techniques 7 Note When you have finished using passwords in applications, clear the sensitive information from memory by calling the SecureZeroMemory function. Password Threat Assessment Article • 01/07/2021 • 2 minutes to read Before implementing code that protects passwords, it is best to analyze your particular environment for ways that an attacker might try to penetrate software defenses. Start by analyzing your network or system architecture. Here are some examples: The number of passwords that must be protected. Is a password required to log on to the local computer? Is the same password used to log on to the network? Are passwords propagated to more than one server on the network? How many passwords must be accommodated? The kind of network (if any) that will be used. Is the network implemented using a corporate directory system (such as LDAP), and is its password architecture used? Are any objects storing unencrypted passwords? Open versus closed network. Is the network self-contained or is it open to the outside? If so, is it protected by a firewall? Remote access. Will users need to access the network from a remote location? After you have analyzed your system or network architecture, then you can start to analyze how an attacker might try to attack it. Here are some possibilities: Read an unencrypted password from a computer's registry. Read an unencrypted password that is hard-coded in the software. Read an unencrypted password from a computer's swapped-out code page. Read a password from a program's event log. Read a password from an extended Microsoft Active Directory directory service schema that has objects that contain a plaintext password. Run a debugger on a program that requires a password. Guess a password. Any of several techniques might be used. For example, the attacker might know some personal information about a user and try to guess a password from that information (for example, the name of a spouse/partner or child). Or, a brute-force method might be tried, where all combinations of letters, numbers, and punctuation are tried (only feasible where short passwords are used). Comparing the possible attack methodologies with system or network architecture will likely reveal security risks. At that point, a risk factor can be established for each risk, and the risk factors can be used to triage fixes. Threat Mitigation Techniques Article • 08/19/2021 • 3 minutes to read There are a number of threat-mitigation techniques available that you can use to better secure passwords. These techniques are implemented by using one or more of the following four, primary technologies. Technology Description CryptoAPI CryptoAPI provides a set of functions that help you apply cryptographic routines to target entities. CryptoAPI can provide hashes, digests, encryption, and decryption, to mention its primary functionality. CryptoAPI also has other features. To learn about cryptography and the CryptoAPI, see Cryptography Essentials. Access control lists An access control list (ACL) is a list of security protections that applies to an object. An object can be a file, process, event, or anything else that has a security descriptor. For more information on ACLs see Access Control Lists (ACLs). Data protection API The data protection API (DPAPI) provides the following four functions that you use to encrypt and decrypt sensitive data: CryptProtectData, CryptUnprotectData, CryptProtectMemory, and CryptUnprotectMemory. Stored user names and passwords Storage functionality that makes handling users' passwords and other credentials, such as private keys, easier, more consistent, and safer. For more information on this functionality, see CredUIPromptForCredentials. These technologies are not available on all operating systems. Therefore, the extent to which security can be improved depends on which operating systems are involved. Here are the technologies that are available in each operating system. Operating system Windows Server 2003 and Windows XP Technology CryptoAPI Access control lists Data protection API Stored user names and passwords Windows 2000 CryptoAPI Access control lists CryptProtectData CryptUnprotectData The following threat-mitigation techniques use one or more of the four technologies. Techniques that require the use of technologies that are not included in the operating system cannot be used. Getting Passwords from the User When you allow the user to set up a password, force the use of strong passwords. For example, require that passwords be a minimum length such as eight characters or more. Passwords should also be required to include uppercase and lowercase letters, numbers, and other keyboard characters such as the dollar sign ($), exclamation point (!), or greater than (>). After you get a password, use it quickly (using as little code as possible), and then erase all vestiges of the password. This minimizes the time available to an intruder to "trap" the password. The trade-off with this technique is the frequency with which the password must be retrieved from the user; however, the principle should be employed wherever possible. For information about how to properly get passwords, see Asking the User for Credentials. Avoid providing "remember my password" user interface options. Often, users will demand to have this option. If you must provide it, then at minimum, ensure that the password gets saved in a secure fashion. For information, see the Storing Passwords section, later in this topic. Limit password entry tries. After a certain number of tries without success, lock out the user for a certain length of time. Optionally, lengthen the response time for each try over a maximum. This technique is aimed at defeating a guessing attack. Storing Passwords Never store passwords in plaintext (unencrypted). Encrypting passwords significantly increases their security. For information about storing encrypted passwords, see CryptProtectData. For information about encrypting passwords in memory, see CryptProtectMemory. Store passwords in as few places as possible. The more places a password is stored, the greater the chance that an intruder might find it. Never store passwords in a webpage or in a web-based file. Storing passwords in a webpage or in a web-based file allows them to be easily compromised. After you have encrypted a password and stored it, use secure ACLs to limit access to the file. Alternatively, you can store passwords and encryption keys on removable devices. Storing passwords and encryption keys on a removable media, such as a smart card, helps create a more secure system. After a password is retrieved for a given session, the card can be removed, thereby removing the possibility that an intruder can gain access to it. How to Optimize Your MSDN Library Search Article • 01/07/2021 • 2 minutes to read To search MSDN, enter a keyword or character string in the Search MSDN with Bing box. After you search the Microsoft Developer Network (MSDN) website, you can narrow your search results by clicking the options available in the Refine search column under By Source or By Topic. These options become available after your first search attempt. To return only topics in the Windows Development section of MSDN Library 1. In the By Topic list, click Win32 & COM. An additional list called Current Refinements appears. The Current Refinements line has Win32 & COM in it. 2. In the By Source list, click Documentation & Articles. The Current Refinements list now includes Documentation & Articles. As you search, additional filters may become available, for example, Windows Security, Windows Graphics and Multimedia, or Windows Messaging and Collaboration. To search only topics in the Security SDK In the By Topic list, click Windows Security. The Current Refinements list now includes Windows Security. When you type a search string, suggestions automatically appear below the search box. To search for SDK content, look for api or windows in the suggestions. When you click a topic in the search results, you can quickly determine whether the topic provides SDK content by viewing the navigation path that appears at the top of the topic. For example, a search for cryptography generates suggestions that include cryptography api. Clicking the suggestion cryptography api, generates a search results pane that includes Cryptography Functions (Windows). Clicking Cryptography Functions (Windows), brings you to a topic that contains the following navigation path across the top of the topic: MSDN > MSDN Library > Windows Development > Security > Cryptography > Cryptography Reference > Cryptography Functions > All Security SDK content contains this portion of that navigation path: MSDN > MSDN Library > Windows Development > Security > To remove search results filters from your MSDN search In the Current Refinements list, click the (x) that follows the search filter you want to remove. For example, to remove Documentation & Articles from Current Refinements, click the (x) that follows Documentation & Articles. You can also click Remove All to remove all filters from your MSDN search. Suggested Keywords Here are some common keywords to use when you search Security SDK content: digital signature software encryption api encryption security software fingerprint reader software malicious attack microsoft genuine test security descriptor smart card api win32 logonuser windows digital signature windows password filter dll