← Blog

What a CSP report would have shown during the Ticketmaster breach

A vendor-hosted chat widget sat on Ticketmaster's payment page. Modified at the vendor, it skimmed cards for four months. The report a policy on that page would have sent, and what it could not see.

Michael Cameron5 min read

Ticketmaster’s payment page loaded a customer-support chat widget from its vendor’s servers. Someone changed the widget at the vendor, and from February to June 2018 it read whatever customers typed into the page, card numbers included. Ticketmaster’s own code was never touched.

A connect-src report is built for this shape, where the compromise is upstream of you and your site is only the delivery route. It is also the shape where what the report cannot see matters most.

What happened

The ICO’s penalty notice records the chronology. On 10 February 2018 an attacker inserted malicious code into a chat bot that Inbenta Technologies hosted and served to Ticketmaster’s customers. Ticketmaster had chosen to include the chat bot on several pages, including the payment page, and because of that the code was able to collect names, card numbers, expiry dates and CVV numbers as they were entered.

The first outside warning came from a bank. On 6 April 2018 around 50 Monzo customers reported fraud on their cards, and on 12 April Monzo met Ticketmaster to share what it had found. The Register reported at the time that 70 percent of the affected cardholders had used Ticketmaster, against less than one percent of Monzo’s customers overall, and that a week after that meeting Ticketmaster’s investigation had found no evidence of a breach. In May a Twitter user posted that Inbenta’s servers were serving two versions of a file, one with an infected line, and at the end of May a customer’s antivirus flagged the Inbenta tag on the Irish site. The script came off every Ticketmaster site on 23 June, and Ticketmaster published a notice on 27 June.

Ticketmaster notified 9.4 million customers across Europe, 1.5 million of them in the UK. The ICO fined it £1.25 million in November 2020 for the part of the breach that fell after the GDPR took effect.

How the skimmer worked

RiskIQ published its analysis two weeks after the disclosure, from its own crawl history of Ticketmaster’s sites. The modified script was served from an Inbenta hostname set up for Ticketmaster. The skimmer hooked every button and form on the page, and when a customer clicked or submitted, it collected each field’s name and value and sent them to a server the attackers ran at webfotce.me, a typo of “webforce”. RiskIQ noted that the group’s drop servers had used domain names mimicking JavaScript libraries and analytics services before this one.

RiskIQ also found that a second supplier, SociaPlus, had been compromised the same way and its scripts modified on subdomains set up for Ticketmaster, which affected sites Ticketmaster’s own statement had not listed.

The ICO’s notice is direct about visibility. Ticketmaster confirmed it had no visibility of changes Inbenta made to the script, and that any change would have been applied automatically without Ticketmaster’s authorisation. It had not implemented subresource integrity, and argued that SRI was unworkable for a script the vendor changed at will. The Commissioner rejected that, and named local hosting, content security policies and iframes as measures that were also available.

The CSP report this would have produced

The widget was allowed. Any policy that let the page load Inbenta’s chat bot had Inbenta’s hostname in script-src, and the modified file came from that hostname, so loading it violated nothing. The report comes from the next step.

{
  "csp-report": {
    "document-uri": "https://www.ticketmaster.co.uk/checkout/payment",
    "violated-directive": "connect-src",
    "effective-directive": "connect-src",
    "original-policy": "default-src 'self'; script-src 'self' https://ticketmasteruk.inbenta.com; connect-src 'self' https://ticketmasteruk.inbenta.com https://api.example-psp.com; report-uri https://k3x9mp2nq7ab.ingest.us.headerhawk.com/r",
    "disposition": "report",
    "blocked-uri": "https://webfotce.me",
    "source-file": "https://ticketmasteruk.inbenta.com/avatar/jsonp/inbenta.js",
    "line-number": 1,
    "status-code": 200
  }
}

The page path and policy are illustrative. A fetch, XMLHttpRequest or sendBeacon call reports under connect-src, and a skimmer that encodes the fields into an image URL reports under img-src, so a payment page worth watching names both. A policy that sets neither still reports the request, because both fall back to default-src, and the effective directive, which HeaderHawk groups on, still reads connect-src or img-src.

Two fields do the work. blocked-uri names webfotce.me, a host nobody at Ticketmaster or Inbenta would recognise. source-file names the Inbenta script, so from the first report the investigation points at the vendor, not at Ticketmaster’s own code.

Where it surfaces

HeaderHawk groups reports by effective directive and blocked host, so the issue reads connect-src blocking webfotce.me, with a report count and first- and last-seen timestamps. Every report would name the payment page as the document it came from. Opening the issue lists the reports with the source file, the browser and operating system, and the policy that was in force.

The ICO’s notice records that Ticketmaster found the mechanism on 23 June by running card details through the payment page and watching the network traffic, and that doing so earlier would likely have found it earlier. A report-only connect-src on that page makes the same observation from every visitor’s browser on every payment, and delivers it to a dashboard.

Alerting is on browser agreement. Reports for an issue accumulate in 15-minute windows, and a window reported by two or more browser families, or carrying 20 or more reports from one, goes to Slack, email or a webhook, then repeats no more often than the rule’s window, which defaults to a day.

Where the report stops

The modified widget loaded without a report. A host allowlist cannot express a vendor’s file changing on the vendor’s server, at a hostname the page allows. The ICO’s answer was subresource integrity. Ticketmaster’s objection, that the vendor changed the file at will, explains why SRI is rare on third-party tags. The report does not settle that argument. It names where the modified file sends data.

A drop server on the allowlist sends nothing. Inbenta’s own hostname was in connect-src for the widget’s normal traffic, and stolen fields routed through it would have satisfied the policy.

And the report follows the request. A policy on the payment page would have shortened the four months between February and June, and changed the order in which a bank, a Twitter user, an antivirus product and the site itself found out.

Sources

Read your own reports this way

Point your policy's reporting at HeaderHawk and see violations grouped by directive, blocked source and page. The Free plan covers 1 site.