If you’re writing your own applications, there are a number of best-practices you should follow to ensure that your code is secure. In this video, you’ll learn about some of the most common secure coding techniques and how to implement them into your development process.
When you’re writing an application, you don’t always have the luxury of time to be able to integrate all of the security checks that you would like to have in that application. That’s why the testing phase of this application is so important. We rely on QA, or quality assurance, to be able to test all aspects of the application, not only to make sure that the application works properly, but to also make sure that the application is secure. Eventually, someone will find the vulnerability that exists inside of your application, so it’s useful to maintain a set of secure coding concepts to minimize the chance of that happening.
What happens when an error occurs inside of your application? Does a message appear on the screen? Does the application simply disappear? You need to understand exactly what the end user will see, and what the results will be when an error occurs. You should think of every possible problem that might occur with a particular application. If there’s a server failure, a database problem, or the network disappears, then you need to know how to handle that particular instance.
If you don’t handle these exceptions properly when you’re writing your software, the bad guys could find a vulnerability with this and take advantage of it in your system. One good best practice when you’re working through these exceptions and these error messages is to not use the built-in messages with the application that you’re using. Those default messages can give away information about how the application was created or the platform that it’s running on. So you should write your own error messages to avoid giving away more information than necessary.
Most applications require that you provide it with some type of input. This input should always be validated and checked against what is expected for that particular input field, whether it’s something on a form, maybe it’s somebody typing at a command line, everything has to be evaluated to make sure that your application only receives information that it’s expecting. For example, your application may be accepting zip codes that are in a different country. So you know that the zip code should only be a certain number of characters long, and it should always have a letter in a certain column. And if there are any problems with this input, your application should attempt to fix the problem or ask the user to input that data again.
A fuzzer is a security tool that will randomly send information into the input of an application. So if you aren’t doing any type of validation check, a simple fuzzing will be able to determine if your application is properly validating this information or not. Many of the applications that we use rely on SQL-based databases to be able to store this information and retrieve it using the application.
A very simple type of SQL code would be this one, where you’re selecting all data from a particular part of the database, where this variable is equal to a particular value. That line of SQL is relatively simple compared to the extremely long and complex SQL queries that can be made inside of an application. If a user or someone maliciously is able to modify those SQL requests, then they may gain access to information in the database that they should not have access to. To combat this problem, many developers will implement stored procedures. A stored procedure will take this very long and involved SQL request and store that request on the database server itself.
So instead of making a very complex call to the database, you simply use a single call command with the name of the stored procedure. That way, nobody’s able to either see or manipulate the call as it’s being made to the data. This means that if you wanted to make an application that was as secure as possible with these SQL queries, every query to the database would be a stored procedure. There would be no SQL calls going across the network and no opportunity for bad guys to make any changes to your SQL code.
In many application roll-outs, we’re deploying a new application, and the users are executing that application on their desktop. But this brings up a number of security questions. Has the application been modified in any way since it was deployed? And can we confirm that a particular application really was written by the developer that we were expecting? We can answer both of these questions by using code signing. Code signing takes advantage of asymmetric encryption to be able to digitally sign the executable. This means that when the executable is run on the desktop, the end user can see that nothing in the application has changed, and it knows exactly who the publisher was of that application.
Organizations that are doing their own application development have a very tight reign over the security associated with the development process. They don’t want anyone to gain access to the source code of the application. That’s because if someone is able to read through the source code, they could potentially find a vulnerability or security problem with that application. That’s why a number of development platforms will use encryption to store the data, and all of the communication over the network will be over an encrypted channel.
If your application is then querying a database or sending information over the network, that information should also be encrypted. That way, all of your users can use the application and know that all of the data over the network is protected. And of course, if we’re storing the source code or the user data, we want to make sure that everything is encrypted on disk. This data at rest should either be encrypted as part of the application, or encrypted as part of the operating system where the data resides.
Obfuscation means that we’re taking something that’s perfectly understandable, and we’re turning it into a form that makes it very difficult to understand. We see this often with source code. We can take source code and scripts that are easy to follow, and we turn them into something that makes it very difficult to follow the logic within a particular script. This not only hides the logic of the way the script or the source code operates, but it also hides any potential security holes and makes it very difficult for someone to understand exactly how an application is functioning. Let’s see how you could obfuscate some very simple code into something that’s very difficult to understand.
This is a very simple PHP script. This echoes the words hello world to the screen. We can run this through a data obfuscation application, and it would create something like this. This performs exactly the same function as the single line, hello world, here at the top, but it performs exactly the same output. For example, if we put this into a PHP interpreter, it would run through the script, and at the bottom write out, hello world. You can see the data obfuscation makes it extremely difficult to follow this application, and it’s hiding a lot of the underlying code from the end user.
A lot of application developers will reuse code from one application to another. If there’s a common process that occurs in both of these applications, it makes sense to simply copy the code to the other application, instead of writing it from scratch. Of course, if the original code has security issues associated with it, by copying the code you’re simply spreading those security problems to another application.
Another challenge with code reuse is the symptom of dead code. With dead code, your application is running an executable, making some calculations, and coming up with the results of that calculation. But nowhere in your code are you ever using the results of that calculation. You’ve effectively gone through the process of performing the calculation, and you’re not using that information anywhere else in the application, thereby making it dead code. We know that introducing any code into an application has the potential to create security problems. So by removing this dead code, you are then effectively making a more secure application.
When data needs to be validated in your application, there’s different places where you can perform this validation. One of these places is on the server. And with server-side validation, all of your checks of the data are occurring on the server itself. This means that if the bad guys are not using the front end that you would normally use for your application, you’re still going to check and maintain the validation once that data arrives at the server.
The application front end that your users have is another good place to perform validation. This is on the client, so we call this client-side validation. This may provide a way for you to filter out a legitimate user from someone who is not legitimate, and it may speed up the validation process since all of the checks are taking place on the user’s local computer. We know that we always want to have some validation occur on the server side, but if we had the opportunity, it would be best if we were able to validate on the server side and the client side.
All of the data in your application, and the application itself, all executes in the memory of your computer. So as a developer, you have to keep close tabs on how the memory is being used by your application. Manipulating memory is a good way to gain access to parts of an application or an operating system that normally you would not have access to. So you never want to trust the users input. You always want to check and validate exactly what’s being input into your application to make sure that nobody’s trying to manipulate any aspect of that memory.
A good example of a vulnerability associated with memory would be a buffer overflow. This is when someone is able to overflow a particular section of memory, so as you’re building your application, you want to be sure that the data that’s going into memory is matching the amount of buffer that you have available for that data. It’s always a good idea to use best practices when you’re designing code to make sure that everything is as secure as possible. Even some of the built-in functions within a particular programming language may not be as secure as they could be. So always be sure to double check the security and the memory management of your application.
If you’ve ever written in an application programming language, then you know that the programming language itself does a large amount of what you need to have done to create that application. But there are times when the application programming language doesn’t provide you with everything you might need. In those cases, you might use a third-party library or software developers kit to be able to enhance or add on capabilities to that programming language.
For example, you may want your application to show a graphical gauge on the screen, and be able to show a value on that gauge. But you may not want to write the code that’s required to display that. Instead, you might want to use a third-party library that automatically has the gauge function, you simply pass the value to the third-party library and it will display the graphical gauge on the screen without you having to write any of that code.
These libraries are used all the time, because they’re able to speed up the programming process. But it’s a third-party library, it’s not code that you’ve written. So there is the potential for a security risk because someone else has written this code. It might be a secure library or the library may not be secure. So it’s best if you’re able to provide as much testing as you can to verify the security of that third-party library. This is an ongoing balancing act for application developers that would like to get their code written quickly but also want to maintain the security of the code base.
The applications that we use every day deal with all kinds of sensitive data. It may be our bank account information, health care information, or anything else that we may not want someone else to be able to see. If you’re developing an application, you have to think about how this sensitive data may be exposed. Is there any encryption of the data when you’re storing the data? Is the data traversing the network without any type of encryption? And is information being displayed to the screen that other people may be able to see? This is why all of the input processes and all of the output processes for your application are important. You have to think every step along the way about any type of data exposure that might occur.