Written by Ulises Gascón

Apr 08, 20202 min read

Based on MDN definition for ETag:

The ETag HTTP response header is an identifier for a specific version of a resource. It lets caches be more efficient and save bandwidth, as a web server does not need to resend a full response if the content has not changed. Additionally, etags help prevent simultaneous updates of a resource from overwriting each other.

If the resource at a given URL changes, a new Etag value must be generated. A comparison of them can determine whether two representations of a resource are the same. Etags are therefore similar to fingerprints, and might also be used for tracking purposes by some servers. They might also be set to persist indefinitely by a tracking server.

ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4"
ETag: W/"0815"

Note: 'W/*' indicates that a weak validator is used, so it is not valid for comparison (not byte-for-byte identical).

You can customize the behaviour in Express:

app.enable('etag') // use strong etags
app.set('etag', 'strong') // same
app.set('etag', 'weak') // weak etags
app.set('etag', function(chunk, encoding){ /* return valid etag */ }) // your own fn

The attack

In the past sometimes the ETag was misconfigured by default using built string and not hashes, like in CVE-2003-1418 that leads to information leaks.

Apache HTTP server in certain configurations allows remote attackers to obtain sensitive information via (1) the ETag header, which reveals the inode number, or (2) multipart MIME boundary, which reveals child proccess IDs (PID).