Managed Code


Use the review questions in this section to analyze your entire managed source code base. The review questions apply regardless of the type of assembly. This section helps you identify common managed code vulnerabilities. For more information about the issues raised in this section and for code samples that illustrate vulnerabilities, see Chapter 7, "Building Secure Assemblies."

If your managed code uses explicit code access security features, see" Code Access Security" later in this chapter for additional review points. The following review questions help you to identify managed code vulnerabilities:

  • Is your class design secure?

  • Do you create threads?

  • Do you use serialization?

  • Do you use reflection?

  • Do you handle exceptions?

  • Do you use cryptography?

  • Do you store secrets?

  • Do you use delegates?

Is Your Class Design Secure?

An assembly is only as secure as the classes and other types it contains. The following questions help you to review the security of your class designs:

  • Do you limit type and member visibility?

    Review any type or member marked as public and check that it is an intended part of the public interface of your assembly.

  • Are non-base classes sealed?

    If you do not intend a class to be derived from, use the sealed keyword to prevent your code from being misused by potentially malicious subclasses.

    For public base classes, you can use code access security inheritance demands to limit the code that can inherit from the class. This is a good defense in depth measure.

  • Do you use properties to expose fields?

    Check that your classes do not directly expose fields. Use properties to expose non-private fields. This allows you to validate input values and apply additional security checks.

  • Do you use read-only properties?

    Verify that you have made effective use of read-only properties. If a field is not designed to be set, implement a read-only property by providing a get accessor only.

  • Do you use virtual internal methods ?

    These methods can be overridden from other assemblies that have access to your class. Use declarative checks or remove the virtual keyword if it is not a requirement.

  • Do you implement IDisposable?

    If so, check that you call the Dispose method when you are finished with the object instance to ensure that all resources are freed.

Do You Create Threads?

Multithreaded code is prone to subtle timing- related bugs or race conditions that can result in security vulnerabilities. To locate multithreaded code, search source code for the text "Thread" to identify where new Thread objects are created, as shown in the following code fragment:

 Thread t = new Thread(new ThreadStart(someObject.SomeThreadStartMethod)); 

The following review questions help you to identify potential threading vulnerabilities:

  • Does your code cache the results of a security check?

    Your code is particularly vulnerable to race conditions if it caches the results of a security check, for example in a static or global variable, and then uses the flag to make subsequent security decisions.

  • Does your code impersonate?

    Is the thread that creates a new thread currently impersonating? The new thread always assumes the process-level security context and not the security context of the existing thread.

  • Does your code contain static class constructors?

    Check static class constructors to check that they are not vulnerable if two or more threads access them simultaneously . If necessary, synchronize the threads to prevent this condition.

  • Do you synchronize Dispose methods?

    If an object's Dispose method is not synchronized, it is possible for two threads to execute Dispose on the same object. This can present security issues, particularly if the cleanup code releases unmanaged resource handlers such as file, process, or thread handles.

Do You Use Serialization?

Classes that support serialization are either marked with the SerializableAttribute or derive from ISerializable . To locate classes that support serialization, perform a text search for the "Serializable" string. Then, review your code for the following issues:

  • Does the class contain sensitive data?

    If so, check that the code prevents sensitive data from being serialized by marking the sensitive data with the [ NonSerialized ] attribute by or implementing ISerializable and then controlling which fields are serialized.

    If your classes need to serialize sensitive data, review how that data is protected. Consider encrypting the data first.

  • Does the class implement ISerializable?

    If so, does your class support only full trust callers , for example because it is installed in a strong named assembly that does not include AllowPartiallyTrustedCallersAttribute ? If your class supports partial-trust callers, check that the GetObjectData method implementation authorizes the calling code by using an appropriate permission demand. A good technique is to use a StrongNameIdentityPermission demand to restrict which assemblies can serialize your object.

  • Does your class validate data streams?

    If your code includes a method that receives a serialized data stream, check that every field is validated as it is read from the data stream.

Do You Use Reflection?

To help locate code that uses reflection, search for "System.Reflection" ” this is the namespace that contains the reflection types. If you do use reflection, review the following questions to help identify potential vulnerabilities:

  • Do you dynamically load assemblies?

    If your code loads assemblies to create object instances and invoke types, does it obtain the assembly or type name from input data? If so, check that the code is protected with a permission demand to ensure all calling code is authorized. For example, use a StrongNameIdentity permission demand or demand full trust.

  • Do you create code dynamically at runtime?

    If your assemblies dynamically generate code to perform operations for a caller, check that the caller is in no way able to influence the code that is generated. For example, does your code generation rely on caller-supplied input parameters? This should be avoided, or if it is absolutely necessary, make sure that the input is validated and that it cannot be used to adversely affect code generation.

  • Do you use reflection on other types?

    If so, check that only trusted code can call you. Use code access security permission demands to authorize calling code.

Do You Handle Exceptions?

Secure exception handling is required for robust code, to ensure that sufficient exception details are logged to aid problem diagnosis and to help prevent internal system details being revealed to the client. Review the following questions to help identify potential exception handling vulnerabilities:

  • Do you fail early?

    Check that your code fails early to avoid unnecessary processing that consumes resources. If your code does fail, check that the resulting error does not allow a user to bypass security checks to run privileged code.

  • How do you handle exceptions?

    Avoid revealing system or application details to the caller. For example, do not return a call stack to the end user. Wrap resource access or operations that could generate exceptions with try/catch blocks. Only handle the exceptions you know how to handle and avoid wrapping specific exceptions with generic wrappers.

  • Do you log exception details?

    Check that exception details are logged at the source of the exception to assist problem diagnosis.

  • Do you use exception filters?

    If so, be aware that the code in a filter higher in the call stack can run before code in a finally block. Check that you do not rely on state changes in the finally block, because the state change will not occur before the exception filter executes.

    For an example of an exception filter vulnerability, see "Exception Management" in Chapter 7, "Building Secure Assemblies."

Do You Use Cryptography?

If so, check that your code does not implement its own cryptographic routines. Instead, code should use the System.Security.Cryptography namespace or use Win32 encryption such as Data Protection Application Programming Interface (DPAPI). Review the following questions to help identify potential cryptography related vulnerabilities:

  • Do you use symmetric encryption?

    If so, check that you use Rijndael (now referred to as Advanced Encryption Standard [AES]) or Triple Data Encryption Standard (3DES) when encrypted data needs to be persisted for long periods of time. Use the weaker (but quicker) RC2 and DES algorithms only to encrypt data that has a short lifespan, such as session data.

  • Do you use the largest key sizes possible?

    Use the largest key size possible for the algorithm you are using. Larger key sizes make attacks against the key much more difficult, but can degrade performance.

  • Do you use hashing?

    If so, check that you use MD5 and SHA1 when you need a principal to prove it knows a secret that it shares with you. For example, challenge-response authentication systems use a hash to prove that the client knows a password without having the client pass the password to the server. Use HMACSHA1 with Message Authentication Codes (MAC), which require you and the client to share a key. This can provide integrity checking and a degree of authentication.

  • Do you generate random numbers for cryptographic purposes?

    If so, check that your code uses the System.Security.Cryptography.RNGCryptoServiceProvider class to generate random numbers, and not the Random class. The Random class does not generate truly random numbers that are not repeatable or predictable.

Do You Store Secrets?

If your assembly stores secrets, review the design to check that it is absolutely necessary to store the secret. If you have to store a secret, review the following questions to do so as securely as possible:

  • Do you store secrets in memory?

    Do not store secrets in plaintext in memory for prolonged periods. Retrieve the secret from a store, decrypt it, use it, and then substitute zeros in the space where the secret is stored.

  • Do you store plaintext passwords or SQL connection strings in Web.config or Machine.config?

    Do not do this. Use aspnet_setreg.exe to store encrypted credentials in the registry on the <identity> , <processModel> , and <sessionState> elements. For information on obtaining and using Aspnet_setreg.exe, see Microsoft Knowledge Base article 329290, "How To: Use the ASP.NET Utility to Encrypt Credentials and Session State."

  • How do you encrypt secrets?

    Check that the code uses DPAPI to encrypt connection strings and credentials. Do not store secrets in the Local Security Authority (LSA), as the account used to access the LSA requires extended privileges. For information on using DPAPI, see "How To: Create a DPAPI Library" in the "How To" section of "Microsoft patterns & practices Volume I, Building Secure ASP.NET Applications: Authentication, Authorization, and Secure Communication " at http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnnetsec/html/SecNetHT07.asp .

  • Do you store secrets in the registry?

    If so, check that they are first encrypted and then secured with a restricted ACL if they are stored in HKEY_LOCAL_MACHINE . An ACL is not required if the code uses HKEY_CURRENT_USER because this is automatically restricted to processes running under the associated user account.

  • Are you concerned about reverse engineering?

    If so, consider an obfuscation tool. For more information, see the list of obfuscator tools listed at http://www.gotdotnet.com/team/csharp/tools/default.aspx .

    Note  

    Do not rely on an obfuscation tool to hide secret data. Obfuscation tools make identifying secret data more difficult but do not solve the problem.

Do You Use Delegates?

Any code can associate a method with a delegate. This includes potentially malicious code running at a lower trust level than your code.

  • Do you accept delegates from untrusted sources?

    If so, check that you restrict the code access permissions available to the delegate methods by using security permissions with SecurityAction.PermitOnly .

  • Do you use assert before calling a delegate?

    Avoid this because you do not know what the delegate code is going to do in advance of calling it.




Improving Web Application Security. Threats and Countermeasures
Improving Web Application Security: Threats and Countermeasures
ISBN: 0735618429
EAN: 2147483647
Year: 2003
Pages: 613

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net