Software Integrity

Security topics every software developer should know

Software developers and information security professionals have almost always been two mutually exclusive groups. However, with the increase in security awareness, developers have started integrating security into the development process. To further bridge the gap between development and security, it is essential for developers to have a good understanding of security principles. In this post, we’ll talk about the basic security concepts that every developer should be aware of while building applications.

Topic #1: Input validation

An application obtains data from various trusted and untrusted sources during its workflow. It is important to perform input validation of data obtained from all sources to ensure that only properly formed data gains entry into the application workflow. If not properly validated, malformed input can lead to attacks such as SQL injection and cross-site scripting (XSS). Always conduct input validation on the server—even if client-side validation is also present.

Syntactic and semantic validation

It’s important to validate data both syntactically and semantically. Syntactic validation ensures that the input data has the correct elements such as structure, data type, and length. On the other hand, semantic validation ensures the correctness of data per business logic (e.g., checking for negative price).

Blacklisting and whitelisting

The two primary approaches for performing input validation are blacklisting and whitelisting. Blacklisting involves detecting dangerous characters and patterns in the input (e.g., an apostrophe character or the <script> tag) and filtering them out. Since blacklisting does not account for all attack vectors, it is relatively easy to bypass these checks and controls. Also, the blacklist needs to be updated every time a new attack vector is discovered. This isn’t very manageable. As such, they should not be used for validating data.

Whitelisting involves defining a set of approved characters and patterns. It also involves implementing controls for validating that the input contains characters and patterns only from the defined set. If the input contains any other characters, that input is discarded. This is a stronger approach for input validation and is generally performed using regular expressions.

Topic #2: Output encoding

Just as input is validated before utilization in the application workflow, output should be properly encoded before sending it to the target interpreter. Encoding involves converting special characters executed by the target interpreter into an equivalent telling the interpreter to use it in a harmless way. For example, consider a web application in which the target interpreter is a web browser. When the server sends a response back to the browser, the output sent in response should be HTML encoded. Thus, stopping the browser from executing script tags, and preventing potential XSS attacks.

Topic #3: Database access

Applications need to access the database at some point in the application workflow to retrieve or store information. Developers should ensure that they are accessing the database in a secure way to prevent SQL injection attacks. The best way is to use parameterized queries since they, unlike dynamic SQL queries, can help the database distinguish between application code and data.

Another way to defend from SQL injection attacks is to make use of stored procedures, which are essentially SQL statements defined and stored in the database. However, developers should take care not to include unsafe dynamic SQL queries inside the stored procedure.

Lastly, the principle of least privilege should be adopted and only the minimum required permissions should be assigned to the database. For example, if a user account needs to read data from some tables in the database, it should be given read-only access only to required tables and should be prevented from accessing anything else.

Topic #4: Know your crypto

A basic knowledge of cryptography is essential for all developers. Before implementing crypto in applications, it’s critical to understand how to do so securely. Some common cryptography related best practices include:

Don’t roll your own crypto. Developers should only use cryptographic algorithms that are widely accepted by the cryptography community. It is also better to use extensively tested libraries for implementing crypto in an application.

Apply strong encryption algorithms like AES and avoid using weaker algorithms like DES and RC4.

Implement secure hashing algorithms like SHA-2 and SHA-3 instead of using the insecure algorithms SHA-1 and MD5.

Adopt a strong encryption key with a length of 128 bits or higher. Keys should never be hardcoded into application code. Instead, they should be stored safely and rotated periodically.

For password hashing, use strong password hashing functions like PBKDF2, bcrypt, and scrypt.

Topic #5: Secure error handling

Make sure that the error handling in the application is implemented properly. Improper error handling may lead to two issues:

Information leakage. If error messages containing stack traces or database dumps are revealed to the user, it may provide insight into potential code vulnerabilities. To prevent this, the application should only display generic error pages to the end user.

Application enters an unhandled state. Ensure that the application ‘fails securely’ for both expected and unexpected error conditions and that it handles all exceptions properly.

Topic #6: Third-party libraries

An application is as secure as its weakest link, as they say. Many developers use third-party libraries in their code. They must ensure that these libraries do not have any security vulnerabilities. Some points that developers should keep in mind before using third-party libraries include:

Searching the libraries for open CVE entries.

Checking if these libraries are regularly maintained and have a large user base.

Updating these libraries regularly, when security patches or new versions are released. If the current version in use doesn’t have any open security vulnerabilities, there might not be a need to upgrade. However, if developers wants to upgrade to the latest version, they should remember that the latest version may contain some vulnerabilities that have not yet been discovered. In any case, developers should regularly keep checking the libraries they use for new vulnerabilities on a regular basis.

Topic #7: Defense in depth

Defense in depth is a security principle that suggests adding multiple layers of security to increase the overall security of an application. In case an attacker manages to compromise one security layer, they would need to get through other layers of security before achieving their attack goal. An example of defense in depth for a web application is implementing client-side input validation, layered server-side input validation, and output encoding to protect the application from XSS.

Summing it up

While this is by no means an exhaustive list, these basic security fundamentals are a good starting point to help software developers begin building securing into their applications.

Reel in the knowledge and skills you need to ensure security and quality.