跳至内容

Referer lost after AWS WAF Challenge on Chrome

0

Hi,

I’m seeing some unexpected behavior while working with AWS WAF Challenges. I have a WAF attached to a CloudFront distribution, with a rule that issues a challenge when certain strings are present in the request URL. These URLs are indexed by Google.

When a user visits such a URL from Google, the initial request correctly includes the header: Referer: https://www.google.com/ The response serves the challenge (challenge.js) as expected.

However, after the challenge is completed, the subsequent request loses the original referer. Instead of https://www.google.com/, the browser sends the page’s own URL as the referer.

This behavior occurs on Chrome and Safari. On Firefox, everything works as expected: the referer remains https://www.google.com/.

From my tests, in all browsers the original referer is stored in Local Storage (e.g. {"referrer":"https://www.google.com/"}), but Chrome and Safari do not use it after completing the challenge.

I’ve tried adjusting the Referrer-Policy on CloudFront and Nginx, but it seems the referer is already lost before reaching CloudFront.

Is there something I’m missing, or is this expected behavior with AWS WAF Challenges? Any guidance or workaround would be appreciated.

Thank you!

已提问 3 个月前78 查看次数
1 回答
0

Why the Referer Header Changes After WAF Challenges

The behavior you're experiencing with lost Referer headers after WAF challenges is expected due to how the challenge mechanism works. Here's what's happening:

Initial Request Flow:
    User clicks a link from Google search results
    Browser sends request with Referer: https://www.google.com/
    AWS WAF intercepts this request and identifies it needs a challenge

Challenge Process:
    WAF returns a challenge page (with challenge.js) instead of your actual content
    This challenge page runs in the user's browser at your domain
    The challenge script completes silently in the background

Post-Challenge Request:
    After successful challenge completion, the browser makes a new request
    This new request originates from your domain (the challenge page)
    Browser sets the Referer to your page URL, not the original Google URL
    The original referer is lost in the standard HTTP flow

This happens because the WAF challenge creates a new browser context - essentially a client-side redirect - which changes the Referer according to standard browser behavior. Technical Solutions to Preserve the Original Referer

Since you've already confirmed the original referer is stored in Local Storage but not being used, here are several approaches to solve this issue:

  1. Custom Request Headers with Lambda@Edge

Use Lambda@Edge to add a custom header containing the original referer:

// Lambda@Edge Viewer Request function exports.handler = async (event) => { const request = event.Records[0].cf.request;

// Check if this is a post-challenge request (has WAF token) if (request.headers['x-amzn-waf-token']) { // Extract original referer from cookies or query params // Add it as a custom header request.headers['x-original-referer'] = [{ key: 'X-Original-Referer', value: /* extract from cookie or query param */ }]; }

return request; };

  1. URL Parameter Approach

Modify your application to include the original referer as a URL parameter:

Create a CloudFront Function that runs on Viewer Request:

function handler(event) { var request = event.request;

// Check if referer exists and no WAF token yet (first request) if (request.headers.referer && !request.headers['x-amzn-waf-token']) { var referer = request.headers.referer.value;

// Append referer to URL if it's from an external source
if (referer.indexOf('google.com') !== -1) {
  var separator = request.uri.indexOf('?') !== -1 ? '&' : '?';
  request.uri += separator + 'original_referer=' + encodeURIComponent(referer);
}

}

return request; }

Then handle this parameter in your application code.

3. Cookie-Based Solution

Set a cookie with the original referer that persists through the challenge:

// CloudFront Function (Viewer Request) function handler(event) { var request = event.request;

// Check if referer exists and no WAF token yet (first request) if (request.headers.referer && !request.headers['x-amzn-waf-token']) { var referer = request.headers.referer.value;

// Add a cookie header with the original referer
if (!request.cookies['original_referer']) {
  request.headers['cookie'] = {
    value: (request.headers.cookie ? request.headers.cookie.value + '; ' : '') + 
           'original_referer=' + encodeURIComponent(referer)
  };
}

}

return request; }

  1. Server-Side Tracking with WAF Custom Request Handling

Use AWS WAF's custom request handling to add the original referer to a header:

Create a custom request handling rule in WAF
Configure it to capture the Referer header on initial requests
Add this as a custom header that persists through the challenge

5. Client-Side JavaScript Solution

Since you mentioned the referer is already stored in localStorage, you can use JavaScript to restore it:

// Add this to your page document.addEventListener('DOMContentLoaded', function() { // Check if this is a post-challenge page load const hasWafToken = document.cookie.includes('aws-waf-token');

if (hasWafToken) { // Get stored referer from localStorage const storedData = localStorage.getItem('referrerData'); if (storedData) { const referrerData = JSON.parse(storedData);

  // Send an analytics event with the original referer
  if (typeof gtag === 'function') {
    gtag('event', 'page_view', {
      'referrer': referrerData.referrer
    });
  }
  
  // Or update your analytics data directly
  if (typeof ga === 'function') {
    ga('set', 'referrer', referrerData.referrer);
  }
}

} });

Implementation Considerations

Performance Impact: Lambda@Edge adds latency, while CloudFront Functions are more lightweight
Security: Validate and sanitize any referer data before using it
Browser Compatibility: Test across browsers as referer handling varies
Analytics Integration: Ensure your analytics platform can use custom headers or parameters

Best Practice Recommendation

The most robust solution is a combination of approaches:

- Use CloudFront Functions to capture the original referer on first request
- Store it as both a cookie and URL parameter
- Implement client-side code to restore it for analytics purposes

This provides multiple fallback mechanisms and works across different browser security policies.

https://docs.aws.amazon.com/waf/latest/APIReference/API_ChallengeAction.html

https://docs.aws.amazon.com/waf/latest/developerguide/waf-tokens-domains.html

https://docs.aws.amazon.com/waf/latest/developerguide/customizing-the-incoming-request.html

AWS
已回答 3 个月前

您未登录。 登录 发布回答。

一个好的回答可以清楚地解答问题和提供建设性反馈,并能促进提问者的职业发展。