CISSP-117 · Lesson 7 of 12 · 27 min

Application vulnerabilities and their mitigations

A security manager does not need to know how to exploit a vulnerability, but does need to recognize the main classes of weakness, understand why they occur, and know which controls prevent, detect and correct them. That knowledge lets a manager judge whether a development program covers the risks that matter, read a penetration test report intelligently, set priorities and challenge a vendor's claims. This lesson surveys the vulnerability classes named in the CISSP outline and in the industry's main rankings. Every description stays at the level of cause and defense.

Rankings: the OWASP Top 10 and the CWE Top 25

Two public rankings are widely used to focus attention. The OWASP Top 10 is an awareness document listing the most critical web application security risk categories, compiled from contributed data and a community survey. Its eighth edition, the OWASP Top 10 2025, was released in late 2025. The Common Weakness Enumeration (CWE), maintained by MITRE with funding from CISA, is a detailed catalog of software and hardware weakness types, and its annual CWE Top 25 Most Dangerous Software Weaknesses ranks weaknesses by how often they appear in published vulnerabilities and how severe those vulnerabilities are.

The OWASP Top 10 2025 (as listed by OWASP in late 2025) with the defenses covered in this course.
RankOWASP Top 10 2025 categoryMain defenses
A01Broken Access ControlDeny by default; server-side, object-level authorization on every request
A02Security MisconfigurationHardened baselines, infrastructure as code, configuration scanning
A03Software Supply Chain FailuresComponent inventory and SBOMs, provenance, controlled sources (Lesson 10)
A04Cryptographic FailuresApproved libraries, authenticated encryption, key management (Lesson 6)
A05InjectionParameterized queries, output encoding, safe APIs (Lesson 5)
A06Insecure DesignThreat modeling, secure design patterns, design review (Lesson 2)
A07Authentication FailuresCentral identity, MFA, rate limiting, secure session handling (Lesson 6)
A08Software or Data Integrity FailuresSigned updates and artifacts, safe deserialization, pipeline integrity
A09Security Logging and Alerting FailuresDefined security events, protected logs, monitored alerts
A10Mishandling of Exceptional ConditionsFail closed, consistent error handling, resource limits

Compared with the 2021 edition, the 2025 list keeps broken access control at the top, moves security misconfiguration up to second place, expands the old 'vulnerable and outdated components' category into the broader Software Supply Chain Failures, folds server-side request forgery into broken access control, and adds Mishandling of Exceptional Conditions. In the 2025 CWE Top 25, published in December 2025, the first three entries were cross-site scripting (CWE-79), SQL injection (CWE-89) and cross-site request forgery (CWE-352), followed by missing authorization (CWE-862) and out-of-bounds write (CWE-787). The rankings measure different things, so their orders differ, but the same small set of weakness families dominates both.

A grid of eight vulnerability classes, each in a box with a short cause and defense. Injection: data treated as code; parameterize and encode. Cross-site scripting: untrusted data in pages; context-aware encoding and CSP. Cross-site request forgery: browser sends unwanted requests; SameSite cookies and tokens. Server-side request forgery: server fetches attacker-chosen addresses; allow lists and network egress controls. Broken access control: missing object checks; deny by default and per-request authorization. Insecure deserialization: untrusted objects rebuilt; data-only formats and allow lists. Memory safety errors: out-of-bounds access and use after free; memory-safe languages and compiler protections. Race conditions: check and use separated in time; atomic operations and locking.
Eight common vulnerability classes, each with its root cause and main defense.

Broken access control

Access control failures occur when users can act outside their intended permissions: viewing another merchant's transactions, calling an administrative function, or changing a record they should only read. The most common form is the insecure direct object reference (IDOR), in which an application uses an identifier supplied by the client, such as an account number in a URL, without checking that the caller is entitled to that object. Automated scanners find these poorly because they do not understand the business rules about who should see what. Defenses are design and coding disciplines: deny by default, enforce authorization on the server for every request and every object, derive the user's identity and tenant from the authenticated session rather than from request parameters, centralize authorization logic in a reviewed component, and write tests that try to access other users' objects.

Every request checks both the role's permission and that the object belongs to the caller's merchant; other merchants' refunds look the same as missing ones.
# Object-level authorization: deny by default, derive tenant from the session (defensive pattern)
REFUNDS = {
    'R-1001': {'merchant': 'M00012345', 'amount': '125.50'},
    'R-1002': {'merchant': 'M00098765', 'amount': '40.00'},
}
ROLE_PERMS = {'merchant_admin': {'refund:read', 'refund:create'}, 'merchant_viewer': {'refund:read'}}
def get_refund(session, refund_id):
    if 'refund:read' not in ROLE_PERMS.get(session['role'], set()):
        return 403, 'forbidden: role lacks permission'
    refund = REFUNDS.get(refund_id)
    if refund is None or refund['merchant'] != session['merchant']:
        return 404, 'not found'          # same answer whether missing or belonging to someone else
    return 200, refund
session = {'user': 'ana', 'role': 'merchant_viewer', 'merchant': 'M00012345'}
for rid in ['R-1001', 'R-1002', 'R-9999']:
    print(rid, '->', *get_refund(session, rid))
print('unknown role ->', *get_refund({'user': 'x', 'role': 'guest', 'merchant': 'M00012345'}, 'R-1001'))
Output
R-1001 -> 200 {'merchant': 'M00012345', 'amount': '125.50'}
R-1002 -> 404 not found
R-9999 -> 404 not found
unknown role -> 403 forbidden: role lacks permission

Injection and cross-site scripting

Injection, covered in Lesson 5, arises whenever untrusted data reaches an interpreter as part of a command or query: SQL, NoSQL, operating system commands, LDAP queries, XPath, template engines or expression languages. Cross-site scripting is injection into the browser. In stored XSS, untrusted content saved by the application is later displayed to other users; in reflected XSS, content from a request is echoed straight back in the response; in DOM-based XSS, the page's own script writes untrusted data into the page. The consequences range from stealing session data to performing actions as the victim. The defenses are parameterized interfaces, context-aware output encoding through frameworks that encode by default, a Content Security Policy, and HttpOnly cookies to limit what injected script can reach.

Cross-site and server-side request forgery

Cross-site request forgery, covered in Lesson 6, abuses the trust an application places in a user's browser. Server-side request forgery (SSRF) abuses the trust the network places in the application's own server. When an application fetches a resource from a URL supplied by a user, for example to import a file or display a link preview, an attacker may supply an address that points inside the organization's network, such as an internal administration service or a cloud metadata endpoint that hands out credentials. Because the request comes from a trusted server, network defenses may let it through. SSRF played a central role in the 2019 Capital One breach, in which a misconfigured web application firewall was used to obtain cloud credentials. Defenses include avoiding user-supplied URLs where possible, allow-listing permitted destinations, resolving and checking the destination address before connecting, blocking private and link-local address ranges, enforcing egress controls at the network layer, and requiring session tokens for cloud metadata services.

An allow list of hosts plus a check that the resolved address is not in private, loopback or link-local ranges (IPv6 ranges omitted for brevity); network egress rules should enforce the same policy independently.
import ipaddress
from urllib.parse import urlsplit
# Defensive check before an outbound fetch requested by a user (illustrative)
ALLOWED_HOSTS = {'files.partner-bank.example', 'cdn.ridgeline.example'}
BLOCKED = [ipaddress.ip_network(n) for n in
           ('10.0.0.0/8', '172.16.0.0/12', '192.168.0.0/16', '127.0.0.0/8', '169.254.0.0/16')]
def check_destination(url, resolved_ip):
    parts = urlsplit(url)
    if parts.scheme != 'https':
        return 'reject: scheme'
    if parts.hostname not in ALLOWED_HOSTS:
        return 'reject: host not on allow list'
    ip = ipaddress.ip_address(resolved_ip)
    if any(ip in net for net in BLOCKED):
        return 'reject: resolves to internal address'
    return 'allow'
tests = [
    ('https://files.partner-bank.example/stmt.csv', '198.51.100.20'),
    ('http://files.partner-bank.example/stmt.csv', '198.51.100.20'),
    ('https://intranet.ridgeline.example/admin', '10.0.4.7'),
    ('https://cdn.ridgeline.example/logo.png', '169.254.169.254'),
]
for url, ip in tests:
    print(f'{url:46s} {ip:16s} {check_destination(url, ip)}')
Output
https://files.partner-bank.example/stmt.csv    198.51.100.20    allow
http://files.partner-bank.example/stmt.csv     198.51.100.20    reject: scheme
https://intranet.ridgeline.example/admin       10.0.4.7         reject: host not on allow list
https://cdn.ridgeline.example/logo.png         169.254.169.254  reject: resolves to internal address

Insecure deserialization and integrity failures

Serialization converts objects into a format that can be stored or transmitted; deserialization rebuilds them. Some serialization formats, such as Python's pickle and Java's native serialization, can reconstruct arbitrary object types and run code during the process. If an application deserializes such data from an untrusted source, the sender can control what the application executes. The defenses are to accept only simple data formats, such as JSON, from untrusted sources and validate them against a schema; where rich formats are unavoidable, to restrict deserialization to an allow list of classes and to sign the data so tampering is detected. The broader OWASP category of software and data integrity failures also includes applications that download updates or plug-ins without verifying signatures, and pipelines that accept unverified artifacts, both addressed in Lesson 4.

Memory safety errors

Programs written in languages such as C and C++ manage memory directly, and mistakes such as writing past the end of a buffer (buffer overflow, CWE-787), reading out of bounds (CWE-125) or using memory after it has been freed (CWE-416) can let attackers crash the program or take control of it. Microsoft and Google have each reported that roughly 70 % of the serious security vulnerabilities in large C and C++ code bases they studied were memory safety issues. Mitigations exist at several layers. Compilers and operating systems add stack canaries, address space layout randomization (ASLR), non-executable memory and control-flow integrity, which make exploitation harder but do not remove the bugs. Safer coding practices, bounds-checked library functions and fuzz testing reduce them. The lasting fix is to write new code in memory-safe languages, such as Rust, Go, Java, C#, Python or Swift, and to plan migration of the riskiest existing components.

Government agencies have made this a policy priority. In June 2025 the US National Security Agency and CISA published a joint cybersecurity information sheet on memory-safe languages, following earlier guidance from 2022 and 2023, and CISA has urged software makers to publish memory safety roadmaps. For a manager, the practical questions are which products contain large amounts of memory-unsafe code, whether new components are being written in memory-safe languages, and what the plan is for the components that face untrusted input.

Race conditions and other logic weaknesses

A race condition occurs when the outcome depends on the timing of events that the program does not control. The classic security example is time-of-check to time-of-use (TOCTOU): a program checks a condition, such as a balance or a file permission, and then acts on it, but the condition changes in between. In a payments system, two simultaneous refund requests might each pass a check that the refund does not exceed the remaining amount, together refunding more than the original payment. Defenses include performing check and update as one atomic operation, using database transactions with appropriate isolation and locking, and idempotency keys that ensure repeated requests are processed once. Lesson 8 shows an example with database transactions.

Other weaknesses named in the CISSP body of knowledge include backdoors and trapdoors (undocumented ways around normal security, sometimes left by developers for maintenance), logic bombs (malicious code that triggers on a condition such as a date or an employee's departure), and covert channels, through which information leaks via timing or storage side effects. Controls are mostly governance: code review with independent reviewers, separation of duties, monitoring of privileged developers, change control, and removal of debug features before release. Business logic flaws, such as allowing a negative quantity to produce a credit, are found mainly through abuse cases, design review and specific tests.

Worked problem

Prioritizing findings from an external assessment

A penetration test of Ridgeline's merchant dashboard reports five findings: an insecure direct object reference exposing other merchants' refunds; a stored XSS in a support ticket field; verbose error messages revealing framework versions; a missing HttpOnly flag on a preference cookie; and an outdated library with no known exploitable path in Ridgeline's use.

Show solution
  1. Rank by impact and exposure: the IDOR exposes other customers' financial data to any authenticated merchant; fix it first, check logs for past misuse and consider whether privacy notification duties apply.
  2. The stored XSS can affect support staff with elevated privileges; fix it next and confirm the framework's automatic encoding is not being bypassed elsewhere.
  3. Verbose errors and the cookie flag are lower risk but cheap to fix; schedule them in the next sprint.
  4. For the outdated library, confirm the analysis that the vulnerable code is unreachable, record it, and upgrade on the normal schedule.
  5. Ask why the IDOR was missed: add authorization tests for every endpoint and a rule in the coding standard.

Answer: Fix the access control flaw immediately and investigate its past use, then the XSS; schedule the minor issues; and close the process gap that let the IDOR through.

Common mistakes

  • MistakeRelying on automated scanners to find access control flaws.

    InsteadUse design review, centralized authorization and tests that attempt cross-user access.

  • MistakeTaking the user or tenant identifier from request parameters.

    InsteadDerive identity and tenant from the authenticated session.

  • MistakeLetting servers fetch any URL a user supplies.

    InsteadAllow-list destinations, block internal address ranges and enforce egress controls.

  • MistakeDeserializing native objects from untrusted sources.

    InsteadAccept simple data formats with schema validation, or restrict classes and verify signatures.

  • MistakeTreating compiler protections as a cure for memory safety bugs.

    InsteadUse them as mitigations while moving new and high-risk code to memory-safe languages.

  • MistakeChecking a balance and then updating it in separate steps.

    InsteadMake check and update atomic with transactions, locking or idempotency keys.

Summary and key terms

  • The OWASP Top 10 2025 is led by broken access control, security misconfiguration and software supply chain failures; the 2025 CWE Top 25 is led by XSS, SQL injection and CSRF.
  • Broken access control, including IDOR, is prevented by deny-by-default, server-side, object-level authorization tied to the session.
  • Injection and XSS are prevented by parameterized interfaces, context-aware encoding and a Content Security Policy.
  • SSRF is prevented by avoiding user-supplied URLs, allow lists, address checks and network egress controls.
  • Insecure deserialization is avoided by using data-only formats or class allow lists with signatures.
  • Memory safety errors are best addressed by memory-safe languages, with compiler and OS protections as mitigations.
  • Race conditions need atomic operations; backdoors and logic bombs are controlled by review, separation of duties and change control.
OWASP Top 10
An awareness ranking of the most critical web application security risk categories.
CWE
Common Weakness Enumeration, MITRE's catalog of software and hardware weakness types.
Insecure direct object reference
Access to an object through a client-supplied identifier without an authorization check.
Server-side request forgery
Causing a server to send requests to destinations chosen by an attacker, often internal ones.
Insecure deserialization
Rebuilding objects from untrusted data in a way that lets the sender control behavior.
Buffer overflow
Writing data beyond the bounds of allocated memory.
TOCTOU
Time-of-check to time-of-use, a race condition in which a checked condition changes before use.
Logic bomb
Malicious code that executes when a specified condition occurs.

Practice problems

Work each problem on paper first, then reveal the answer to check.

  1. Which category leads the OWASP Top 10 2025?

    Show answer

    Broken access control.

  2. Which three weaknesses led the 2025 CWE Top 25?

    Show answer

    Cross-site scripting, SQL injection and cross-site request forgery.

  3. What is an IDOR?

    Show answer

    Access to an object via a client-supplied identifier without checking authorization.

  4. Why are scanners weak at finding access control flaws?

    Show answer

    They do not know the business rules about who may access which objects.

  5. Name the three main types of XSS.

    Show answer

    Stored, reflected and DOM-based.

  6. Give two defenses against SSRF.

    Show answer

    Destination allow lists, blocking internal address ranges, egress controls, protected metadata services.

  7. Why is native object deserialization from untrusted sources dangerous?

    Show answer

    It can reconstruct arbitrary objects and run code chosen by the sender.

  8. What is the lasting fix for memory safety errors?

    Show answer

    Using memory-safe languages for new and high-risk code.

  9. How can a TOCTOU race in refunds be prevented?

    Show answer

    Make the check and update atomic, using transactions, locking or idempotency keys.

  10. Which controls address backdoors left by developers?

    Show answer

    Independent code review, separation of duties, change control and removing debug features.

Lesson quiz · 5 questions

Score 60% or more to complete this lesson.

Take the quiz