Book Read Free

Sharks in the Moat

Page 25

by Phil Martin


  1) It forces the developer to think things through before laying down code.

  2) It ensures that modules are implemented with high cohesion and loose coupling.

  3) It produces a series of tests that can be quickly run prior to code check-in that will reveal issues in the earliest stages of development.

  4) It allows a team to quickly find the source of pesky bugs, as unit testing points directly to the offending module.

  Overall, a team will be able to generate better code in a shorter timeframe relative to delivering the entire project. It is important to note the ‘relative’ term here, as it will increase development time upfront, but more than make up for it later when fewer bugs are generated and the ones that are found are easier to fix. It requires a good deal of discipline on the developer’s part to properly implement decent unit tests.

  Unit testing also discourages the use of hard-coding values, as unit tests should inject any dependencies directly into the module. While we won’t go into dependency injection in this book, it is a crucial capability that every development team should understand and execute if proper unit testing is to be achieved.

  Another win for unit testing is the ability to allow modules to be developed even if the code on either side of the module has not yet been completed. For example, let’s suppose that we are building the checkout process for an online store. In our design, we have a Cart object that invokes a ShippingRate object, a CurrencyConversion object, a DiscountCode object, and a Tax object. The developer tasked with creating the ShippingRate object is at a clear disadvantage as neither the Cart object is ready which would invoke her class, and neither is the CurrencyConversion object ready, which her code would consume. Fortunately, she has chosen to create a test harness which will play the part of the Cart object so that her own code can be tested – this harness is called a driver. Furthermore, she can mock up what the CurrencyConversion object will eventually look like on her own and call it from her own ShippingRate code – this temporary object is called a stub. She is then able to complete her own class using only the driver and stub as long as the actual Cart and CurrencyConversion classes implement the same interfaces as her driver and stub. Drivers and stubs can also be used when dealing with third-party components that require other dependencies not yet understood.

  Other advantages for unit testing include the following:

  It validates functional logic.

  It makes it easier to discover inefficiencies and complexity that more complex code could hide, as unit testing executes code in smaller modules.

  It can enhance automated testing processes by integrating directly with source control build tools. For example, we can configure our source control and build environment to execute all unit tests for each check-in and refuse to accept the changes if any test fails.

  It encourages collective ownership of the shared code base, as it highlights developer-caused issues early before the product is deployed.

  Software Vulnerabilities and Mitigation Options

  In this book, we are focusing on secure code, not just coding in general. But, when discussing the level of security as implemented within our code, how do we quantify such a thing? After all, we all have our own ideas of the riskiest attacks and which ones our code base is most vulnerable to. This is the point at which we can always falls back on our trusty RASQ – the relative attack surface quotient. Let’s quickly summarize the primary contributors to the attack surface:

  The amount of code and services that are executed by default.

  The volume of code that can be accessed by untrusted users.

  The extent of damage encountered when code is exploited.

  RASQ should be calculated before and after coding activities. Because we have the chance to reduce RASQ by how we implement code, this entire section covers defensive coding practices.

  Almost all technological security breaches are a direct result of software weakness. The leading root causes of such attacks are design flaws, coding issues, and improper configuration and operations. The number one root cause? Software coding weaknesses. This information had been culled from vulnerability databases that collect such information and collate the breach to the underlying root cause. In addition to the name of the vulnerability these databases include how exploitable the weakness is, the potential impact, and how to mitigate the vulnerability. Following is a list of the most commonly used vulnerability databases.

  The National Vulnerability Database, or NVD, is owned by the U.S. government and uses something called the Security Content Automation Protocol, or SCAP. This approach enables the automation for vulnerability management, security measurement and compliance.

  The US Computer Emergency Response Team, or CERT, has a Vulnerability Notes Database that has the primary goal of reducing security risks in software before and after deployment. This is applied by focusing on discovering vulnerabilities before deployment and mitigating vulnerabilities after deployment.

  The Open Source Vulnerability Database is an independent database created by the security community.

  Common Vulnerabilities and Exposures, or CVE, is a free international dictionary of publicly known vulnerabilities and exposures.

  The OWASP Top 10 List not only lists the most common issues but views them from an organizational risk perspective. Figure 75 shows the top weaknesses discovered in 2017.

  Risk

  Description

  A1 – Injection

  Injection flaws, such as SQL, NoSQL, OS, and LDAP injection, occur when untrusted data is sent to an interpreter as part of a command or query. The attacker’s hostile data can trick the interpreter into executing unintended commands or accessing data without proper authorization.

  A2 – Broken Authentication and Session Management

  Application functions related to authentication and session management are often implemented incorrectly, allowing attackers to compromise passwords, keys, or session tokens, or to exploit other implementation flaws to assume other users’ identities temporarily or permanently.

  A3 – Cross-Site Scripting (XSS)

  Many web applications and APIs do not properly protect sensitive data, such as financial, healthcare, and PII. Attackers may steal or modify such weakly protected data to conduct credit card fraud, identity theft, or other crimes. Sensitive data may be compromised without extra protection, such as encryption at rest or in transit, and requires special precautions when exchanged with the browser.

  A4 – Insecure Direct Object References

  Many older or poorly configured XML processors evaluate external entity references within XML documents. External entities can be used to disclose internal files using the file URI handler, internal file shares, internal port scanning, remote code execution, and denial of service attacks.

  A5 – Security Misconfiguration

  Restrictions on what authenticated users are allowed to do are often not properly enforced. Attackers can exploit these flaws to access unauthorized functionality and/or data, such as access other users' accounts, view sensitive files, modify other users’ data, change access rights, etc.

  A6 – Sensitive Data Exposure

  Security misconfiguration is the most commonly seen issue. This is commonly a result of insecure default configurations, incomplete or ad hoc configurations, open cloud storage, misconfigured HTTP headers, and verbose error messages containing sensitive information. Not only must all operating systems, frameworks, libraries, and applications be securely configured, but they must be patched and upgraded in a timely fashion.

  A7 – Missing Function Level Access Control

  XSS flaws occur whenever an application includes untrusted data in a new web page without proper validation or escaping or updates an existing web page with user-supplied data using a browser API that can create HTML or JavaScript. XSS allows attackers to execute scripts in the victim’s browser which can hijack user sessions, deface web sites, or redirect the user to malicious sites.

>   A8 – Cross-Site Request Forgery (CSRF)

  Insecure deserialization often leads to remote code execution. Even if deserialization flaws do not result in remote code execution, they can be used to perform attacks, including replay attacks, injection attacks, and privilege escalation attacks.

  A9 – Using Components with Known Vulnerabilities

  Components, such as libraries, frameworks, and other software modules, run with the same privileges as the application. If a vulnerable component is exploited, such an attack can facilitate serious data loss or server takeover. Applications and APIs using components with known vulnerabilities may undermine application defenses and enable various attacks and impacts.

  A10 – Unvalidated Redirects and Forwards

  Insufficient logging and monitoring, coupled with missing or ineffective integration with incident response, allows attackers to further attack systems, maintain persistence, pivot to more systems, and tamper, extract, or destroy data. Most breach studies show time to detect a breach is over 200 days, typically detected by external parties rather than internal processes or monitoring.

  Figure 75: The OWASP Top 10

  The Common Weakness Enumeration, or CWE, is an international list of vulnerabilities providing a common language for describing architectural, design and coding weaknesses. The CWE/SANS Top 25 most dangerous programming errors are shown in Figure 76.

  Rank

  ID

  Name

  1

  CWE-89

  Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')

  2

  CWE-78

  Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')

  3

  CWE-120

  Buffer Copy without Checking Size of Input ('Classic Buffer Overflow')

  4

  CWE-79

  Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')

  5

  CWE-306

  Missing Authentication for Critical Function

  6

  CWE-862

  Missing Authorization

  7

  CWE-798

  Use of Hard-coded Credentials

  8

  CWE-311

  Missing Encryption of Sensitive Data

  9

  CWE-434

  Unrestricted Upload of File with Dangerous Type

  10

  CWE-807

  Reliance on Untrusted Inputs in a Security Decision

  11

  CWE-250

  Execution with Unnecessary Privileges

  12

  CWE-352

  Cross-Site Request Forgery (CSRF)

  13

  CWE-22

  Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')

  14

  CWE-494

  Download of Code Without Integrity Check

  15

  CWE-863

  Incorrect Authorization

  16

  CWE-829

  Inclusion of Functionality from Untrusted Control Sphere

  17

  CWE-732

  Incorrect Permission Assignment for Critical Resource

  18

  CWE-676

  Use of Potentially Dangerous Function

  19

  CWE-327

  Use of a Broken or Risky Cryptographic Algorithm

  20

  CWE-131

  Incorrect Calculation of Buffer Size

  21

  CWE-307

  Improper Restriction of Excessive Authentication Attempts

  22

  CWE-601

  URL Redirection to Untrusted Site ('Open Redirect')

  23

  CWE-134

  Uncontrolled Format String

  24

  CWE-190

  Integer Overflow or Wraparound

  25

  CWE-759

  Use of a One-Way Hash without a Salt

  Figure 76: The CWE/SANS Top 25 Most Dangerous Programming Errors

  The Top 25 programming errors can be grouped into three different categories:

  Insecure interaction between components, represented by 6 errors on the top 25 list and shown in Figure 77. These weaknesses are related to insecure ways in which data is sent and received between separate components, modules, programs, processes, threads, or systems.

  Risky resource management, represented by 11 errors on the top 25 list, shown in Figure 78. The weaknesses in this category are related to ways in which software does not properly manage the creation, usage, transfer, or destruction of important system resources.

  Porous defenses, represented by 8 errors on the top 25 list, shown in Figure 79. The weaknesses in this category are related to defensive techniques that are often misused, abused, or just plain ignored.

  1

  CWE-89

  Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')

  2

  CWE-78

  Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')

  4

  CWE-79

  Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')

  9

  CWE-434

  Unrestricted Upload of File with Dangerous Types

  12

  CWE-352

  Cross-Site Request Forgery (CSRF)

  22

  CWE-601

  URL Redirection to Untrusted Site ('Open Redirect')

  Figure 77: CWE Top 25 - Insecure interaction between components

  Rank

  ID

  Name

  5

  CWE-306

  Missing Authentication for Critical Function

  6

  CWE-862

  Missing Authorization

  7

  CWE-798

  Use of Hard-coded Credentials

  8

  CWE-311

  Missing Encryption of Sensitive Data

  10

  CWE-807

  Reliance on Untrusted Inputs in a Security Decision

  11

  CWE-250

  Execution with Unnecessary Privileges

  15

  CWE-863

  Incorrect Authorization

  17

  CWE-732

  Incorrect Permission Assignment for Critical Resource

  19

  CWE-327

  Use of a Broken or Risky Cryptographic Algorithm

  21

  CWE-307

  Improper Restriction of Excessive Authentication Attempts

  25

  CWE-759

  Use of a One-Way Hash without a Salt

  Figure 78: CWE Top 25 - Risky resource management

  Rank

  ID

  Name

  3

  CWE-120

  Buffer Copy without Checking Size of Input ('Classic Buffer Overflow')

  13

  CWE-22

  Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')

  14

  CWE-494

  Download of Code Without Integrity Check

  16

  CWE-829

  Inclusion of Functionality from Untrusted Control Sphere

  18

  CWE-676

  Use of Potentially Dangerous Function

  20

  CWE-131

  Incorrect Calculation of Buffer Size

  23

  CWE-134

  Uncontrolled Format String

  24

  CWE-190

  Integer Overflow or Wraparound

  Figure 79:CWE Top 25 - Porous defenses

  Now it’s time to address the most common vulnerabilities head-on. While we could approach them using the CWE categories, it is a little easier to categorize them from the end-user’s point of view into
four groups – client, network, system and server code, as shown in Figure 80. Note that the following discussions do not represent a comprehensive list of all possible weaknesses, but rather the most important ones that the development team can directly impact through coding.

  Another note – any developer should read the Testing role as well, as it discusses some additional steps on preventing various attacks such as injection by performing input validation.

  Client Vulnerabilities

  Client vulnerabilities are found directly within the application an end-user interacts with. For all practical purposes with modern applications, this will be represented by a browser. But it should be simple to envision each vulnerability as implemented in a native mobile or desktop app as well.

  International Issues

  When software must be written to support more than one language, culture or geographical region, it opens a whole different world that seems strange to someone who has never had to deal with such a thing before. Challenges can be grouped into two categories – legal and technological.

  Figure 80: The Four Categories of Development Vulnerabilities

  Legal requirements must be addressed to prevent the application from violating regulations. For example, full-time in France often means a 30-hour work week, while in the US it is a 40-hour week. The software must be able to accommodate both if it is designed to work in both locations.

 

‹ Prev