cors
8 TopicsiRule for CORS OPTIONS Header
I am working on creating an iRule that sends a 200 response when an OPTIONS header is sent. Here is the rule: when HTTP_REQUEST { if { ( [HTTP::method] equals "OPTIONS" ) } { HTTP::respond 200 Access-Control-Allow-Origin "[HTTP::header Origin]" Access-Control-Allow-Methods "POST, GET, OPTIONS" Access-Control-Allow-Headers "[HTTP::header Access-Control-Request-Headers]" Access-Control-Max-Age "86400" return } } When attempting to deploy this irule to an application, I am given the following error: IRule error: Transaction on BIG-IP failed after 0 seconds: 01070151:3: Rule [/Common/CORS-Preflight] error: /Common/CORS-Preflight:4: error: [undefined procedure: Access-Control-Allow-Methods][Access-Control-Allow-Methods "POST, GET, OPTIONS"] /Common/CORS-Preflight:5: error: [undefined procedure: Access-Control-Allow-Headers][Access-Control-Allow-Headers "[HTTP::header Access-Control-Request-Headers]" ] /Common/CORS-Preflight:6: error: [undefined procedure: Access-Control-Max-Age][Access-Control-Max-Age "86400"] Can anyone help with what the syntax issue may be with this?1.4KViews0likes2CommentsAccess-Control-Allow-Origin iRule Strange Error
I hope somebody here can help me. I've been sitting on this issue for over 8 hours now. I'm trying to enable CORS in my loadbalancer. I created an iRule which should intercept all OPTIONS type requests (because our backend cannot handle them) and answer it with the appropriate headers: when HTTP_REQUEST { if { [HTTP::method] eq "OPTIONS" } { HTTP::respond 200 -version 1.1 \ Date "[clock format [clock seconds] -format "%a, %d %b %Y %H:%M:%S %Z"]" \ Connection "Keep-Alive" \ Keep-Alive "timeout=3, max=250" \ Access-Control-Allow-Origin "*" \ Access-Control-Allow-Methods "GET, HEAD, POST, PATCH, PUT" \ Access-Control-Allow-Headers "Accept, Authentication, Authorization, Content-Encoding, Content-Length, Content-MD5, Content-Type, If-Match, If-None-Match, X-CUST-Header1, X-CUST-Header2" \ Access-Control-Expose-Headers "Content-Encoding, Content-Length, Content-MD5, Content-Type, ETag, Location, X-CUST-Header3, X-CUST-Header4" \ Access-Control-Max-Age "3600" event HTTP_REQUEST disable } } I've tried adding "*", "[HTTP::header Origin]" and the actual origin URL to Access-Control-Allow-Origin and tested it with 4 different browsers (FF34, FF38, Opera 29 and Chrome 43). The result is always the same: if the Access-Control-Allow-Origin header would match I get an error in the developer console ("F12" in most browsers), that the header is missing. But! You can see the header in the response headers and the XHR seems to work! See screenshot: If I put some random URL into the header the developer console says that the header does not match. (Before the loadbalancer I had Apache to set the headers, that way I had no CORS error in the developer console of the browsers - but I had some other problems.) Has anybody encountered this? Firmware: 11.5.1-HF8369Views0likes1CommentAdding CORS response headers
Hey all, There are a number of other older (2013-era) threads about CORS headers, and I want to ask a specific question which has not been asked there: Can I add a response header using HTTP::header insert within an HTTP_REQUEST? In at least one CORS-related thread (https://devcentral.f5.com/questions/cors-irule-query), this is shown happening. However, in another thread (https://devcentral.f5.com/questions/access-control-allow-origin-on-f5) the answer includes code in the HTTP_REQUEST to set a variable and then in the HTTP_RESPONSE, a check is made on that variable and if it is set, the HTTP::header insert is used. Basically, I want to include all my CORS-related code in one place. Currently, I am doing basic CORS (adding the ACAO header for GET/POST requests from my domain where the Origin request header is present) using my CDN (Akamai) and I have this iRule for CORS preflight responses: when HTTP_REQUEST { if { ( [HTTP::method] equals "OPTIONS" ) and ( [HTTP::host] contains "mysite.com"] ) and ( [HTTP::header] exists "Access-Control-Request-Method") } { HTTP::respond 200 Access-Control-Allow-Origin "[HTTP::header Origin]" \ Access-Control-Allow-Methods "POST, GET, OPTIONS" \ Access-Control-Allow-Headers "[HTTP::header Access-Control-Request-Headers]" \ Access-Control-Max-Age "86400" return } } However, for simplification, I want to put all the CORS stuff (basic and preflight) in the iRule. So my question is, will this work: when HTTP_REQUEST { CORS preflight OPTIONS requests if { ( [HTTP::method] equals "OPTIONS" ) and ( [HTTP::host] contains "mysite.com"] ) and ( [HTTP::header] exists "Access-Control-Request-Method") } { HTTP::respond 200 Access-Control-Allow-Origin "[HTTP::header Origin]" \ Access-Control-Allow-Methods "POST, GET, OPTIONS" \ Access-Control-Allow-Headers "[HTTP::header Access-Control-Request-Headers]" \ Access-Control-Max-Age "86400" return } CORS GET/POST requests if { ( [HTTP::method] equals "GET" or [HTTP::method] equals "POST") and ( [HTTP::host] contains "mysite.com"] ) and ( [HTTP::header] exists "Origin") } { HTTP::header insert Access-Control-Allow-Origin "[HTTP::header Origin]" } } or do I need this: when HTTP_REQUEST { CORS preflight OPTIONS requests if { ( [HTTP::method] equals "OPTIONS" ) and ( [HTTP::host] contains "mysite.com"] ) and ( [HTTP::header] exists "Access-Control-Request-Method") } { HTTP::respond 200 Access-Control-Allow-Origin "[HTTP::header Origin]" \ Access-Control-Allow-Methods "POST, GET, OPTIONS" \ Access-Control-Allow-Headers "[HTTP::header Access-Control-Request-Headers]" \ Access-Control-Max-Age "86400" return } CORS GET/POST requests if { ( [HTTP::host] contains "mysite.com"] ) and ( [HTTP::header] exists "Origin") } { set cors_origin [HTTP::header Origin] } } when HTTP_RESPONSE { CORS GET/POST response - check variable set in request if { [info exists cors_origin] } { HTTP::header insert Access-Control-Allow-Origin $cors_origin } } Does this make sense, or am I getting too complex?Solved8.6KViews0likes13CommentsProblem with doubly-quoted string
This is related to this previous question I asked: https://devcentral.f5.com/questions/adding-cors-response-headers I am now having a separate problem related to a new version of sample code in that thread, which was trying to return CORS headers automatically. Here's the problem fragment: if { ( [HTTP::method] equals "OPTIONS" ) and ( [HTTP::host] contains "example.com"] ) and ( [HTTP::header] exists "Access-Control-Request-Method") } { HTTP::respond 200 "Access-Control-Allow-Origin" "[HTTP::header Origin]" "Access-Control-Allow-Methods" "POST, GET, OPTIONS" "Access-Control-Allow-Headers" "[HTTP::header Access-Control-Request-Headers]" "Access-Control-Max-Age" "86400" } elseif { ( [HTTP::host] contains "example.com"] ) and ( [HTTP::header] exists "Origin") } { CORS GET/POST requests - set cors_origin variable set cors_origin [HTTP::header Origin] } As you can see, each of the CORS response header names in the second line is enclosed in double-quotes, so the iRule treats them as strings. However, when I try to deploy the iRule that contains this fragment, it fails, and I'm not sure why. Could the problem be this bit: "Access-Control-Allow-Headers" "[HTTP::header Access-Control-Request-Headers]" Could the iRule think that Access-Control-Request-Headers is not a string? If so, what's the solution? Can I have a string within a string - I'm assumign this isn't valid: "Access-Control-Allow-Headers" "[HTTP::header "Access-Control-Request-Headers"]"462Views0likes2CommentsCORS implementation
Problem this snippet solves: Pretty self-explanatory - we had to implement CORS (Cross-Origin-Resource-Sharing) where we had multiple domains, all of which had to be able to make AJAX calls to API's in our 'api.example.com' subdomain. Additionally, we had some partners who also need to be able to call our API's. In some cases, we had to pass cookies in the request. In the past, various developers had created backend Java code to return the CORS response headers, but almost invariably they did an incomplete job - either returning an invalid value or not returning all the required headers or writing the code such that it wasn't portable across applications. Therefore, I decided to write some 'common' CORS handling code, which would have the benefit of doing 'proper' origin checking and would also immediately return the OPTIONS preflight response directly from F5, thus improving performance. After much hacking around, here is what I came up with. We used a class to define multiple top-level domains as 'allowed' origins - this would contain both your domains and also those of any partners whom you want to allow to make CORS requests to your site. If you just have multiple subdomains on a single domain (e.g. www.example.com, api.example.com, code.example.com), you could simply use [HTTP::header Origin] ends_with ".example.com" - it's a little simpler. I'm always returning the Access-Control-Allow-Credentials: true response header for 'valid' non-OPTIONS (e.g. GET/POST) CORS requests, even if it's not required (i.e. even if the withCredentials flag was not set in the request) - unfortunately, there is no way to know whether it is needed simply by looking at the request, so it's the only way to ensure client errors don't occur. I'm passing the value of the Access-Control-Request-Method request header in the Access-Control-Allow-Methods response header (e.g. a single value of 'GET' or 'POST' or whatever) - in most implementations, you'll see people returning somethign like a string like Access-Control-Allow-Methods: GET, POST, PUT, but there's really no significant benefit to doing this - much simpler to only return what is passed. In either case, it will be cached by the browser because of the Access-Control-Max-Age response header. Note that because you will be returning a specific Access-Control-Allow-Origin value, rather than '*', you should also return the Vary: Origin response header. This may have issues with browser caching or if you use a CDN like Akamai or Cloudflare - you should consult any CDN product documentation. There are multiple good sources for explaining the Vary header - Google is your friend. If anyone has any comments, please add them, good or bad! I would love to know if someone finds this snippet useful... Code : # Domains that are allowed to make cross-domain calls to example.com class allowed_origins { ".example.com" ".example2.com" ".goodpartner.com" } when HTTP_REQUEST { unset -nocomplain cors_origin if { [class match [HTTP::header Origin] ends_with allowed_origins] } { if { ( [HTTP::method] equals "OPTIONS" ) and ( [HTTP::header exists "Access-Control-Request-Method"] ) } { # CORS preflight request - return response immediately HTTP::respond 200 "Access-Control-Allow-Origin" [HTTP::header "Origin"] \ "Access-Control-Allow-Methods" [HTTP::header "Access-Control-Request-Method"] \ "Access-Control-Allow-Headers" [HTTP::header "Access-Control-Request-Headers"] \ "Access-Control-Max-Age" "86400" \ "Vary" "Origin" } else { # CORS GET/POST requests - set cors_origin variable set cors_origin [HTTP::header "Origin"] } } } when HTTP_RESPONSE { # CORS GET/POST response - check cors_origin variable set in request if { [info exists cors_origin] } { HTTP::header insert "Access-Control-Allow-Origin" $cors_origin HTTP::header insert "Access-Control-Allow-Credentials" "true" HTTP::header insert "Vary" "Origin" } } Tested this on version: 11.09KViews2likes20CommentsHEIST Vulnerability – Overview and BIG-IP Mitigation
An interesting topic was talked about in the recent Black Hat conference. It is a new attack called HEIST (HTTP Encrypted Information can be Stolen through TCP-windows) which demonstrates how to extract sensitive data from any authenticated cross-origin website. What makes this attack unique is the ability to execute without any sort of traffic eavesdropping or man-in-the-middle scenarios. The attack happens in the browser, upon visiting an attacker-controlled website. Basics of a HEIST The HEIST attack, as described by Leuven University researchers Mathy Vanhoef and Tom Van Goethem, makes use of a new browser feature called Service Workers and specifically a new interface called Fetch API. The Fetch API, much like XMLHttpRequest (XHR), allows for arbitrary requests to be sent from the browser. These requests may also include sensitive authorization information such as session cookies. It is obviously not so trivial to read the responses from requests sent by Fetch API or XHR, due to the Same-origin Policy (SOP) enforced by the browser. However, it may be possible to use side channel attacks to infer information about the size of the response and in certain circumstances even extract personal data. No Empty Promises The attack uses the Fetch API and its performance measuring tool. Shortly after an arbitrary request is sent using Fetch API, the browser creates a Promise object in the DOM. This object is created once the browser starts receiving data from the server. A “responseEnd” attribute is added to the object once the browser fully receives the entire data. The “patent” of the attack is knowing whether the response consisted of either one TCP packet, or more. That is by measuring the time between the Promise object creation and “responseEnd”. This allows the attacker to detect an approximate size of any page, as it appears to the victim. For pages that reflect user-input data, the attacker may detect the exact size of the response. Can I (Ab)Use? Service Workers are supported in the following browsers: This table shows that a rather large majority of browsers in the market today already support Service Workers. The trend is expected to grow as Service Workers are useful with creating dynamic and responsive web applications. Source: http://caniuse.com/#feat=serviceworkers Call the Police! In this section we’ll go over possible mitigations, including solutions available for BIG-IP users. Disable third-party cookies The researchers list disabling third-party cookies as the only real mitigation for this attack. By disabling this functionality, the browser won’t send authorization information in Fetch API and XHR requests made to cross-origin domains. Pros: Completely disables the attack. Cons: The setting happens in the browser. Web servers cannot enforce this setting upon users. Also, it is unclear what functionality may be hampered by disabling third-party cookies. Applying data in varying lengths to responses The researchers also list this action as a possible mitigation. The idea is to add data at random lengths to every response. This will considerably affect the attacker’s ability to understand what is the actual response length. The original attack requires up to 14 requests in order to detect the exact response length. By adding random data in different possible lengths, the attacker may have to work much harder and be more aggressive towards the web server. The following is an iRule that adds this functionality to BIG-IP virtual servers: when HTTP_RESPONSE { set sRandomString {} set iLength [expr {int(rand() * 1000 + 1)}] for {set i 0} {$i < $iLength} {incr i} { set iRandomNum [expr {int(rand() * 62)}] if {$iRandomNum < 10} { incr iRandomNum 48 } elseif {$iRandomNum < 36} { incr iRandomNum 55 } else { incr iRandomNum 61 } append sRandomString [format %c $iRandomNum] } HTTP::header insert X-HEIST $sRandomString log local0. "Added random header X-HEIST: $sRandomString" } This iRule will add a random string as a response header called “X-HEIST”. The string length ranges between 1 and 1000 chars. Pros: Adds significant complexity to the attack, possibly until the point that it is no longer feasible. Cons: Doesn’t completely shut down the vulnerability. In some cases, where the exact response length isn’t interesting to the attacker – this approach alone may be less effective. Block unknown origins Fetch API and XHR requests often add a request header that describes from which domain the request originated. For example, an XHR request in a script that runs on “http://attacker.com” will add the following request header: Origin: attacker.com The Origin header is not meant to be used as an access list for security needs. However, it is generally good practice to only allow known domains to be able to send Fetch API or XHR requests. This configuration is available in BIG-IP ASM (version 11.5.0 and up), under Security >> Application Security : URLs : Allowed URLs : Allowed HTTP URLs >> Allowed HTTP URL Properties: Pros: A request with an unknown Origin will be blocked by ASM, disallowing the browser from performing this attack. Cons: It may be challenging for website admins to create an allowlist of accepted domains. For public APIs it is often desired to allow all origins. In addition, there are some cases where the Origin header isn’t added to the request. Web Scraping protection Enabling Web Scraping protection in ASM may prevent this attack. Web Scraping protection is configurable under Security >> Application Security : Anomaly Detection : Web Scraping. Combining this protection with the iRule mentioned above creates adequate mitigation for this attack. By adding length randomization, the amount of requests the attacker must send is significantly increased. This will trigger Web Scraping detection in ASM once it is enabled. Furthermore, during the attack period the browser will fail answering the JavaScript challenges sent by ASM and therefore not receive the desired result from the server. Conclusion The HEIST attack is a unique and original form of attack. It uses legitimate functionality like cross-origin requests, and is based on known variables such as TCP slow start algorithm defaults. The attack uses side channel to retrieve data from cross-origin sources, despite the SOP protection found in browsers. As the researchers claim, the only real effective mitigation to this attack is disabling third-party cookies in the browser. However, using ASM and iRules we’ve shown that it’s possible to effectively mitigate this 0-day vulnerability using the tools and protections already found in BIG-IP.532Views0likes0CommentsCORS control with ASM
Hi All, Good day. I have a few questions need your expert advice: i have a F5 NLB that host a virtual server as an reverse proxy in the web tier of my 3 tier system. My actual website hosted in my App tier using IIS 8.5, with CORS ext. installed and configured. However, recent VA scan on my system shows that my system did not restrict the CORS properly and allow "access-control-allow-origin" to any hosts. Now, i understand that F5 has an ASM module to enforce security on URLs like CORS but unfortunately my infra team did not purchase the license for this module. May i know, without ASM, does it mean the F5 will overwrite my website response header despite my IIS had restricted the origin? thank you!324Views0likes1CommentCORS iRule Problem
I'm having a lot of trouble setting CORS headers and I'm hoping someone with more familiarity can help me out. This is my first time working with CORS, in fact until a few days ago I had never even heard of it. After some reading, my understanding is that CORS is a way to prevent a webpage from referencing another webpage. So I have a page, we'll call it siteA, that gets some dynamic data from another webpage, siteB (both are internal pages) and my understanding is that siteB will not talk to siteA unless siteA presents a CORS header with a value of siteA.domain.com; is this even the correct interpretation of how this is supposed to work? DevCentral keeps marking as spam so I might end up posting a partial explanation545Views0likes4Comments