How to defend against Account Takeovers
Learn about account takeover threats, protection strategies, and detection methods to secure your digital accounts and prevent unauthorised access.
A Content Security Policy (CSP) is a web security standard that adds a crucial layer of defense against content injection attacks, most notably Cross-Site Scripting (XSS). It is implemented via an HTTP response header (Content-Security-Policy
) sent from the server to the browser.
The header's value specifies the trusted sources from which the browser is allowed to load resources such as scripts, styles, images, fonts, and frames. By creating an "allowlist" of trusted domains, you can prevent the browser from executing malicious scripts injected by an attacker.
XSS attacks occur when an attacker injects malicious scripts into a trusted website. When a victim visits the site, the malicious script executes in their browser, allowing the attacker to steal session cookies, deface the site, or redirect the user to a malicious page.
CSP provides a powerful mitigation by telling the browser: "Only execute scripts from self
(my own domain) and https://apis.google.com
. Ignore all others." This effectively blocks the malicious injected script from running.
Implementing a CSP is a multi-step process. It's crucial to start with a reporting-only policy to avoid breaking your site.
A reporting-only policy allows you to monitor potential CSP violations without actually blocking any content. This is a safe way to discover all the legitimate resources your site uses before you start enforcing the policy.
The header for this is Content-Security-Policy-Report-Only
.
Example: A strict starting point
Content-Security-Policy-Report-Only:
default-src 'none';
script-src 'self';
connect-src 'self';
img-src 'self';
style-src 'self';
report-uri https://your-csp-report-collector.com/report;
Let's break down these directives:
default-src 'none'
: This is the fallback. By default, nothing is allowed. This forces you to explicitly allowlist every type of resource.script-src 'self'
: Allows scripts to be loaded from your own domain.connect-src 'self'
: Allows AJAX requests, WebSockets, etc., to your own domain.img-src 'self'
: Allows images from your own domain.style-src 'self'
: Allows stylesheets from your own domain.report-uri
: This is crucial. The browser will POST a JSON report of any violation of this policy to the specified URL. You can use a service like report-uri.com
or build your own collector.Deploy the Report-Only
header to your website and wait for violation reports to come in. As you browse your site and users interact with it, you will receive reports for every resource that is loaded from a source not on your allowlist.
For example, you might get a report that a script from https://google-analytics.com
was blocked. This tells you that you need to add it to your script-src
directive.
Based on the reports, gradually build up your policy by adding the legitimate sources you discovered.
Example: An evolving policy
Content-Security-Policy-Report-Only:
default-src 'none';
script-src 'self' https://google-analytics.com https://www.googletagmanager.com;
connect-src 'self' https://google-analytics.com;
img-src 'self' data: https://www.google-analytics.com;
style-src 'self' 'unsafe-inline' https://fonts.googleapis.com;
font-src 'self' https://fonts.gstatic.com;
report-uri https://your-csp-report-collector.com/report;
New additions:
script-src
, connect-src
, and img-src
.data:
was added to img-src
to allow for inline data URI images.style-src
and font-src
.'unsafe-inline'
was added to style-src
. This is often needed for legacy CSS but should be avoided if possible. Crucially, avoid 'unsafe-inline'
and 'unsafe-eval'
for script-src
, as they undermine the primary goal of CSP.Once you are confident that your policy covers all legitimate resources and you are no longer seeing violation reports for normal site operation, you can move to an enforcement policy.
To do this, simply change the header name from Content-Security-Policy-Report-Only
to Content-Security-Policy
.
Example: Final Enforcement Policy
Content-Security-Policy:
default-src 'none';
script-src 'self' https://google-analytics.com https://www.googletagmanager.com;
connect-src 'self' https://google-analytics.com;
img-src 'self' data: https://www.google-analytics.com;
style-src 'self' https://fonts.googleapis.com;
font-src 'self' https://fonts.gstatic.com;
report-uri https://your-csp-report-collector.com/report;
(Note: We aim to remove 'unsafe-inline'
from style-src
by refactoring CSS if possible).
report-uri
: Always include a report-uri
(or the newer report-to
) directive, even in enforcement mode. This will alert you to any new injection attacks being attempted against your site.'unsafe-inline'
and 'unsafe-eval'
for scripts: These directives largely defeat the purpose of CSP. If you must use inline scripts, use a nonce or a hash.script-src 'nonce-rAnd0m'
) and to the script tag (<script nonce="rAnd0m">
).script-src 'sha256-...'
).object-src 'none'
: Disallow plugins like Flash, which are a common attack vector.frame-ancestors 'self'
: This directive helps prevent clickjacking attacks by controlling where your site can be framed.Implementing a strong CSP is a powerful step towards securing your website. By starting with a Report-Only
policy and iteratively refining it, you can deploy this critical security feature without breaking functionality.
Learn about account takeover threats, protection strategies, and detection methods to secure your digital accounts and prevent unauthorised access.
An overview of Account Takeover Attacks
A step-by-step breakdown of how credential stuffing attacks are carried out, from obtaining stolen credentials to bypassing defenses and taking over accounts.
An introduction to Anycast DNS
A quick description about what an Apex Domain is.
Learn the essential best practices for managing and rotating API keys to enhance security, prevent unauthorized access, and minimize the impact of key compromise.
© PEAKHOUR.IO PTY LTD 2025 ABN 76 619 930 826 All rights reserved.