Web Application Security Hardening Guide
1. Clickjacking Protection
Problem: Site allows being embedded in iframes, exposing it to Clickjacking attacks.
Solution:
- Use HTTP response headers to restrict framing.
- Recommended Headers:
Content-Security-Policy: frame-ancestors 'none';
X-Frame-Options: DENY
Implementation:
- Apply headers in Nginx, Apache, IIS, Node.js, etc.
- Verify with curl and browser developer tools.
Apache Nginx IIS
<httpProtocol>
<customHeaders>
<add name="X-Frame-Options" value="DENY" />
<add name="Content-Security-Policy" value="frame-ance
Header always set X-Frame-Options "DENY" add_header X-Frame-Options "DENY"; </customHeaders>
Header always set Content-Security-Policy "frame-ancestors
add_header Content-Security-Policy
'none'" "frame-ancestors
</httpProtocol>
'none'";
2. Missing Security Headers (COEP & COOP)
Problem: Cross-Origin-Embedder-Policy and Cross-Origin-Opener-Policy missing.
Risk: Allows XS-Leaks, Spectre-style attacks, and window.opener exploitation.
Solution:
- Add headers:
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp
- Test in staging to avoid breaking external resources.
- Ensure third-party assets allow CORP or CORS, or self-host them.
Apache Nginx IIS
<httpProtocol>
<customHeaders>
<add name="Cross-Origin-Opener-Policy" value="same-o
<add name="Cross-Origin-Embedder-Policy" value="requ
Header always set Cross-Origin-Opener-Policy
add_header
"same-origin"
Cross-Origin-Opener-Policy "same-origin";
</customHeaders>
Header always set Cross-Origin-Embedder-Policy
add_header
"require-corp"
Cross-Origin-Embedder-Policy "require-corp";
</httpProtocol>
3. Multiple Security Headers Missing
Problem: Key security headers missing (CSP, Permission-Policy, Referrer-Policy, etc.).
Solution: Configure the following headers globally:
- Content-Security-Policy: default-src 'self'; script-src 'self'; object-src 'none'; frame-ancestors 'none';
- Permission-Policy: geolocation=(), camera=(), microphone=()
- X-Permitted-CrossDomain-Policy: none
- Referrer-Policy: strict-origin-when-cross-origin
- Clear-Site-Data: "cache", "cookies", "storage", "executionContexts" (use selectively, e.g., logout)
Implementation: Add headers in web server (Apache/Nginx/IIS) or app framework (Node, Django,
Spring).
Apache Nginx IIS
<httpProtocol>
<customHeaders>
<add name="Content-Security-Policy" value="default-src '
<add name="Referrer-Policy" value="strict-origin-when-cr
Header always set Content-Security-Policy "default-src
add_header'self'"
Content-Security-Policy "default-src<add
'self'";
name="X-Permitted-Cross-Domain-Policies" value=
Header always set Referrer-Policy "strict-origin-when-cross-origin"
add_header Referrer-Policy "strict-origin-when-cross-origin";
<add name="Permissions-Policy" value="geolocation=(), c
Header always set X-Permitted-Cross-Domain-Policies
add_header"none"
X-Permitted-Cross-Domain-Policies<add "none";
name="Clear-Site-Data" value="cache, cookies, stor
Header always set Permissions-Policy "geolocation=(),
add_headercamera=()"
Permissions-Policy "geolocation=(),</customHeaders>
camera=()";
Header always set Clear-Site-Data "\"cache, cookies,
add_header
storage,
Clear-Site-Data
executionContexts\""
"'cache', 'cookies',
</httpProtocol>
'storage', 'executionContexts'";
4. TRACE / TRACK HTTP Method Enabled
Problem: TRACE/TRACK methods enabled, exposing to XST attacks.
Solution: Disable TRACE/TRACK in production.
Examples:
- Apache: TraceEnable off
- Nginx: if ($request_method = TRACE) { return 405; }
- IIS:
- Node.js: Block TRACE/TRACK in middleware
Verify: curl -i -X TRACE https://site should return 405 or 501.
Apache Nginx IIS
<system.webServer>
<security>
<requestFiltering>
<verbs>
<add verb="TRACE" allowed="false" />
<add verb="TRACK" allowed="false" />
</verbs>
</requestFiltering>
</security>
TraceEnable off if ($request_method = TRACE) { return 405; }</system.webServer>
5. Directory Listing Enabled
Problem: Directory listing exposes internal structure and files if index is missing.
Solution:
- Apache: Options -Indexes
- Nginx: autoindex off;
- IIS:
- Node.js (express.static): express.static('public', { index: false })
Additional: Deploy index files, restrict permissions, use WAF for filtering backup/config files.
Apache Nginx IIS
<system.webServer>
<directoryBrowse enabled="false" />
Options -Indexes autoindex off; </system.webServer>
6. Username Enumeration
Problem: Error messages, APIs, or reset flows expose valid usernames.
Risk: Enables brute force and credential stuffing.
Solution:
- Always use generic error messages: "Invalid username or password"
- Use same response time regardless of account existence
- Rate limit login attempts
- In forgot-password: always respond with "If an account exists, you'll receive an email"
- API: return uniform status codes, never expose user existence
- Monitor for repeated probing attempts