Posts Tagged ‘SSRF’
Guarding the Web: Understanding and Mitigating Modern Application Security Risks: XSS • CSRF • Clickjacking • CORS • SSRF
Modern web applications operate in a hostile environment. Attackers exploit input handling, browser trust, and server connectivity to inject code (XSS), trigger unauthorized actions (CSRF), trick users into clicking hidden UI (clickjacking), abuse permissive cross-origin policy (CORS), or make the server itself fetch sensitive resources (SSRF). This article explains the mechanics of each threat and provides concrete, production-grade mitigation patterns you can adopt today.
Cross-Site Scripting (XSS): When Untrusted Input Becomes Code
Threat model: User-provided data is rendered into a page without correct encoding or policy restrictions, allowing script execution in the victim’s browser.
Typical Exploits
Stored XSS (comments, profiles):
<script>fetch('/api/session/steal', {credentials:'include'})</script>
Reflected XSS (search query):
GET /search?q=<script>alert(1)</script>
DOM-based XSS (dangerous sinks):
// Anti-pattern: innerHTML with untrusted input
const result = new URLSearchParams(location.search).get('msg');
document.getElementById('banner').innerHTML = result; // XSS sink
High-Confidence Mitigations
- Contextual Output Encoding: Encode before insertion, based on context (HTML, attribute, URL, JS, CSS).
- Prefer Safe APIs: Use
textContent/setAttributeoverinnerHTML; avoideval/Function constructors. - Framework Defaults: Modern templating (e.g., React, Angular) auto-escapes. Avoid escape bypasses (e.g.,
dangerouslySetInnerHTML) unless you sanitize with robust libraries. - Content Security Policy (CSP): Block inline scripts and restrict sources; use nonces.
CSP Example (Nonce-Based)
Content-Security-Policy: default-src 'none';
script-src 'self' 'nonce-r4nd0mNonce';
style-src 'self';
img-src 'self' data:;
connect-src 'self';
base-uri 'self';
frame-ancestors 'self';
form-action 'self';
Server/Framework Snippets
Express.js: encode + CSP headers
app.use((req, res, next) => {
res.set('Content-Security-Policy',
"default-src 'none'; script-src 'self'; style-src 'self'; img-src 'self' data:; connect-src 'self'; base-uri 'self'; frame-ancestors 'self'");
res.set('X-Content-Type-Options', 'nosniff');
next();
});
Do sanitize if you must render HTML: Use a vetted sanitizer (e.g., DOMPurify on the client, OWASP Java HTML Sanitizer on the server) with an allowlist.
Cross-Site Request Forgery (CSRF): Abusing Session Trust
Threat model: A logged-in user’s browser sends a forged state-changing request (e.g., money transfer) to a trusted site because cookies are automatically included.
Exploit Example
<form action="https://bank.example/transfer" method="POST">
<input type="hidden" name="to" value="attacker">
<input type="hidden" name="amount" value="1000">
</form>
<script>document.forms[0].submit();</script>
Mitigations That Work Together
- Synchronizer (Anti-CSRF) Tokens: Embed a per-session/per-request token in each state-changing form or AJAX request; verify server-side.
- SameSite Cookies: Set session cookies to
SameSite=LaxorStrictandSecureto block cross-site inclusion. - Method & Content Checks: Require POST/PUT/DELETE with
Content-Type: application/json; reject unexpected content types. - Origin/Referer Validation: For sensitive endpoints, verify
Origin(preferred) orReferer. - Re-authentication / Step-Up: For high-value actions, require a second factor or password confirmation.
Example (Express + CSRF Token)
// Pseudocode with csurf-like middleware
app.post('/transfer', requireAuth, verifyCsrfToken, (req, res) => {
// process transfer
});
SPA + API note: Prefer token-based auth (Authorization header) to avoid ambient cookies. If you must use cookies, combine SameSite with CSRF tokens.
Clickjacking: UI Redress and Hidden Frames
Threat model: An attacker overlays your site in an invisible <iframe> and tricks users into clicking sensitive controls.
Exploit Sketch
<iframe src="https://target.example/approve" style="opacity:0;position:absolute;top:0;left:0;width:100%;height:100%"></iframe>
Mitigations
- X-Frame-Options (XFO):
DENYorSAMEORIGIN. (Legacy but still widely respected.) - CSP frame-ancestors: Modern, fine-grained embedding control.
- UI Hardening: Re-prompt for confirmation on dangerous actions; disable one-click irreversible changes.
Header Examples
X-Frame-Options: DENY
Content-Security-Policy: frame-ancestors 'self'
Server Config
Nginx:
add_header X-Frame-Options "DENY" always;
add_header Content-Security-Policy "frame-ancestors 'self'" always;
Apache:
Header always set X-Frame-Options "DENY"
Header always set Content-Security-Policy "frame-ancestors 'self'"
CORS: Safe Cross-Origin Requests Without Overexposure
Threat model: Overly permissive CORS allows arbitrary origins to read sensitive API responses or send authenticated requests.
Dangerous Patterns
Access-Control-Allow-Origin: *combined withAccess-Control-Allow-Credentials: true(browsers will ignore, but this signals confusion and often pairs with other mistakes).- Reflecting the request
Originwholesale without an allowlist. - Forgetting
Vary: Origin, causing caches/CDNs to serve one origin’s CORS response to all.
Safe Configuration
Access-Control-Allow-Origin: https://app.example
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Authorization, Content-Type
Access-Control-Expose-Headers: ETag, X-Request-Id
Vary: Origin
Implementation Tip
// Pseudocode: strict allowlist
const allowed = new Set(['https://app.example', 'https://admin.example']);
const origin = req.headers.origin;
if (allowed.has(origin)) {
res.setHeader('Access-Control-Allow-Origin', origin);
res.setHeader('Vary', 'Origin');
}
Principle: CORS is not an auth mechanism—treat it as a read-permission gate. Apply per-endpoint scoping; don’t turn it on globally.
Server-Side Request Forgery (SSRF): Turning Your Server Into a Proxy
Threat model: The application fetches remote resources based on user input (URLs), allowing attackers to reach internal networks or cloud metadata endpoints.
Exploit Examples
- Cloud metadata theft:
http://169.254.169.254/latest/meta-data/(AWS) /http://metadata.google.internal//http://169.254.169.254/metadata/instance(Azure; IMDSv2/headers required). - Reaching services on
localhostor RFC1918 IPs (e.g., Redis, internal dashboards). - Schema abuse:
file://,gopher://, orftp://if unsupported schemas aren’t blocked. - Open redirect chains or DNS rebinding that convert a safe-looking hostname into an internal IP at resolution time.
Defense-in-Depth
- Strict Allowlists: Only permit fetching from specific hosts/paths; reject everything else.
- URL & IP Validation: Parse the URL; resolve DNS; block private and link-local ranges; re-validate after redirects.
- Egress Proxy with ACL: Force all outbound HTTP(S) through a proxy that enforces destination policies and logs requests.
- Cloud Hardening: Require IMDSv2 (AWS); block server access to metadata endpoints unless strictly needed.
- Timeouts & Size Limits: Short connect/read timeouts and response byte caps to prevent internal scanning and DoS.
Hardening Snippet (Pseudocode)
function safeFetch(userUrl) {
const url = new URL(userUrl);
// allowlist scheme
if (!['https:'].includes(url.protocol)) throw new Error('Blocked scheme');
// DNS resolve and block private IPs
const ip = resolveToIP(url.hostname);
if (isPrivate(ip) || isLinkLocal(ip) || isLoopback(ip)) throw new Error('Blocked destination');
// enforce egress proxy
return proxyHttpGet(url, { timeoutMs: 2000, maxBytes: 1_000_000, followRedirects: 3, revalidateIPOnRedirect: true });
}
Header note: SSRF is best mitigated by network policy and URL validation; “headers” alone can’t prevent SSRF, but you may set request policies (e.g., disallow redirects, strip sensitive headers) and enforce gateway rules.
Complementary Security Headers
- Strict-Transport-Security:
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload - X-Content-Type-Options:
nosniffto block MIME type sniffing. - Referrer-Policy: e.g.,
strict-origin-when-cross-origin. - Permissions-Policy: Restrict powerful APIs (camera, geolocation, etc.).
- Cross-Origin-Opener-Policy / Resource-Policy / Embedder-Policy: Strengthen isolation where feasible.
Operational Controls & SDLC Integration
- Threat Modeling: Map trust boundaries (browser ⇄ app ⇄ services ⇄ internet) and identify high-risk data flows.
- Static/Dynamic Testing: SAST, DAST, and dependency scanning in CI; add security unit tests for templating and request flows.
- Observability: Log security-relevant events (CSP violations via
report-to, WAF blocks, CSRF failures, SSRF proxy denies) and alert. - WAF/Gateway Policies: Enforce header baselines, block known bad payloads, and constrain egress with explicit ACLs.
- Secrets Hygiene: Short-lived tokens, mTLS for service-to-service, and key rotation.
- Least Privilege by Default: Scope CORS per endpoint, narrow IAM roles, network segmentation.
Deployment Checklist
- ✅ XSS: Contextual encoding, CSP with nonces, sanitizer for any HTML rendering.
- ✅ CSRF: Anti-CSRF tokens,
SameSite+Securecookies, Origin checks, step-up auth on critical actions. - ✅ Clickjacking:
X-Frame-Options: DENYandCSP frame-ancestors 'self'. - ✅ CORS: Explicit allowlist, credentials only when necessary,
Vary: Origin, scoped to sensitive endpoints. - ✅ SSRF: Allowlist destinations, block internal ranges, egress proxy with ACL, timeouts/size caps, re-validate after redirects.
- ✅ Headers: HSTS, XCTO, Referrer-Policy, Permissions-Policy in place.
- ✅ Ops: Logging/alerting on policy violations; SAST/DAST integrated; WAF rules tuned to app.
[DefCon32] Listen to the Whispers: Web Timing Attacks that Actually Work
Timing attacks, long dismissed as theoretically potent yet practically elusive, gain new life through innovative techniques. James Kettle bridges the “timing divide,” transforming abstract concepts into reliable exploits against live systems. By amplifying signals and mitigating noise, Kettle unveils server secrets like masked misconfigurations, blind injections, hidden routes, and untapped attack surfaces.
Traditional hurdles—network jitter and server noise—once rendered attacks unreliable. HTTP/2’s concurrency, enhanced by Kettle’s single-packet method, synchronizes requests in one TLS record, eliminating jitter. Coalescing headers via sacrificial PING frames counters sticky ordering, making attacks “local” regardless of distance.
Server noise, from load variances to cloud virtualization, demands signal amplification: repeating headers for cumulative delays or denial-of-service tactics like nested XML entities. Repetition exploits caching, reducing variability; trimming requests minimizes unnecessary processing.
Parameter Discovery and Control Flow Insights
Kettle adapts Param Miner for time-based parameter/header guessing, uncovering hidden features on thousands of bug bounty sites. Timing reveals parameters altering responses subtly, like JSON-validated headers or cache keys signaling web cache poisoning risks.
Control flow changes, such as exceptions, emerge vividly. A Web Application Firewall (WAF) bypass exemplifies: repeated “exec” parameters trigger prolonged analysis, escalating to denial-of-service; excess parameters expose max-header limits, enabling evasion.
IP spoofing headers like “True-Client-IP” induce DNS caching delays, confirmed via pingbacks. Non-caching variants suggest third-party geo-lookups, bypassing with hostnames.
Server-Side Injection Vulnerabilities
Timing excels at blind injections in non-sleep-capable languages. Serde JSON injections manifest as microsecond differentials; combining with client-side reflections infers standalone processing, aiding exploitation.
Blind Serde parameter pollution contrasts reserved/unreserved characters, yielding exploits. Doppelgangers—non-blind equivalents—guide understanding, turning detections into impacts.
SQL injections via sleep evade WAFs but overlap existing tools; timing shines where sleep fails, though exploitation demands deep target insight.
Scoped Server-Side Request Forgery Detection
Overlooked for years, scoped SSRF—proxies accessing only target subdomains—defies DNS pingbacks. Timing detects via DNS caching or label-length timeouts: valid hostnames delay; invalids accelerate or prolong.
Automating exploration, Kettle probes subdomains directly and via proxies, flagging discrepancies like missing headers. Exploits span firewall bypasses, internal DNS resolutions uncovering staging servers, pre-launch consoles, and frontend circumventions.
Frontend impersonation leverages trusted internal headers for authentication bypasses, exploitable via proxies, direct backend access, or smuggling. Timing guesses header names, enabling severe breaches.
Links:
EN_DEFCON32MainStageTalks_004_005.md