Web Security from the Browser’s Perspective
Preface
The web security knowledge I had picked up before was mostly from a frontend point of view, so the most familiar one was using input to perform an XSS attack, and I had not really touched on much else. However, after recently starting to learn more about how browsers work, I realized that looking at Web security from the browser’s perspective gives a more complete picture.
From the browser’s perspective, Web security can be roughly divided into Web page security, browser network security, and browser system security.
Web Page Security
Same-origin policy
If two URLs share the same protocol, domain, and port, they are considered same-origin. The same-origin policy ensures that within a single page, you can only use and request resources from the same origin.
What would happen if there were no same-origin policy? Suppose we open a banking page, and then accidentally open a malicious site. The malicious site could freely modify the DOM of the banking page, or even monitor our behavior on it. Therefore, the same-origin policy is the most basic security guarantee on the web. At the very least, we are not running naked online with every action observable.
The same-origin policy applies on three levels: DOM, web data, and network.
DOM level
- For two pages with a same-origin relationship, you can use Javascript to operate DOM nodes across pages; if they are not same-origin, this is restricted.
For example, on site XXX, open a sub-tab, then in the console run:
{ let pdom = opener.document pdom.body.style.display = "none" }The DOM will be hidden
Data level
- The same-origin policy prevents non-same-origin sites from reading the current site’s Cookie, IndexDB, LocalStorage and other data.
- Based on the same-origin policy, you cannot read these via the second page’s
opener.
Network level
- The same-origin policy restricts sending site data to non-same-origin sites via methods like XMLHttpRequest.
However, completely restricting a page to same-origin resources, while secure, is also very inconvenient. Therefore the same-origin policy makes the following concessions:
- Pages can embed third-party resources
- This means a page can use a CDN to import resources, but CSP needs to be configured to prevent XSS attacks.
- Cross-origin resource sharing and cross-document messaging
- XMLHttpRequest and Fetch cannot directly request non-same-origin resources, so the browser introduced CORS (Cross-Origin Resource Sharing) to allow safe cross-origin requests.
- Two non-same-origin DOMs cannot manipulate each other, so the browser introduced the cross-document messaging mechanism, allowing communication with non-same-origin DOMs through the JS API
window.postMessage.
XSS attack (Cross Site Scripting)
An XSS attack mainly involves injecting malicious Javascript into a page in various ways, after which the hacker can do whatever they want, such as stealing Cookie data, modifying the DOM, monitoring user behavior, popping up ad dialogs, and so on. So how is the malicious script injected? There are mainly three types:
- Stored XSS attack
- The hacker exploits a vulnerability on the page to upload a malicious script to the target server. The most typical case is uploading the script to the server through an
inputon the page. - Then when a user requests the page that contains the malicious script, the malicious script is also fetched and executed.
- The hacker exploits a vulnerability on the page to upload a malicious script to the target server. The most typical case is uploading the script to the server through an
Reflected XSS attack
- A common case is when a user accidentally clicks on a hacker’s link.
That link submits a request containing malicious code to the Web server, and the Web server reflects the malicious code back to the browser. A simple demo with NodeJS:
var express = require('express'); var router = express.Router(); /* GET home page. */ router.get('/', function(req, res, next) { res.render('index', { title: 'Express',xss:req.query.xss }); }); module.exports = router;If the user clicks a URL like
http://www.xxx.com?xss=<script>alert('attack!!')</script>, that is a simple illustration of an XSS attack.
DOM-based XSS attack
- It does not involve the server, and may go through WiFi or local malware.
- Uses network hijacking to modify the content and data of the HTML page during transmission.
So how do we prevent XSS attacks?
- Filter input content on the server, so scripts do not get into the database.
- Make full use of CSP.
- Set
HttpOnlyon Cookies, because Javascript cannot read data set withHttpOnlyin a Cookie.
CSRF attack (Cross-site request forgery)
A CSRF attack, also known as cross-site request forgery, mainly takes advantage of sites with CSRF vulnerabilities. Such sites record the user’s login info in the browser, intended to make life convenient by avoiding re-login; but this also gives hackers an opportunity to use the user’s logged-in state to perform malicious operations from a third-party site.
Take Facebook as an example: assume that after a user logs in to Facebook, Facebook simply records the user’s login state in the browser cookie; at the same time, Facebook also supports a transfer feature, with API as follows:
# Supports both GET and POST
# Endpoint
https://www.facebook.com/sendcoin
# Parameters
## Target user
user
## Amount
number
# Example: transfer 1000 to user Davie
https://www.facebook.com/sendcoin?user=Davie&number=1000
At this point, the hacker can use a few simple attack tricks:
Auto-fire a GET request, e.g. hide the request URL inside an
img:<!DOCTYPE html> <html> <body> <h1>Hecker CSRF Attack Example</h1> <img src="https://www.facebook.com/sendcoin?user=hacker&number=1000"> </body> </html>- This way, once the user enters this page, and the browser already has the user’s login Cookie, a transfer is automatically initiated.
Auto-fire a POST request:
<!DOCTYPE html> <html> <body> <h1>Hecker CSRF Attack Example</h1> <form id='hacker-form' action="https://www.facebook.com/sendcoin" method=POST> <input type="hidden" name="user" value="hacker" /> <input type="hidden" name="number" value="100" /> </form> <script> document.getElementById('hacker-form').submit(); </script> </body> </html>- As you can see, the hacker creates a hidden Form on the page, and once the user enters the page, this Form’s submit is fired automatically.
Luring the user into clicking also uses the same principle.
So how do we prevent CSRF attacks?
- Make full use of the SameSite attribute on Cookies.
- In the HTTP header, when setting a Cookie via the
set-cookiefield, you can include theSameSiteoption to forbid third-party use. TheSameSiteoption usually has Strict, Lax, and None.
- Strict completely forbids third-party use.
- Lax allows third-party Cookies to be sent in some HTML tag situations.
- In the HTTP header, when setting a Cookie via the
- The server side should verify the request’s origin site.
Browser System Security
This part, simply put, is the browser using Browser Sandboxing to isolate the Render Process from other processes.
For example, if we download a piece of malware but never execute it, it cannot harm our computer. Similarly, when a page downloaded by the browser contains a script that is harmful to the operating system, and the Render Process executes that script, without isolating the Render Process the script could really touch the OS and run the malicious code; with Browser Sandboxing, the Render Process is isolated from the operating system, so even if the Render Process is attacked through a vulnerability, it will not affect the local computer’s OS.
Browser Network Security
HTTPS
Network security in the browser, preventing man-in-the-middle attacks.
- Digital Certificate
- Use a digital certificate to prove the server’s identity to the browser.
- The digital certificate contains the server’s public key.
ChangeLog
- 20221102 - init
- 20260501–translate by claude code
Ref
- Geektime: 《Browser Principles and Practice》