← Back to all reports

Unauthenticated Database Injection Reads Every Customer Across All Sibling Insurance Brands

Reported May 19, 2026
Severity Critical
Platform Web
Vulnerability Class SQL Injection (CWE-89)
Target Type Australian General Insurer
Impact Read any row of any of over 500 production tables, full account takeover of any quote

The Risk

Any anonymous visitor on the internet could run database queries directly against the insurer's production system by sending one type of request. From a single entry point on one sibling brand, the same trick read live customer data belonging to every other sibling brand out of the shared database. The over 500 production tables on the same database account included claims records, policy records, and the customer email log. The same flaw also handed back the verification details needed to fully take over any customer's in-progress quote: only the quote number was required to extract the customer's date of birth and postcode, which are the two pieces of information the customer-facing resume form asks for.

The Vulnerability

The retrieve-quote service accepted a JSON request with a "customer" field. The application concatenated that field directly into a database query string with no parameterisation. The database engine then evaluated whatever the attacker supplied as an expression.

The endpoint required no authentication. Its own published API specification declared "security: []". A protection layer in front of the site blocked classic injection patterns on the query string with a 403, but the JSON POST and PUT bodies slipped entirely past it.

The same root cause was reachable from every sibling-brand secure domain and wrote into the same shared production table on the same database account.

The Attack

Mint a researcher quote

An anonymous bearer was minted from the no-auth token endpoint. A researcher-owned quote was created to use as a known target.

Extract a resume token via injection

An injection in the "customer" field caused the database to return the 36-character resume token associated with the researcher's quote. The token field exceeded the customer column width, so it was extracted in two chunks. The extracted token matched the one returned at quote-creation time, byte for byte, proving the injection read from the real production table rather than from anything in the request.

Replay the stolen token

The extracted token was replayed to the retrieve endpoint as the only input. The server returned the customer's date of birth and postcode with no further verification. Those two values are exactly what the customer-facing resume form asks the customer to enter to resume their quote. The attacker now holds both, plus the downstream access to driver, vehicle, policy, contact, and payment data behind it.

Enumerate the broader database

Walking the system catalog confirmed over 500 production tables on the same database account, including the claims master, policy header and detail, and the customer email log. Every column of every row in any of those tables was readable via the same primitive, at two unauthenticated HTTP calls per row.

Cross-brand confirmation

From a second sibling brand's domain (a tab with no cookies bound to the first brand), the same injection minted a quote tagged for the first brand and then read the resulting token back out of the shared production table. The token matched. A single injection on any sibling-brand domain reads every other brand's customer data through the same shared table.

The Impact

  • Arbitrary read on over 500 production tables of the insurer's core system, with no authentication.
  • Full account-takeover-equivalent on any in-flight customer quote: extract the resume token, replay it, receive the customer's date of birth and postcode, then enter the customer-facing resume flow as the customer.
  • Cross-brand reach. One entry point on any sibling brand reads every other brand's data through the shared table.
  • Victim selection scales via the previously submitted quote-number enumeration oracle, which produces real in-flight quote numbers at 50 to 80 percent per-prefix hit density.
  • The database credential used by the application service should be treated as compromised pending forensic review of the query history since the service went live.
  • Regulatory exposure under the Australian Privacy Act and the notifiable data breaches scheme.

Remediation

  • Parameterise every database query in the retrieve-quote service. The "customer" field, and every other user-controlled value, must be bound as a parameter, not concatenated into the query string.
  • Require authentication on the retrieve-quote endpoints, and remove the "security: []" declaration from the published API specification.
  • Apply least-privilege on the database account used by the service. There is no reason it should hold read on hundreds of unrelated production tables.
  • Audit and rotate the database credential. Review query history for unexpected reads since the service went live.
  • Do not rely on the front-of-site protection layer as the primary defence. The POST and PUT body slipped past it cleanly.
  • Fix the related quote-retrieval verification skip and the quote-number enumeration oracle as part of the same remediation effort. The three findings chain together end-to-end.