4 min read

Security Tests with Static Analysis

Given the increasing threat to the security of IT application systems, software testing is expected to uncover the majority of potential security vulnerabilities. But dynamic testing is not the only way to discover security flaws in the system. Static analysis of the code can be an inexpensive method of uncovering potential security threats. Not all, but some of the potential security flaws can be detected in this way. (Examples used here refer to Java)

Purpose of the static analysis

Static analysis is one of many testing approaches to find defects in a software system. It is a technique for examining the requirements texts, design models and code components associated with a software product without actually executing the product. Design reviews and code inspections are based on the same principle, only they are performed by humans. A static analysis is performed by an automaton that checks for various rules. The goal is to uncover defects in the design of the software before the dynamic test.

Potential security vulnerabilities in the code

There are now many tools available for the static analysis of source code. When selecting a suitable tool, the question arises as to the types of defects that are reported by the tool. Another question is the frequency of false reports, so-called “false positives”. These are reports of defects that are not actually real defects. If tools produce many such reports, this only distracts from the real defects. As far as real defects are concerned, it is important to have a classification scheme. From a code security perspective, there are five main classes of defects: Missing Code, Unauthorized Code, Tamperable Code, Error-prone Code, Non-compliant Code.

Missing code

An example of missing code is the missing check of the input parameters of public methods. The first check is whether the input data has the correct type and whether it is within the valid value range. If not, an exception condition should be triggered.

The same applies to return results. Values returned by called methods in remote classes should be checked before they are used.

Another example of missing code is the absence of the “final” clause in a class definition. The fact that the following class is not declared with “final” allows an intruder to copy and manipulate the code. To prevent this, all subordinate classes should be declared with “final”.

At least one third of the code should consist of security-checking instructions. If this is not the case, it is a sign that the execution of the code is not secure.

Unauthorized code

Built-in constants are an example of unauthorized code. Having such values in the code is not easy to maintain and is dangerous. Hackers who gain access to the byte code can change these values. It is therefore advisable to outsource all constants to external resources. This is especially true for texts.

Other examples of problem areas are casts and nesting.

Manipulable code

One example of manipulable code is built-in SQL statements. They are susceptible to SQL injection attacks, which allow external parties to corrupt the database content. SQL statements therefore have no place in the application code. If they are used at all, then only in a protected access layer.

Further examples of manipulable code can be found in the areas of cloning and deserialization.

Error-prone code

Error-prone code can easily lead to an error under certain circumstances. Typical examples of this type of flaw are the comparison of an object with a string or a recursion without an end condition. In terms of security, a potential security vulnerability exists if the number of parameters in the function call is less than the number of parameters in the called method. In this case, the intruder has the opportunity to append their own data to the parameter list and thus spread viruses in the code.

Non-compliant code

Non-compliant code involves deviations from a given standard. This is not a direct threat to security, but in some cases it could become one. Let’s take the example of when certain standard services are to be avoided because they may be corrupted. If you use them in your code anyway, you run the risk of adopting infected objects.

Case study on the detection of code deficiencies

A study was conducted at North Carolina State University with three million lines of C++ code by Nortel Networks Corporation to show how effective automated static analysis can be. Using the “Flexlint” tool, the experiment uncovered more than 136,000 defects, or one defect for every 22 lines of code, even though the code had been in use for more than three years. The number of defects from the static analysis correlated with the number of error messages from the pre-release test with an accuracy of 83%. This indicates that the errors could have been detected just as well by the static analysis. In contrast to the dynamic test, which cost 12 person-months, the static analysis would only have cost 2 person-months.

Detection of security flaws in Java code

As the study shows, the majority of defects can already be detected in the code before testing takes place. This also applies to security defects, but not to other non-functional defects such as time consumption, data volume and throughput capacity. Tools that support testing can be easily integrated into the development process (e.g. continuous integration). In the age of agile development and the continuous delivery of software, defects must be detected and eliminated quickly and without great effort. Static analysis of the code is the best way to do this.

The following list is an example of the rules implemented in such tools. They originate from the JavAudit tool:

  • Avoid the allocation of non-initialized objects
  • Restrict access to classes and methods
  • Finalize all classes and methods
  • Prohibit the addition of new classes to finished packages
  • Prohibit the nesting of classes
  • Do not allow signature - signing - of the code
  • Pack all code in a single jar
  • Define all classes as uncloneable
  • Define all classes as unserializable
  • Define all classes as undeserializeable
  • Prohibit embedded SQL statements
  • Prohibit casting of data types
  • Check all input arguments
  • Check all return values
  • Put all IO operations in try..catch brackets
  • Place all calls to remote methods in try…catch brackets
  • Compare the type and number of parameters in each interface
  • Avoid the use of hard-coded data values

Conclusion

Experience with static code analysis shows that many security flaws in an IT system are already visible in the code. Static analysis is an inexpensive, fast and reliable way to uncover these security flaws. Developers only need the right tools and the determination to produce clean code.

Analytical Quality Assurance

Checking and measuring software artifacts Analytical quality assurance offers a cost- and resource-saving way of checking software artifacts - such...

Weiterlesen

Unit Testing

For me, the unit test is the most essential of all test stages. It is also the first thing I look at when I start a new consulting project. Why? This...

Weiterlesen

The Fight Against Technical Debt

As part of an agile development team, testers have a special responsibility. Among other things, they must prevent technical debt from getting out of...

Weiterlesen