In my previous post, I addressed four coding policies that almost guarantee a data breach. This post will cover five solution strategies to shore up your application’s security.
The guiding principle to correct these flawed policies (see Part 1) is to change the priorities that direct development and support of software applications. Vulnerabilities in code must be given a higher value, similar to bugs, and tracked with the same awareness and attention. Also, security controls should be considered in the earliest stages of the development life-cycle so that they can be implemented at the lowest cost and reduction of time. In addition, the value of a company’s reputation needs to be factored when, not if, the software is compromised and adversely affects customer experience and thus the bottom line. These changes represent a major shift for a development team but can be introduced as five distinct solutions as time and training allows:
Solution I: Write custom validation logic for each data type in the application. This can be accomplished with static lists of expected values, numeric and date range tests, regular expressions, and custom classes that wrap the validation with the storage and retrieval methods of the class. The developer should use these interfaces exclusively in all application code to centralize the validation and safe output of data.
Solution II: Select a framework or library that provides reliable data sanitization. Some languages are bundled with cybersecurity libraries, but these are not automatically used and must be referenced by the code: PHP (e.g. htmlspecialchars), .NET (e.g. ValidationRule), and Java (Validator interface). Other 3rd party solutions, such as the ESAPI library from the OWASP Foundation, can work in many scenarios to provide field tested and reliable data validation functions. If your time and budget allows, instrumentation can also be added to legacy code using an IAST or RASP tool which automatically detects unsafe data usage.
Solution III: Remove all uses of dynamic SQL and injection-vulnerable functions. Any code that dynamically assembles SQL statements from user input will be vulnerable to SQL injection. So, this code pattern must be rooted out and converted to safe alternatives (parameterized queries, converting data to non-string types, dereferencing with static arrays, etc.). Sometimes this code is easy to spot, but clever code can hide how it constructs these statements. So an automated static code scanner will be useful to identify vulnerable code and if integrated into the SDLC, will detect code changes that might have re-introduced a vulnerability. An advanced solution, for the truly paranoid, is to replace the standard database library with a custom one that allows safe methods to be used but throws exceptions and deprecation warnings for the rest. This is known as a “shim” which can identify vulnerable code early in the development lifecycle without the use of a scanner, to save valuable time.
Solution IV: Include cybersecurity controls in each phase of the development process. Before code is written, the requirements should include the security needs of the data such as encryption, expected ranges, and types. Ideally, this starts by referencing a company’s data classification policy and standard data model to define validation schemas or other necessary controls. For example, if an application stores an age data element, it might define this as being limited from 0 to 150. When this is coded, the developer would reference this requirement and code validation logic to convert input string to a number then check that it is from 0 through 150. If the validation fails, the input is not accepted and the code follows a different specified course. This is a simple example, but validations like these can be enough to block a potential hacker from misusing the application. As companies increase their use of rapid development with Agile or DevOps, integrating security controls into all phases of development is more imperative since they will have even less time to make remediations.
Solution V: Define a role-based cybersecurity skill set for all personnel. This includes project managers, architects, developers, database administrators, systems engineers, and even non-technical staff. The selected training curriculum or certifications will be unique to each role in the organization and based on the technology that it uses. This can range from annual security awareness training to certifications in the secure use of technologies that the company leverages. An example of this kind of policy is the DoDD 8140 (www.dodd8140.com) which lists required certifications for all federal government computer support personnel.
In conclusion, many websites remain vulnerable to hackers due to outdated policies and dependence on external controls. The ultimate solution to remediate application vulnerabilities is to fix the code itself. Remediation can also be viewed as part of holistic code management that bakes-in security controls into the entire life-cycle. Applying one or more of these solutions will lower cybersecurity risk to a company and yield safer applications that are hardened against attacks. Going forward, this change of priorities will allow developers to make the needed code improvements that protect the data, customers, and the company’s reputation by delivering a secure finished product.