Wednesday, February 5, 2014

Secure Delphi Programming Series

Working in the IT security industry it is extremely important for us to keep up with all the standards relating to the development of a secure product. In fact, it's so important for us, that we get every version of our product and all product files independently verified by a third party security analysis firm that rigorously test every aspect of product security. Unfortunately independent verification by a good firm can be very expensive and might not make financial sense for all developers. However, you can do your product and your customers some good by making sure you keep security in mind and applying some simple security principles while developing your applications.

Therefore, I thought I would start a small series of posts around the topic of secure delphi programming. Touching on issues around how to produce Delphi applications using industry standard security practices and principles.

  • Secure Delphi Programming: Part 2 - Protecting Secrets
  • Secure Delphi Programming: Part 3 - Secure Communication

Although this series is currently still in progress, feel free to suggest other areas of secure programming that you might like me to cover in this series below.

Thursday, January 2, 2014

Secure Delphi Programming: Part 1 - Binary Security

One area of particular importance surrounding secure programming is the security of all product binary files. In my opinion this as one of the most important areas of product security because possible exploits, through weaknesses in your binary files, can not only be used to compromise your software, but can also be used to compromise your customers workstations and/or servers that your products are running on. This is also important if you are looking at trying to sell your product into enterprise, where binary security is heavily scrutinised.

You might not be aware at just how many responsibilities there are for a developer to ensure that the executables developed are indeed secure from the possibility of exploitation on a customers machine, and what might surprise you is that most modern binary security features for Windows that Microsoft introduced are opt-in, meaning that you don't just automatically inherit them when you compile your projects to a newer SDK. So below is a brief overview of a number of important areas of security that can be easily leveraged for your binaries:


Safe Structured Exception Handlers (SafeSEH)
Under Microsoft compilers, SafeSEH is a compiler option that enforces known targets for exception handlers. This option helps prevent many types of stack buffer overflow exploits. Unfortunately Delphi doesn't yet have an option to enable SafeSEH but keep an eye out for when (or if) this does get addressed here http://qc.embarcadero.com/wc/qcmain.aspx?d=106781. However, note that the SafeSEH option is only required for 32 bit executables and not for 64 bit ones, as 64 bit executables already address this.


Data Execution Prevention (DEP / NX)
Data Execution Prevention helps prevent regions of memory identified as containing non executable data from being executed. This helps protect against some program errors, and certain malicious exploits such as storing executable instructions in data areas via a buffer overflow. This feature was included in Delphi from Delphi 2007 onwards.

For more information on how to implement it in your projects, have a read of Brian Long's write up here: http://blog.blong.com/2013/12/catching-up-on-happenings-in-delphi.html#DEPandASLR.


Address Space Layout Randomization (ASLR)
Address Space Layout Randomization is a security technique that helps protect against buffer overflow attacks and memory corruption vulnerabilities. This is accomplished by the randomisation of base addressees of the process, its heaps, its thread stacks and its modules in a process's address space.

Please refer to the he above mentioned write up by Brian Long for how to also implement ASLR.


Avoid VirtualAlloc
This is interestingly something you won't find mentioned in any of the Microsoft documentation but the use of the VirtualAlloc API is now considered bad security practice. This is because the memory addresses used for allocations do not consider ASLR. This means this could lead to an ASLR bypass condition, which could allow for exploitation of a memory corruption vulnerability.

An interesting article with a more in-depth explanation can be found here: http://recxltd.blogspot.com.au/2011/12/curious-case-of-virtualalloc-aslr-and.html.


Encode function pointers
If an object instance's memory space were to become corrupted, for example through a buffer overflow, then an attacker may be able to overwrite memory containing function pointers and subsequently may be able to execute arbitrary code. To limit the affects of such an exploit, pointers to functions can be encrypted and decrypted at runtime using the EncodePointer and DecodePointer APIs. These functions obfuscate the target address using a pre-process token, such that a blind overwrite of the pointer will result in an unpredictable, garbled address. 

I would recommend that you review your code and that the EncodePointer API be utilised wherever possible and suitable.


Avoid Banned SDL APIs
Microsoft maintains a list of APIs that is considered insecure and ensuring they are not used is a good way to significantly reduce a number of potential code vulnerabilities. In most cases there are secure counterparts that can be called instead.

The Security Development Lifecycle banned function call list can be found here: http://msdn.microsoft.com/en-us/library/bb288454.aspx.


Digital Code Signing
Code signing all your binary files (including EXE, CPL, DLL, OCX and SYS files) with a digital signature is the best way to assure recipients that the binary files indeed come from your organisation and that the files have not been altered or corrupted at any stage during delivery or during the course of its usage. Digital code signing certificates can be easily purchased from a trusted source such as Symantic Authenticiation Services (formally Verisign) found here http://www.symantec.com/en/au/verisign/code-signing/microsoft-authenticode.


Forced Integrity
While its important to ensure that all binary files are code signed, it is also important to ensure that the signatures on each binary are verified before they are loaded. This is a feature that Microsoft introduced from Windows Vista onward, and can be accomplished by enabling the Force Integrity flag for each binary file. This can be simply added along with the DEP and ASLR flags as follows:


 { DllCharacteristics constant definitions }  
 const  
  IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE    = $0040; // DLL can move.  
  IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY = $0080; // Code Integrity Image  
  IMAGE_DLLCHARACTERISTICS_NX_COMPAT       = $0100; // Image is NX compatible  
   
 { set the PE Optional Header flags to enable ASLR, Code Integrity Check  
   and DEP(NX) }  
 {$IFDEF RELEASE}  
  {$SetPEOptFlags IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE or  
                  IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY or  
                  IMAGE_DLLCHARACTERISTICS_NX_COMPAT}  
 {$ENDIF}  

As you may notice I have encapsulated the flags inside a conditional define such that it only get compiled on release versions. This is because each compile of the binary must be digitally signed for the executable to even execute, making simple debugging through the IDE problematic otherwise.

Some more in-depth information about the process of forced integrity signing can be found here: https://social.technet.microsoft.com/wiki/contents/articles/255.forced-integrity-signing-of-portable-executable-pe-files.aspx.

IMPORTANT NOTE: The Force Integrity flag does not work in versions of Delphi older than Delphi XE 5 Update 2 as there was a bug preventing its correct operation that was only recently fixed (QC Report http://qc.embarcadero.com/wc/qcmain.aspx?d=72147)

If anyone has any other suggestions for securing your Delphi binary files, feel free to comment below.