Developers are the foundation of an organization’s digital strategy, building the products and services that drive revenue and help their company to operate more efficiently. Unwittingly, they also sit on the frontlines of application security, even though most never intended to be security professionals. Most developers, after all, want to build applications and be innovators. However, in today’s environment, the applications they build can be the weak point that enables a threat actor’s attack. By practicing secure coding, development teams can create practices that drive better security across the organization.
What is secure coding and why is it important?
Secure coding practices include the knowledge, policies, and procedures that developers use to design, write, test and review software to prevent security vulnerabilities that malicious actors can use as attack vectors. As part of secure development practices, developers need to learn how to write code that is devoid of defects, bugs, and logic flaws that may pose a security risk.
The Secure Software Development Lifecycle (S-SDLC) relies on DevOps teams to incorporate software security directly into every stage of the application development lifecycle, making secure coding practices critical.
What are secure coding practices?
The Open Web Application Security Project (OWASP) is a non-profit collaboration that works with the developer community to establish best practices around secure coding practices. In 2018, OWASP published its Top Ten Proactive Controls list. The first proactive control is to define security requirements. To provide the necessary guidance, OWASP then released its Application Security Verification Standard (ASVS) that established functional and non-functional security controls to use during the design, development, and testing phases.
Here is a synopsis of the critical things to consider when developing secure applications.
To prevent attackers from moving laterally, developers need to make sure that they build authentication controls into their applications beyond enabling multi-factor authentication (MFA). As part of this, they need to consider:
- Low-privilege operating system accounts
- Communications between application components
- Authentication mechanism’s security, ability to use strong authentication, and logging capabilities
- Consistent authentication security controls across all pathways
Beyond authentication, application developers need to make sure that users can limit access to the applications according to the principle of least privilege. Additionally, access within the applications should also consider how to enforce the principle of least privilege access. Some things to consider include:
- Ability to enforce controls at the access point, not on the client
- Ensuring access control is flexibility enough for the application’s needs
- Enforcing principle of least privilege across all resources to protect against spoofing and elevation of privilege attack methodologies
- Using a single, well-vetted access control mechanism
- Applying attribute or feature-based access controls, not just role-based controls
Input and Output Verification
As the trust boundary changes, developers need to build in trust enforcement at all access points, including APIs, serverless, or microservices. As part of building in this security, they need to make sure that:
- Input and output requirements clearly define handling and processing data to ensure regulatory and policy compliance across sensitive data content and type
- Integrity controls, like encryption, mitigate risks associated with data transmission or injection attacks
- Input validation is enforce on a trusted service layer
- Output encoding occurs as close to or by the interpreter as possible
Using encryption precisely secures sensitive data without being wasteful. In an attempt to balance these needs, developers should consider:
- Key management policies and the key lifecycle outlined in NIST SP 800-57
- Protection of key material and other secrets, like with key vaults
- Keys and passwords must be replaceable and integrated into sensitive data encryption processes
- Treating client-side secrets as insecure
Logging and Auditing
Logging and auditing are used to prove compliance with regulations, industry standards, and internal policies. Some best practices include:
- Using a common logging format across the system
- Protecting logs from unauthorized access
Data Protection and Privacy
Increased focus from regulatory agencies and legislatures mean that developers need to make sure that their applications have the right privacy controls built into them. To do this, they should incorporate:
- Ability to identify and classify sensitive data
- Protections that meet compliance requirements for encryption, integrity, retention, and privacy
As threat actors look to intercept data as it communicates between components, developers need to build in protections like:
- Encrypting component communications across different containers, systems, sites, or cloud providers
- Verifying both sides in a communication link, like using TLS certificates and chains
Since malware and ransomware continue to be a primary attack vector, developers need to
- Use a source code control system
- Have procedures to protect check-ins
- Can trace any changes to source code control systems
To protect the information that the applications stores, processes, and transmits, developers need to make sure that they understand and map how data moves through the application and across systems. As part of this process, they need to:
- Define and document all components in terms of their business or security function
- Make sure all high-value business logic flows like authentication, session management, and access control always share in real-time, not unsynchronized
- Keep these high-value business logic flows thread safe to prevent multiple threads from changing data at the same time
Secure File Upload
To protect applications that allow users to upload files, developers need to make sure that they can do this securely to prevent malicious actors from uploading malware or engaging in an injection attack.
Some best practices include:
- User-uploaded files being stored outside of the web root
- Implementing a Content Security Policy (CSP)
- Serving user-uploaded files with either octet stream downloads or an unrelated domain, like cloud file storage bucket
As part of security-by-design, application configurations should be strong enough that administrators and users have to work to weaken the default security posture. To build security-by-default, developers should consider:
- Segregating components that have different trust levels
- Using binary signatures, trusted connections, and verified endpoints to connect with remote devices
- Ensuring that builds incorporate warnings for insecure components and taking remediation steps
- Testing the ability to securely deploy the application during the build process
- Ensure deployments can be isolated at the network level to mitigate attacks that can come from other applications
- Prevent application from using unsupported, insecure, or deprecated client-side technologies
Why do developers struggle to maintain secure coding practices?
Often, developers want to build security into their applications but lack the background knowledge to do it. For example, research published in February 2021 as part of the 43rd International Conference on Software Engineering found that for developers using Python and Java, only 40% know the OWASP standard.
To practice secure coding, developers need the right education. Despite not intending to become security practitioners, the move to cloud-based applications means that securing software requires building it directly into the products.
4 ways to help developers learn secure coding practices
To build a successful secure codings training, organizations need to create a program that meets developers where they are. This means understanding their needs and giving them the resources to be successful.
Find a format that works
All training should be rooted in Learning Science principles, or it will become nothing more than a box to check for compliance purposes. As part of locating the right format, organizations should look for a program that provides:
- Manageable lessons: too much information overwhelms learners so any training should be delivered as “bite-sized chunks”. Developers are also extremely busy, and bite-sized lessons are easier for them to take.
- Conceptual and procedural knowledge: learners need to know both the “what” and the underlying “why” for true proficiency
- Goal-directed practice and targeted feedback: People learn best with hands-on, real-world training that has specific objectives and provides feedback for how to enhance performance
- Connected knowledge structures: content should apply information that builds on previously learned information for better retention
Find a training philosophy that works
Instead of treating defensive security strategies as separate from offensive, use an educational approach that incorporates both for enhanced understanding of how attacks work and how to mitigate risk.
Use contextual learning
People learn better when the education builds on and connects to their personal experience. For secure code training, this means growing knowledge in a way that is relevant to the developers’ daily activities.
Some ways to help create a contextual learning experience include choosing the right:
- Interface: using something they already know, like a development environment
- Programming language: focusing on the languages they know and use in their da-to-day activities
- Real-world examples: providing content directly related to what developers would see in their real lives helps retention
- Adaptive training: providing lessons based on vulnerabilities that are actually discovered in their code
Many people have negative associations with education because it often focuses on taking away points for errors rather than providing positive reinforcement for successes. Secure coding education should be something that developers see as a positive, rather than as a form of punishment
When building out a training program, organizations should consider making it enjoyable to learn by providing positive reinforcement using mechanisms such as:
- Tokens: offering points or tokens that people can use to exchange for something they want
- Social: sharing successes and praising achievements
- Tangible: offering monetary or physical rewards for meeting milestones
Enhancing application security by practicing secure coding
Ensuring that developers have the right education is the key to securing the software development lifecycle. Organizations need to enable their developers. Instead of hoping that they learn best practices on their own, organizations need to offer solutions that give developers the knowledge they need. More importantly, they need to build a secure coding training program that provides the educational experience that truly helps developers learn the necessary skills.
HackEdu’s secure coding training platform is built on a foundation of Learning Science principles so that developers can internalize knowledge and build on what they already know. As application security becomes mission-critical, developers need the education and the supporting tools that help them practice on real-world vulnerabilities in the languages they use. Without that, applications will continue to be a security weakness and a risk factor, instead of the business enabler they should be.