‘Good’ and ‘evil’ web site
-
Visit these two web sites: good.puffling.no and evil.puffling.no. Visiting each will set a few cookies in your browser.
-
If you're running an ad blocker, you should probably turn it off for these two side (if you do, you'll feel like a winner!).
-
Press F12 to open the browser's developer tools, and go to the Network tab.
-
The two sites are pretty much the same, so you can mostly work with either one
Cookie policies
- Each site sets a number of cookies, e.g. for Good:
SESSION_ID_GOOD
,STRICT_COOKIE_GOOD
,NONE_COOKIE_GOOD
andDOMAIN_COOKIE
.
We'll assume you're working with good.puffling.no
, but you can pick the evil one if you like.
a) Determine what the SameSite
policy is for each cookie (for one of the sites + the CREEPY_AD_TRACKING_ID
belonging to ads.puffling.no
).
b) Without checking what the browser does, for cookie, try to guess/determine whether each cookie will be sent, for the following scenarios. The rules are described here.
- Visiting (clicking a link) from an unrelated site (e.g, the links here on GitLab)
- Visiting from the (i.e., a site belonging to the same domain name)versa)
- Loading an image embedded on the page on:
- an unrelated site (e.g., below)
- the good site
- the bad site
- Submitting a form from an unrelated, or the good or bad sites.
c) Check what the browser actually does. The good/evil pages will show which cookies the server received, so those are easy, but for other requests you must check the heders in the developer tools.


d) Assuming the owner of the ‘evil’ site is actually ‘evil’ (i.e., will try to access or change the user's data on the ‘good‘ site, without permission) – for the scenarios below, what do you imagine is the worst that could happen when the user is at the evil site, and requests including cookies are made to the good site. In particular, assume that the session cookie for a logged-in user is sent.
- User clicks a link to the good site
- User (or script) submits a form to the good site
- Script makes an API request for private data belonging to the user
- Evil page embeds a private image belonging to the user
Resource origin
e) On the evil site, try accessing image data from the good site, as seen in Embedded resources: Accessing cross-origin data.
f) Check the HTML code for the IMG
tags for the images found under Anonymous access.
-
Try accessing the image data in the same ways you tried in e). What's different compared to above? In particular, try loading the image with
await fetch(url)
. -
Check the request headers. What does the Sec-Fetch-Mode and Sec-Fetch-Site headers do?
Content Security Policy
For the good and evil sites, adding the csp
parameter to the request makes the server set the Content-Security-Policy
header. Try it here: https://good.puffling.no/?csp=default-src 'self'
(there's also form you can fill out on the page to try different policies).
The setting 'self'
means only allow resources from the same origin, https:
will allow from any server (with SSL/TLS), and unsafe-inline
will allow styles and scripts declared as element attributes (e.g., <tag style="…" onclick="…">
. With default-src
this applies to everything: scripts, style sheets, images, etc. You can combine multiple values in one directive: default-src 'self' 'unsafe-inline'
, and multiple semicolon-separated directives in one policy: style-src 'self'; img-src 'self'
.
g)
- Check what is blocked by
default-src 'self'
. (There will be error messages in the log.) - Find a policy that allows loading both
good_image
andevil_image
, but not thealien_image
orinline_image
. Make sure you only allow cross-origin images, not other resources such as CSS styles (the page border should be grey and Style sheets allowed should say only “same-origin”). - Modify the previous CSP to also allow cross-origin style sheets (Style sheets allowed should say only “same-origin” and “cross-origin”)
h)
The CSP setup from g) allows resources to be loaded over the net, but disallow inline resources. See the examples under Inline access To allow these, you need 'unsafe-inline'
.
Why is this not included by default? Why do you think inline resources are considered unsafe?
CORS – Cross-Origin Resource Sharing
i)
-
Go to the evil site, without CSP. Try clicking on CLICK ME! in the Inline access section. The text should change to “I got ur secrets” + whatever is in the text field below (
password123
by default). If not you might still have CSP on, or you're using an ad blocker. -
Visit the ad server which has been tracking your every move (unless you used an ad blocker). You should see your secret, and a log of your visits to the good and evil sites.
-
Try clicking CLICK ME TOO!. Nothing should happen, except an error message in the console log. The difference between “Click me” and “Click me too” is that in the first case, the server sends a
Access-Control-Allow-Origin
header, telling the browser that it's OK for a script to read this data. Without it, you get the CORS warnings in the console. -
Visit the ad server again. You should see that despite the error message, the secret was (probably) delivered to the server.
j)
If you've been visiting the evil site, your password has probably been stolen several times. If you've visited the good site, you should find “U got hacked!” in the console log, together with a reference to an IMG element. Why did this happen?