Understanding threats and the common types of attack helps you to identify appropriate countermeasures and allows you to build more secure and robust assemblies. The main threats are:
Unauthorized access or privilege elevation, or both
Code injection
Information disclosure
Tampering
Figure 7.1 illustrates these top threats.
The risk with unauthorized access, which can lead to privilege elevation, is that an unauthorized user or unauthorized code can call your assembly and execute privileged operations and access restricted resources.
Vulnerabilities that can lead to unauthorized access and privileged elevation include:
Weak or missing role-based authorization
Internal types and type members are inadvertently exposed
Insecure use of code access security assertions and link demands
Non-sealed and unrestricted base classes, which allow any code to derive from them
Common attacks include:
A luring attack where malicious code accesses your assembly through a trusted intermediary assembly to bypass authorization mechanisms
An attack where malicious code bypasses access controls by directly calling classes that do not form part of the assembly's public API
Countermeasures that you can use to prevent unauthorized access and privilege elevation include:
Use role-based authorization to provide access controls on all public classes and class members.
Restrict type and member visibility to limit which code is publicly accessible.
Sandbox privileged code and ensure that calling code is authorized with the appropriate permission demands.
Seal non-base classes or restrict inheritance with code access security.
With code injection, an attacker executes arbitrary code using your assembly's process level security context. The risk is increased if your assembly calls unmanaged code and if your assembly runs under a privileged account.
Vulnerabilities that can lead to code injection include:
Poor input validation, particularly where your assembly calls into unmanaged code
Accepting delegates from partially trusted code
Over-privileged process accounts
Common code injection attacks include:
Buffer overflows
Invoking a delegate from an untrusted source
Countermeasures that you can use to prevent code injection include:
Validate input parameters.
Validate data passed to unmanaged APIs.
Do not accept delegates from untrusted sources.
Use strongly typed delegates and deny permissions before calling the delegate.
To further reduce risk, run assemblies using least privileged accounts.
Assemblies can suffer from information disclosure if they leak sensitive data such as exception details and clear text secrets to legitimate and malicious users alike. It is also easier to reverse engineer an assembly's Microsoft Intermediate Language (MSIL) into source code than it is with binary machine code. This presents a threat to intellectual property.
Vulnerabilities that can lead to information disclosure include:
Weak or no formal exception handling
Hard-coded secrets in code
Common attacks include:
Attempting to cause errors by passing malformed input to the assembly
Using ILDASM on an assembly to steal secrets
Countermeasures that you can use to prevent information disclosure include:
Solid input validation
Structured exception handling and returning generic errors to the client
Not storing secrets in code
Obfuscation tools to foil decompilers and protect intellectual property
The risk with tampering is that your assembly is modified by altering the MSIL instructions in the binary DLL or EXE assembly file.
The primary vulnerability that makes your assembly vulnerable to tampering is the lack of a strong name signature.
Common attacks include:
Direct manipulation of MSIL instructions
Reverse engineering MSIL instructions
To counter the tampering threat, use a strong name to sign the assembly with a private key. When a signed assembly is loaded, the common language runtime detects if the assembly has been modified in any way and will not load the assembly if it has been altered .