关于XSS与CSRF的文章方案存疑?求安全解决方法
Absolutely—your observation is spot on. The combination of storing an auth token in sessionStorage and including session cookies via credentials: 'include' creates a double vulnerability when XSS occurs:
- An attacker with XSS access can easily read the token from
sessionStorageusingwindow.sessionStorage.getItem('token'), just like your legitimate code does. - Browsers automatically attach session cookies to requests when
credentials: 'include'is set, so the attacker doesn't even need to steal the cookie directly—their malicious script can simply send a request to the API, and the browser will include the cookie for them.
This means an attacker can forge fully authenticated requests using both the stolen token and the session cookie, rendering the dual-check approach useless. The setup is redundant at best and dangerous at worst, since it exposes two separate pieces of authentication data to XSS.
Here are proven strategies to mitigate both XSS and CSRF risks properly:
1. Use HttpOnly, Secure, SameSite cookies for authentication
This is the most robust approach for most scenarios:
- Store your session ID or auth token in an HttpOnly cookie: This prevents JavaScript (and thus XSS attackers) from accessing the cookie entirely.
- Add the Secure flag: Ensures the cookie is only sent over HTTPS, avoiding interception.
- Set a SameSite attribute (either
StrictorLax): Blocks browsers from sending the cookie in cross-site requests, neutralizing CSRF attacks.
With this setup, you can remove the sessionStorage token entirely. Your API only needs to validate the cookie, and the browser handles attaching it to requests automatically—no need for credentials: 'include' (though it's safe to use if needed).
2. Token-based auth for SPAs (with memory-only access tokens)
If you need token-based auth (e.g., for single-page apps that don't refresh the page):
- Store a short-lived access token only in memory (not
localStorage/sessionStorage). For example, hold it in a variable in your app's state. If the page refreshes, use a long-lived refresh token (stored in an HttpOnly cookie) to fetch a new access token. - The refresh token can't be accessed via XSS, and the access token is only present in memory—if an attacker steals it via XSS, it will expire quickly, limiting the window of opportunity.
3. Enforce Content Security Policy (CSP)
CSP acts as a safeguard to prevent XSS attacks from happening in the first place:
- Configure your server to send a
Content-Security-Policyheader that restricts script execution to trusted sources only. For example, block inline scripts,eval(), and scripts from untrusted domains. - This makes it far harder for attackers to inject and execute malicious scripts in your app.
4. Strict input/output sanitization
Always sanitize user input before storing it, and escape content when rendering it in the browser. For example:
- Escape HTML characters (like
<,>,") when displaying user-generated content to prevent script injection. - Use framework-built functions or trusted libraries to handle sanitization automatically.
内容的提问来源于stack exchange,提问作者Luukth

