Sensitive data in HTML5 Web Storage
ID |
javascript.sensitive_data_web_storage |
Severity |
high |
Resource |
Information Leak |
Language |
JavaScript |
Tags |
CWE:922, NIST.SP.800-53, OWASP:2021:A4, PCI-DSS:6.5.3 |
Description
Local Storage and Session Storage (known as Web Storage) are HTML5 features that allows web developers to store information in the user’s browser using JavaScript.
Data in Local Storage is saved across browser sessions as it does not have expiration time. It is similar to persistent cookies as it is under the same-origin policy.
It is not recommended to save sensitive data into Web Storage, such as session data, user details, personal information, credit card info, authentication tokens or JWTs, etc.
Rationale
Web Storage is not recommended for storing sensitive data because it is not encrypted and can be easily accessed by the user, and attackers may exploit cross-site scripting attacks to exfiltrate without effort the stored data. In the case of local storage this is even worse, as it outlives web sessions.
Web Storage was not designed to be used as a secure store in a browser. It was designed as a simple key/value store for public configuration values, like user preferences and the like.
Do not consider Web Storage (localStorage
or sessionStorage
) as a secure store for sensitive data. A single cross-site scripting vulnerability can allow an attacker to steal the stored data, or to modify it without leaving any trace. The same happens with the indexedDB
database API.
This example stores sensitive data into local storage:
// FLAW
localStorage.username = document.getElementById('login_username').value;
localStorage.password = document.getElementById('login_password').value;
Other cases will check for session identifiers, anti-CSRF tokens, password reset tokens or 'remember-me' tokens (fetched from cookies or hidden form fields), etc.
Remediation
Never store anything sensitive in local storage.
The only situation in which you should use local storage: when you need to store some publicly available information that is not at all sensitive, doesn’t need to be used in a high performance app, isn’t larger than 5MB, and consists of purely string data.
For session identifiers, use cookies instead. Session identifiers are generated by the server and should be stored in cookies, with the HttpOnly
flag to avoid JavaScript access, Secure
so cookie is only sent over HTTPS, and SameSite
set preferably to Strict
.
Prefer sessionStorage
over localStorage
if you need to store temporary data. sessionStorage
is available only to that browser window/tab, and is deleted when it is closed.
You may store encrypted or hashed data into Web Storage, as far as the data is cryptographically protected. |
Configuration
The detector has the following configurable parameters:
-
sources
, that indicates the source kinds to check. -
neutralizations
, that indicates the neutralization kinds to check.
Unless you need to change the default behavior, you typically do not need to configure this detector.
References
-
CWE-922 : Insecure Storage of Sensitive Information.
-
OWASP Top 10 2021 Category A01 : Broken Access Control.
-
HTML5 Security - Local Storage, in OWASP Cheat Sheet Series.
-
Please stop using Local Storage, by R. Degges.
-
Secure data storage in the browser, by Pragmatic Web Security.