

0 / 2 embers
0 / 3000 xp
click for more info
Complete a lesson to start your streak
click for more info
Still calibrating
click for more info
Not enough gems
Cost: 6 gems
1: Cross-Site Scripting (XSS)
incomplete
2: Fix Cross-Site Scripting
incomplete
3: Cross-Site Request Forgery (CSRF)
incomplete
4: CSRF Tokens
incomplete
5: Content Security Policy
incomplete
6: Legitimate Inline Scripts
incomplete
7: Sandboxing 'iframe' Elements
incomplete
8: Clickjacking
incomplete
9: Same-Origin and Referrer Policies
incomplete
10: Cross-Origin Resource Sharing
incomplete
11: CORS in Express
incomplete
12: Helmet
incomplete
Back
ctrl+,
Next
ctrl+.
This lesson's interactive features are locked, please to keep using them
Cross-Site Request Forgery (CSRF) happens when a browser is tricked into making a request the user didn't intend, using credentials the browser automatically includes.
Unlike XSS, CSRF does not require code execution in the target application. An attacker only needs a state-changing endpoint that trusts a session cookie:
<form action="https://bank.example.com/transfers" method="post">
<input type="hidden" name="recipient" value="attacker" />
<input type="hidden" name="amount" value="500" />
<button>Claim 500 free gems</button>
</form>
If a signed-in customer submits that form from an attacker-controlled page, the browser may attach the bank's session cookie! Sure, the attacker can't read the response, but they don't need to: the unauthorized transfer has already happened.
https://shop.example.com and https://evil.example.com are cross-origin because an origin includes the exact host. They're still same-site because a site uses the scheme and registrable domain. Different ports on the same host are also cross-origin but same-site.
That distinction matters because SameSite cookies govern cross-site requests, not every cross-origin request. They're an important defense, but an attacker-controlled sibling subdomain can still be same-site.
For state-changing browser requests, the server can compare the request's Origin header with its trusted application origin:
Origin: https://evil.example.com
If Origin is present, it must match exactly. When it's absent, the server can parse the Referer header and compare that URL's origin instead. Prefix or substring checks are unsafe: https://shop.example.com.attacker.example is not https://shop.example.com.
If neither header is present, the server can't verify the request's source at all and should reject it. Sure, that might reject some non-browser clients that send neither header, but treating an unverifiable request as trusted would leave the hole wide open.
Bearly Secure needs to verify that state-changing requests came from its own pages. Build the request-source guard before allowing POST requests through.
npm run attacker-lab
With Bearly Secure and Bearly Evil still running, run and submit the CLI tests from the project root.
You can stop Bearly Evil after successfully submitting this lesson.