The successful development of secure application software begins with a solid understanding of the Application Development Lifecycle and the best practices associated with the development process. To this end, the Business Applications area of the University Computing and Telecommunications department has developed an excellent overview of the application development lifecycle phases that you can download by clicking here.
Building upon the principles highlighted in Application Development Lifecycle document, we have developed the following checklist of specific actions that can be taken throughout the lifecycle to ensure that the application software effectively protects the information the University creates, collects, stores, processes and transmits.
Application security checklist
Making a piece of application software “attack-resistant” requires that all of the following conditions are met, at a minimum:
- The security of each function is built into its design, and is functionally tested in design reviews and “table-top” exercises.
- The program code and all code updates are managed by an effective code management system that ensures only authorized developers can access and maintain the program code stored within it.
- Application developers understand the “best practices” associated with the programming environment used.
- The program code precisely implements the design.
- Each program code component is unit tested before participating in full-function system testing.
- The testing team includes technical and non-technical individuals who will likely attempt to use the system in unplanned ways.
- The program code runs on professionally-managed systems and networks that adhere to system and network management “best practices”.
- All program code movement follows a documented change management process.
- Segregation of duties is enforced as program code is moved from development to QA/test to production environments.
- The application's functions are thoroughly documented in a manner that enables future programmers to gauge the impact of each program change effectively.
1. The security of each function is built into its design
There are ample opportunities for security controls to fail when they were not a part of the application design at the outset. In general, the longer it takes a development team to answer the information security-related questions, the more difficult it is to ensure that the security model is complete. Some (but not all) of the questions that need to be answered for an application early on include:
- What are the functional roles of the individuals who will use the system? Is there only one application administrator role or will administrative functions be distributed to different individuals at different levels? How will end users be grouped, e.g., by job function, by the ability to update vs. only view?
- How will administrators and users be authenticated, e.g., will operating system authentication be leveraged or will a user file of IDs and passwords be maintained? Will something more than a password be required to authenticate?
- If an application-based user file is being maintained, how will user records be maintained? Are the passwords that are stored in the file or database encrypted appropriately? How will the system facilitate password resets and changes?
- In addition to logging administrative activity, how much user-level transaction logging is necessary, e.g., only logons and logoffs, what transactions were performed, what records and data elements were added, updated or deleted?
- Is there any sensitive data that needs to be encrypted on the network? On the server?
2. The program code and all code updates are managed by an effective code management system
Code management systems provide a number of benefits, helping to ensure that:
- The right version of the code is being modified, tested and deployed.
- Multiple individuals are not updating the same program code at the same time that can cause coding conflicts and introduce vulnerabilities and “back doors”.
- Changes are tracked.
- Modifications that are found to be problematic can be backed out.
- The “segregation of duties” principle can be enforced, where developers are authorized to update the code of specific applications, but someone else must move the code to test and production environments.
3. Application developers understand the “best practices” associated with the programming environment used
While there are numerous attack patterns used by malicious hackers to compromise applications, systems and data, the following attacks have been singled out because, while the number of programs that have been exploited by these attacks is significant, the program adjustments required to defend against these attacks are relatively trivial:
- A “Buffer overflow” attack relies on the program allowing the user to enter any number of characters
in an input form field. Unfortunately, the input buffer into which the data is entered
has a maximum size. So if a malicious hacker can reverse engineer the program to
determine where the input buffer is in relation to certain program instructions, he
or she could enter enough data into an input form field to reach the end of the buffer and
then continue to overwrite the legitimate program code that follows the input buffer
with malicious code. Then when the program conditions direct the application to execute
the original program code that followed the buffer, it will execute the malicious program
Preventing buffer overflows involves making sure that all program requests to receive data from a user always have the buffer size limit specified in the command.
- A “SQL-injection” attack relies on an application program not screening the information entered into
a form field for special characters before the data is inserted into an SQL database
query. If no screening occurs, the malicious hacker could populate a form field with
a character string that includes not only a reasonable field data value but also one
or more SQL database commands that could cause the application program to submit those
commands to the database for execution. If this type of attack succeeds, database
data could be altered or erased, or protected database data could be exposed.
Preventing SQL-injection attacks from succeeding requires that programs screen the data entered into each form field for characters that have a special meaning for SQL command processing, such as a semicolon, single quote, double quote and others. If found, the program code must either remove these characters from the input string or escape them by preceding each of them with a backslash (\) before inserting the input string into any SQL command.
- A “Cross-site scripting” attack is similar to SQL-injection in that commands are being inserted into the
data but, unlike SQL injection, this attack uses your server to store malicious script
commands and deliver them to your users’ workstations. If no screening occurs, the
malicious hacker could submit a form with one or more form fields populated with Java
script or other scripting language commands that the application will store in the
database row and column that corresponds to the input form field. When another user
requests for display the database data element that is holding the malicious script
commands, the malicious script commands will be delivered to the user's browser which,
upon receipt, will execute the commands on the user's computer.
Preventing cross-site scripting attacks from succeeding against your application programs involves screening all input data for script-related HTML commands before the data is inserted into any SQL command. Remove any script-related HTML command found.
Programs called “web application scanners” can help you detect these vulnerabilities and more in your web applications. Upon execution, the scanner crawls your website testing each web page encountered for known attack methods, including the above three. The scanner will list each vulnerability that it finds along with recommendations for addressing it.
The Open Web Application Security Project, an organization that focuses on web application security and privacy, has a wealth of information about web application attack methods and ways that you can better protect your application programs against them. Visit their web site at https://www.owasp.org/ .
4. The program code precisely implements the design
It is important that complex applications are not designed as large, complex monoliths but as a collection of functional objects, each of which has a specific role in the process with a limited number of inputs and outputs. As the program objects, functions and subroutines are being written, regular code reviews should be scheduled to confirm that the developed code is consistent with the design specifications.
5. Each program code component is unit tested before participating in full-function system testing
Continuing in the same vein as the previous recommendation, each program object, function and subroutine should be developed so that each can be tested separately to ensure that it consistently produces the desired result. By limiting each “object’s” functions to a manageable set, it makes it fairly easy to confirm that each object is satisfying its intended purpose. This in turn makes the next step, system testing, far more effective, since system testing would primarily need to confirm that everything integrates effectively.
6. The testing team includes both technical and non-technical individuals
It has been proven many times that developers are not always the best testers of the program code that they write. This is primarily due to the fact that subconsciously they tend to test to what they know is in the application. This sometimes results in production implementations failing because the end users, who are just learning the system, enter transactions in ways that were never planned. Catching these types of conditions by having non-technical individuals involved in testing could prevent a masked vulnerability from hitting the production environment.
7. The program code runs on professionally-managed systems and networks that adhere to system and network management “best practices”
An application is only as good as its weakest link, so it is critical that the server and network infrastructure is implemented in compliance with security industry “best practices”. Computer scanning program are available that can check servers and networking equipment for vulnerabilities, report any vulnerabilities that it finds and make recommendations for remediation be run on a regular basis. Running a scanner against servers and network components when they aredeployed and regularly thereafter is highly recommended.
8. All program code movement follows a documented change management process
Assuming that the second recommendation – to use a code management system – is followed, it is important that it is used consistently, every time, as programs are moved from the development environment to QA/test to production. in cases where a production “fix” was applied outside of the change management system, there is a chance that the corrections made could be undone the next time the program is updated.
9. Segregation of duties is enforced as program code is moved from development to QA/test to production environments
Best practices and virtually all privacy legislation require that no application developer should move the software that he or she developed into the production environment. What this means is that the change management system must be set up so that each programmer can only update code in the development environments of the applications for which he or she is responsible, but not in the applications' QA/test or production environments. The reason should be obvious – the segregation of duties institutes roadblocks against someone going “rogue”. In organizations with limited numbers of technical staff, procedures are often set up where the developer for application 1 could be the software mover for application 2 and vice versa.
10. The application’s functions are effectively documented
Finally, a very important component of maintaining attack-resistant systems is to ensure that enough program documentation exists to ensure that any future developer, even those who never saw the application before, can find their way around the application relatively quickly with a complete picture of how the application works. Many application security failures have been attributed to applications that were updated by someone who was not associated with the application before and didn’t realize the full impact of the change he or she made.