Tuesday, November 10, 2009

Empirical overview of security vulnerabilities [1/4]

The objective of this four-part article is to provide an overview of security issues identified through the Cockpit. Unlike other surveys which are based on theoretical approaches more or less exhaustive, approach is here empirical: problems mentioned are those we detect through our automated analyses on our customer projects (static analysis on Java or C# code). These problems are those that seem most interesting to inject as a new booster shot for developers who would still not be sensitive to this security dimension.

Preamble

Results are not reassuring, many security rules, even basic, are often ignored in development. Even less reassuring when you know that these applications are sometimes part of the critical sectors: banking, insurance, health ... This may be probably explained by several factors:

  • developers show often motivations related to innovation, technical challenges, addition of new features, whereas security prefers paranoid-like behavior, requires mature technologies / architectures, and becomes fragile as soon as you introduce new elements
  • an obvious lack of training. We all presume that security is a prerequisite known by all developers, but only few training schools or companies really educate (future) developers about security concerns
  • security-oriented tests are rarely performed during acceptance phases, which are often limited to check functional and architectural behaviors. And when black box tests are implemented (e.g. with software testing exploration using HTTP access), they do not detect all issues detected by white box tests. And they sometimes arrive too late to allow a fixing campaign on code.

Any quality problem inside code is a potential security issue!

We present here various security issues poorly addressed in developments, but everyone must also understand the following assertion: any quality problem inside code is a potential security issue. Some basic detections such as self-assignments ( someVar = someVar; ), inverted conditions ( if (someValue.someMethod () & & (someValue! = null)) ), infinite recursive calls, creation of unnecessary instances inside iterations, lack of verification of method result, etc.. are likely to create security issues:

  • unexpected behavior (validation of erroneous form data, wrong permissions added to users, confidential data displayed, ...)
  • application crash (lack of memory, execution stack full, ...)

This article describes some quality rules having a direct impact on security. We start first part with the use of encryption algorithms.

Encryption algorithms

The choice of an encryption algorithm is crucial. Firstly because it is often difficult to change algorithm once it has been used in the application (for example, if you used to save your passwords with a MD5 checksum and want to move to SHA, you will not be able to check existing passwords as they will no longer be comparable).

And on the other hand because it is obviously necessary to select a robust algorithm. To avoid implementing some custom algorithms with suspicious reliability, projects often resort to standard algorithms whose specifications are public: MD5, AES, RSA, ... But two problems arise:

  • these algorithms have not an endless lifetime! The evolution of computing power and the constant search for security holes make obsolete some algorithms yesterday considered as unbreakable. Developers must keep informed of the news. However broken algorithms such as DES (symmetric algorithm) or MD5 (fingerprint algorithm) are still numerous in code. Even if they are not always dangerous in the short-term (like MD5), you have to anticipate they could persist for several years in the project.
  • these algorithms must be configured: key size, passwords, salt, padding, ... Again, some knowledge is needed to use these algorithms in a secure way. For example, storing passwords with a fingerprint algorithm (MD5, SHA ...) without using salt to prevent from Rainbow-table attacks is a nonsense.

Recommendations :

  • Use algorithms up to date. For example: SHA for fingerprints, AES for symmetric encryption or RSA for asymmetric encryption.
  • Use keys with sufficient sizes. For example 128 for AES or 2048 for RSA. See Wikipedia: Key size.
  • Take care of configuring the algorithms properly:
    • systematically add salt inside fingerprints for confidential data (obviously not for identification data such as file checksums). For example: md5("a fixed and original value" + somePassword)
    • use padding options, and good ones. For example, the OAEP padding with RSA (Java: Cipher.getInstance( "RSA/ECB/OAEPPADDING), C#: RSA.Encrypt(dataToEncrypt, true))
  • Hide passwords and salts. Except when they may be requested interactively when starting application, they must necessarily be stored somewhere, so use the least accessible way: drowning in code (code obfuscation, dynamic generation, dispersal, .. .), encryption in external files (which requires then to store other passwords ...), ....

To be continued... In the next part, we will discuss issues related to concurrency and object encapsulation.

0 comments:

Post a Comment