How is the DOM object document.cookie property built? - javascript

When you are served a web page, who builds the DOM document? Is it strictly the server printing HTML? How is the browser involved? I am specifically interested in knowing how is the document.cookie property populated.
A) The server populates document.cookie
The browser stores a cookie for foobar.com in the users hard drive.
The next time foobar.com is visited, the browser presents all cookies for foobar.com to the server.
The server builds the DOM document.cookie property based on these cookies.
B) The browser populates document.cookie
The browser stores a cookie for foobar.com in the users hard drive.
The next time foobar.com is visited, the server goes on about constructing and serving the HTML.
Somewhere before or after the browser grabs all the cookies on the hard drive and populates document.cookie.
I am interested in this information because I'm studying how cookie stripping at proxy servers such as Varnish and Squid can affect cookies. If document.cookie was built by the server (option A above), then I would assume cookie stripping by proxies would affect the document.cookie property. I am however party inclined to think B is the case since I have a directive in a Varnish server to specifically strip a cookie, but the data of the cookie remains persistent in document.cookie even after stripping it from the request.
This question is especially important for people who have websites behind Varnish, since a request that comes attached with a cookie negates the use of cached data and generates a back-end hit.

The DOM is built and used by the browser based on the server's response. Part of the job of a browser's layout engine is to parse the HTML returned by the server into the DOM. Unfortunately, the different browsers use different layout engines, so the DOM tree sometimes has differences within it.
document.cookie specifically is a attribute of the DOM Level 1 spec. As was said, the correct answer is more or less (B). Cookies are packaged as part of the request that a client sends to the server, and although the server can set cookies in the response, in the end they all reside in the client side.

The Server sends data to the browser which interprets it and builds a DOM tree. the cookies are sent along with the data and are not built into the DOM, but instead stored on the local machine. basically B. The browser can manipulate cookies on the machine; the server can manipulate any cookies it's issued.

Related

Why does document.cookie exist and when is it used by DOM in a browser?

I am a bit confused by the document.cookie property: why does this property exist at all, and under what scenario the DOM, when being rendered in a browser, want to access it?
The examples that I can find, such as https://www.w3schools.com/js/js_cookies.asp and https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie, only tell me how to read or write a cookie, but I wonder why the DOM need to access the cookie at all.
Consider an HTTP response, both the web document and the cookie are sent from the origin server, what is the reason that the web document wants to access the cookie only after it is loaded into the browser? Why can't such jobs be done at the server side and save client's effort and time? And based on my understanding, cookie is used for the server to identify session or user and will be attached by the browser when a request is sent to the server, which does not contain any meaningful content from human being's perspective, so what practical use of cookies in the DOM context?
It's meant to be accessed by JavaScript. As JS is built to interface with the page DOM, it uses that to set/read cookies. For example (and this is gonna sound very meta but bear with me), you can programmatically set a cookie for a user if they hit the "I agree" on a cookie consent notification. JS can then search for that cookie to see if the user has agreed, and then decide whether or not to display the notification, which itself is a process that interacts with DOM.

Javascript how to create a cookie not sent to server [duplicate]

I want to reduce load times on my websites by moving all cookies into local storage since they seem to have the same functionality. Are there any pros/cons (especially performance-wise) in using local storage to replace cookie functionality except for the obvious compatibility issues?
Cookies and local storage serve different purposes. Cookies are primarily for reading server-side, local storage can only be read by the client-side. So the question is, in your app, who needs this data — the client or the server?
If it's your client (your JavaScript), then by all means switch. You're wasting bandwidth by sending all the data in each HTTP header.
If it's your server, local storage isn't so useful because you'd have to forward the data along somehow (with Ajax or hidden form fields or something). This might be okay if the server only needs a small subset of the total data for each request.
You'll want to leave your session cookie as a cookie either way though.
As per the technical difference, and also my understanding:
Apart from being an old way of saving data, Cookies give you a limit of 4096 bytes (4095, actually) — it's per cookie. Local Storage is as big as 10MB per domain — this Stack Overflow question also mentions it.
localStorage is an implementation of the Storage Interface. It stores data with no expiration date, and gets cleared only through JavaScript, or clearing the Browser Cache / Locally Stored Data — unlike cookie expiry.
In the context of JWTs, Stormpath have written a fairly helpful article outlining possible ways to store them, and the (dis-)advantages pertaining to each method.
It also has a short overview of XSS and CSRF attacks, and how you can combat them.
I've attached some short snippets of the article below, in case their article is taken offline/their site goes down.
Local Storage
Problems:
Web Storage (localStorage/sessionStorage) is accessible through JavaScript on the same domain. This means that any JavaScript running on your site will have access to web storage, and because of this can be vulnerable to cross-site scripting (XSS) attacks. XSS in a nutshell is a type of vulnerability where an attacker can inject JavaScript that will run on your page. Basic XSS attacks attempt to inject JavaScript through form inputs, where the attacker puts alert('You are Hacked'); into a form to see if it is run by the browser and can be viewed by other users.
Prevention:
To prevent XSS, the common response is to escape and encode all untrusted data. But this is far from the full story. In 2015, modern web apps use JavaScript hosted on CDNs or outside infrastructure. Modern web apps include 3rd party JavaScript libraries for A/B testing, funnel/market analysis, and ads. We use package managers like Bower to import other peoples’ code into our apps.
What if only one of the scripts you use is compromised? Malicious
JavaScript can be embedded on the page, and Web Storage is
compromised. These types of XSS attacks can get everyone’s Web Storage
that visits your site, without their knowledge. This is probably why a
bunch of organizations advise not to store anything of value or trust
any information in web storage. This includes session identifiers and
tokens.
As a storage mechanism, Web Storage does not enforce any secure
standards during transfer. Whoever reads Web Storage and uses it must
do their due diligence to ensure they always send the JWT over HTTPS
and never HTTP.
Cookies
Problems:
Cookies, when used with the HttpOnly cookie flag, are not accessible through JavaScript, and are immune to XSS. You can also set the Secure cookie flag to guarantee the cookie is only sent over HTTPS. This is one of the main reasons that cookies have been leveraged in the past to store tokens or session data. Modern developers are hesitant to use cookies because they traditionally required state to be stored on the server, thus breaking RESTful best practices. Cookies as a storage mechanism do not require state to be stored on the server if you are storing a JWT in the cookie. This is because the JWT encapsulates everything the server needs to serve the request.
However, cookies are vulnerable to a different type of attack:
cross-site request forgery (CSRF). A CSRF attack is a type of attack
that occurs when a malicious web site, email, or blog causes a user’s
web browser to perform an unwanted action on a trusted site on which
the user is currently authenticated. This is an exploit of how the
browser handles cookies. A cookie can only be sent to the domains in
which it is allowed. By default, this is the domain that originally
set the cookie. The cookie will be sent for a request regardless of
whether you are on galaxies.com or hahagonnahackyou.com.
Prevention:
Modern browsers support the SameSite flag, in addition to HttpOnly and Secure. The purpose of this flag is to prevent the cookie from being transmitted in cross-site requests, preventing many kinds of CSRF attack.
For browsers that do not support SameSite, CSRF can be prevented by using synchronized token patterns. This
sounds complicated, but all modern web frameworks have support for
this.
For example, AngularJS has a solution to validate that the cookie is
accessible by only your domain. Straight from AngularJS docs:
When performing XHR requests, the $http service reads a token from a
cookie (by default, XSRF-TOKEN) and sets it as an HTTP header
(X-XSRF-TOKEN). Since only JavaScript that runs on your domain can
read the cookie, your server can be assured that the XHR came from
JavaScript running on your domain. You can make this CSRF protection
stateless by including a xsrfToken JWT claim:
{
"iss": "http://galaxies.com",
"exp": 1300819380,
"scopes": ["explorer", "solar-harvester", "seller"],
"sub": "tom#andromeda.com",
"xsrfToken": "d9b9714c-7ac0-42e0-8696-2dae95dbc33e"
}
Leveraging your web app framework’s CSRF protection makes cookies rock
solid for storing a JWT. CSRF can also be partially prevented by
checking the HTTP Referer and Origin header from your API. CSRF
attacks will have Referer and Origin headers that are unrelated to
your application.
The full article can be found here:
https://stormpath.com/blog/where-to-store-your-jwts-cookies-vs-html5-web-storage/
They also have a helpful article on how to best design and implement JWTs, with regards to the structure of the token itself:
https://stormpath.com/blog/jwt-the-right-way/
With localStorage, web applications can store data locally within the user's browser. Before HTML5, application data had to be stored in cookies, included in every server request. Large amounts of data can be stored locally, without affecting website performance. Although localStorage is more modern, there are some pros and cons to both techniques.
Cookies
Pros
Legacy support (it's been around forever)
Persistent data
Expiration dates
Cookies can be marked as HTTPOnly which might limit XSS atacks to user browser during his sesion (does not guarantee full immunity to XSS atacks).
Cons
Each domain stores all its cookies in a single string, which can make
parsing data difficult
Data is unencrypted, which becomes an issue because... ... though
small in size, cookies are sent with every HTTP request Limited size
(4KB)
Local storage
Pros
Support by most modern browsers
Persistent data that is stored directly in the browser
Same-origin rules apply to local storage data
Is not sent with every HTTP request
~5MB storage per domain (that's 5120KB)
Cons
Not supported by anything before: IE 8, Firefox 3.5, Safari 4, Chrome 4, Opera 10.5, iOS 2.0, Android 2.0
If the server needs stored client information you purposely have
to send it.
localStorage usage is almost identical with the session one. They have pretty much exact methods, so switching from session to localStorage is really child's play. However, if stored data is really crucial for your application, you will probably use cookies as a backup in case localStorage is not available. If you want to check browser support for localStorage, all you have to do is run this simple script:
/*
* function body that test if storage is available
* returns true if localStorage is available and false if it's not
*/
function lsTest(){
var test = 'test';
try {
localStorage.setItem(test, test);
localStorage.removeItem(test);
return true;
} catch(e) {
return false;
}
}
/*
* execute Test and run our custom script
*/
if(lsTest()) {
// window.sessionStorage.setItem(name, 1); // session and storage methods are very similar
window.localStorage.setItem(name, 1);
console.log('localStorage where used'); // log
} else {
document.cookie="name=1; expires=Mon, 28 Mar 2016 12:00:00 UTC";
console.log('Cookie where used'); // log
}
"localStorage values on Secure (SSL) pages are isolated"
as someone noticed keep in mind that localStorage will not be
available if you switch from 'http' to 'https' secured protocol, where
the cookie will still be accesible. This is kind of important to
be aware of if you work with secure protocols.
Cookies:
Introduced prior to HTML5.
Has expiration date.
Cleared by JS or by Clear Browsing Data of browser or after expiration date.
Will sent to the server per each request.
The capacity is 4KB.
Only strings are able to store in cookies.
There are two types of cookies: persistent and session.
Local Storage:
Introduced with HTML5.
Does not have expiration date.
Cleared by JS or by Clear Browsing Data of the browser.
You can select when the data must be sent to the server.
The capacity is 5MB.
Data is stored indefinitely, and must be a string.
Only have one type.
Key Differences:
Capacity:
Local Storage: 10MB
Cookies: 4kb
Browser Support:
Local Storage: HTML5
Cookies: HTML4, HTML5
Storage Location:
Local Storage: Browser Only
Cookies: Browser & Server
Send With Request:
Local Storage: Yes
Cookies: No
Accessed From:
Local Storage: Any Window
Cookies: Any Window.
Expiry Date:
Local Storage: Never Expire, until done by javascript.
Cookies: Yes, Have expiry date.
Note: Use that, what suits you.
It is also worth mentioning that localStorage cannot be used when users browse in "private" mode in some versions of mobile Safari.
Quoted from WayBack Archive of MDN topic on Window.localStorage back in 2018:
Note: Starting with iOS 5.1, Safari Mobile stores localStorage data in the cache folder, which is subject to occasional clean up, at the behest of the OS, typically if space is short. Safari Mobile's Private Browsing mode also prevents writing to localStorage entirely.
Cookie:
is accessible by JavaScript so Cookie's data can be stolen by XSS
attack(Cross Site Scripting attack) but setting HttpOnly flag
to Cookie prevents the access by JavaScript so Cookie's data is
protected from XSS attack.
is vulnerable to CSRF(Cross Site Request Forgery) but setting
SameSite flag with Lax to Cookie mitigates CSRF and setting SameSite flag with Strict to Cookie prevents
CSRF.
must have expiry date so when expiry date passes, Cookie is
deleted automatically so even if you forgot to delete Cookie,
Cookie is deleted automatically because of expiry date.
is about 4KB as a common size (depending on browsers).
Local Storage:
is accessible by JavaScript so Local Storage's data can be stolen by XSS
attack(Cross Site Scripting attack) then, as logn as I researched,
there are no easy preventions for Local Storage from XSS
attack.
is not vulnerable to CSRF(Cross Site Request Forgery).
doesn't have expiry date so if you forgot to delete Local Storage
data, Local Storage data can stay forever.
is about 5MB as a common size (depending on browsers).
I recommend using Cookie for sensitive data and Local Storage for non-sensitive data.
Well, local storage speed greatly depends on the browser the client is using, as well as the operating system. Chrome or Safari on a mac could be much faster than Firefox on a PC, especially with newer APIs. As always though, testing is your friend (I could not find any benchmarks).
I really don't see a huge difference in cookie vs local storage. Also, you should be more worried about compatibility issues: not all browsers have even begun to support the new HTML5 APIs, so cookies would be your best bet for speed and compatibility.
Local storage can store up to 5mb offline data, whereas session can also store up to 5 mb data. But cookies can store only 4kb data in text format.
LOCAl and Session storage data in JSON format, thus easy to parse. But cookies data is in string format.

Local storage saved from external domain javascript doesn't get saved under external domain

If I load a javascript file from example.org on example.com and save something in local storage, it doesn't get saved under example.org (like how cookies would) but gets saved under example.com instead.
This makes it impossible for data to be kept on example.org like in the case of cookies. Cookies would work but they would carry the burden of being passed on along every HTTP request, which is what I want to avoid.
Tried looking up but nothing actually caters to the scenario of javascript being loaded from an external domain. Is this really by design? Doesn't sound like a good approach.
Whenever browser-side JavaScript needs to care about the origin, it uses the URL of the page hosting the JavaScript to determine it.
This is the only reasonable way to approach it, because you would otherwise have a huge security hole.
Jo Evil Hacker would simply <script src="http://example.org/yourScript.js"></script> and then call functions in it to get the cookies which should be kept private from them.

JavaScript and third party cookies

Say there is a site foo.com which loads JavaScript from site bar.com. Now, say the JavaScript from site bar.com tries to read cookies using document.cookies. I was under the impression that using JavaScript, you can read all the cookies set in the browser irrespective of their source. But it turns out that the JavaScript from the site bar.com can only access cookies set by bar.com and not any other. If this is the case, how are script injection attacks which steal cookies carried out?
But it turns out that the JavaScript from the site bar.com can only access cookies set by bar.com and not any other.
That isn't true. What matters is where the HTML document containing the <script> element is, not the URL of the JS file that said <script> mentions in the src attribute.
I suspect your problem is that you are accessing document.cookies when the property is called document.cookie (Singular!)
They load scripts inside the attacked page.
For instance, when comments in a blog system get compromised, they contain a script element that is executed when the page is rendered. This script can get the cookies and send it to the attacker's server.
That's why you should never trust user input and disallow at least certain tags in comments (or translate every < to <). But don't do this on the client side, as this prevention technique can easily be circumvented; test for (and change) malicious input on the server side.
You can only access cookies which have been set for the given domain name. From the Wikipedia article on cookies:
Beside the name/value pair, a cookie
may also contain an expiration date, a
path, a domain name, and whether the
cookie is intended only for encrypted
connections. RFC 2965 mandates cookies
have a version number, but this is
usually omitted. These pieces of data
follow the name=newvalue pair and are
separated by semicolons. For example,
a cookie can be created by the server
by sending a line Set-Cookie:
name=newvalue; expires=date; path=/;
domain=.example.org.
The domain and
path tell the browser that the cookie
has to be sent back to the server when
requesting URLs of a given domain and
path. If not specified, they default
to the domain and path of the object
that was requested. As a result, the
domain and path strings may tell the
browser to send the cookie when it
normally would not. For security
reasons, the cookie is accepted only
if the server is a member of the
domain specified by the domain string.
If foo.com sent a cookie which had the domain name of bar.com, or even .com, then JavaSCript code on bar.com could read that cookie. However most browsers are configured to only accept cookies when the domain name matches, and would reject such a cookie.

Using non persistent Http Cookies to deliver out of band data to the browser

Imagine that your web application maintains a hit counter for one or multiple pages and that it also aggressively caches those pages for anonymous visitors. This poses the problem that at least the hitcount would be out of date for those visitors because although the hitcounter is accurately maintained on the server even for those visitors, they would see the old cached page for a while.
What if the server would continue to serve them the cached page but would pass the updated counter in a non-persistent http cookie to be read by a piece of javascript in the page that would inject the updated counter into the DOM.
Opinions?
You are never going to keep track of the visitors in this manner. If you are aggressively caching pages, intermediate proxies and browsers are also going to cache your pages. And so the request may not even reach your server for you to track.
The best way to do so would be to use an approach similar to google analytics. When the page is loaded, send an AJAX request to the server. This ajax request would increment the current counter value on the server, and return the latest value. Then the client side could could show the value returned by the server using javascript.
This approach allows you to cache as aggressively as you want without losing the ability to keep track of your visitors.
you can also get the page programmatically via asp or php out the cache yourself and replace the hitcounter.

Categories

Resources