Security Headers are http header, which set additional limitations for a overall higher security when it comes to common attack mechanisms like Cross Site Scripting (XSS), Clickjacking or MIME-Sniffing. A part of most of todays pentest tools is scanning these headers and grading into a list. That’s why I’m often jumping into discussions with customers CISO. The easiest way to verify your results is using securityheaders.com (formerly securityheaders.io)
I want to give you some insights when it comes to configure your headers for a Citrix ADC setup, when using a Gateway vServer with (aka advanced auth) and without (aka basic auth) AAA.
Starting from Citrix ADC release 13.0 build 76.29, the Content-Security-Policy (CSP) response header is supported for Citrix Gateway and AAA vServer-generated responses. By default, the CSP header is disabled. The command is enabling an aaa parameter, which is also effective for Gateway vServer. See below why I wouldn’t recommend the default setting.
First an important note when you’re experimenting with the following headers (eg binding and unbinding new rewrite policies) is cache, cache and cache! You can use ADC’s command flush cache contentgroup loginstaticobjects but the scanning pages like securityheaders or Mozilla’s Observatory are also using cached results. Don’t be impatient and bring some time for this topic.
This is how the report looks like for a typically default Citrix Gateway vServer – it doesn’t matter if linked to an authentication Profile with AAA vServer – or used directly with basic authentication. The report is based on an actual 13.0 build:
Now I will enable the new included CSP and flush the cache (you don’t have to use or license Integrated Caching, so the warning about a missing feature is OK) of the loginpages by running the following commands:
set aaa parameter -defaultCSPHeader enable flush cache contentgroup loginstaticobjects
Which includes the following CSP header after a rescan:
That’s definitely a good run from Citrix, as this default CSP isn’t that bad – but you’re able to set some higher security points – so I don’t recommend to enable the defaultCSPHeader command. Maybe that’s why the default one’s from Citrix are disabled by default.
StoreFront Receiver / Workspace App client detection
The most occurred problem when http header for higher security were implemented on customer ICA Proxy’s is the afterwards non-functioning Citrix StoreFront Receiver / Workspace App client detection, as nothing will happen when clicking on the detection button. The .ica file gets downloaded but isn’t auto-started with your local installed Workspace App, that may be confusing for some Users.
So I’ve questioning myself, how’s the client detection working? What’s happening technically in background?
There are three requests (initiated by jQuery) to StoreFront, which are responsible for the detection and are processed in the following sequence:
Citrix’ new default CSP header is adding their well known client-applications like Secure Access, the older one called Gateway-Plugin, EPA and also third-party like the VMware Horizon View client – But they forgot their own mostly used client engine – the Citrix Workspace App! That’s because I’ve added receiver://* to the list of acceptable clients. And voilà, the client detection is working, again.
Differences when using AAA without Gateway
As ADC’s AAA is also often used to protect and preauth web-apps – so not the common Citrix Gateway ICA Proxy config – I also have some notes when securing AAA vServer.
First thing which is different is the limitation when binding rewrite policies to an AAA vServer, as there is only support for AAA_Response type.
What’s the biggest limitation with AAA_Response types? You aren’t able to bind policies with configured http response header (HTTP.RES) expressions. That’s why we have to rethink and rebuild our http security header for an “Only-AAA” setup. Also, the expressions are much more detailed, as you have to insert all your web-app FQDN’s and third-party apps / plugins, too. Otherwise the high security in CSP will break your apps. I’m in development but this needs some more investigation, that’s why I decided to publish this in Part2, soon.
Putting it all together
Basically here is my actual script for configuring security headers both on Gateway vServer AND potentially linked AAA vServer. Below some details, as I will update this post when there are new or deprecated headers.
Last update 28.08.2022
- The script includes three new headers, which aren’t impacting the securityheaders.com grade as of now:
- Cross-Origin-Embedder-Policy (COEP)
- Cross-Origin-Opener-Policy (COOP)
- Cross-Origin-Resource-Policy (CORP)
- The script doesn’t configure the Strict-Transport-Security (HSTS) header, as you are able to configure this on SSL Settings or SSL Profile:
- Enable HSTS and set the Max-Age to 31536000
- Enable Include Subdomains
- The script is deleting ADC’s default Feature-Policy header, which includes camera ‘none’; microphone ‘none’; geolocation ‘none’ – as this header is deprecated and renamed to Permissions Policy.
- The script isn’t doing anything regarding the header X-XSS-Protection, as it is set to 1 by ADC, the recommended value is 1; mode=block – but this header is soon going to be deprecated, as Content-Security-Policy will be the replacement for modern browsers.
- The script is creating a customized Content-Security-Policy (CSP) header, which is a combination of the new default one and also including images and scripts to run only from specified sources. The URLs should include all of your Gateway and AAA vServer FQDN’s. I validated the following configured features:
- ICA Proxy (Workspace App, Client Detection, HTML5)
- SSL VPN
- AlwaysOn VPN (Auto Machine,- & User-Tunnel)
- EPA Scan
- RDP Proxy
- NativeOTP & PushOTP
#script for advanced security headers, scan with securityheaders.com #source https://www.julianjakob.com/citrix-adc-latest-insights-about-security-headers/ #replace https://gateway.customer.com with your GW vServer Public-FQDN #replace GW_vServer with your Citrix Gateway vServer Name ######################################################################### enable ns feature REWRITE add rewrite action rw_act_insert_Content_security_policy insert_http_header Content-Security-Policy "\"default-src 'self'; script-src https://www.google.com/recaptcha/api.js https://www.gstatic.com/recaptcha/releases/ https://gateway.customer.com 'self' https://gateway.customer.com 'unsafe-inline' 'unsafe-eval'; connect-src 'self'; img-src http://localhost:* https://gateway.customer.com 'self' data: http: https:; style-src 'self' 'unsafe-inline'; font-src 'self' data:; frame-src https://www.google.com/recaptcha/ com.citrix.agmacepa://* receiver://* citrixng://* com.citrix.nsgclient://* vmware-view:// nsgcepa://* application://* 'self'; child-src 'self' com.citrix.agmacepa://* receiver://* citrixng://* com.citrix.nsgclient://* vmware-view:// nsgcepa://nsgcepa application://*; form-action 'self'; object-src 'none'; report-uri /nscsp_violation/report_uri\"" add rewrite action rw_act_insert_Expect_CT_Header insert_http_header Expect-CT "\"enforce,max-age=30\"" add rewrite action rw_act_delete_FeaturePolicy delete_http_header Feature-Policy add rewrite action rw_act_remove_Server delete_http_header Server add rewrite action rw_act_insert_Permissions_Policy insert_http_header Permissions-Policy "\"vibrate=(self), sync-xhr=(self \'https://gateway.customer.com\')\"" add rewrite action rw_act_insert_Cross-Origin-Embedder-Policy insert_http_header Cross-Origin-Embedder-Policy "\"require-corp\"" add rewrite action rw_act_insert_Cross-Origin-Opener-Policy insert_http_header Cross-Origin-Opener-Policy "\"same-origin\"" add rewrite action rw_act_insert_Cross-Origin-Resource-Policy insert_http_header Cross-Origin-Resource-Policy "\"same-origin\"" add rewrite policy rw_pol_insert_Content_security_policy TRUE rw_act_insert_Content_security_policy add rewrite policy rw_pol_enforce_Expect_CT TRUE rw_act_insert_Expect_CT_Header add rewrite policy rw_pol_remove_FeaturePolicy "HTTP.RES.HEADER(\"Feature-Policy\").EXISTS" rw_act_delete_FeaturePolicy add rewrite policy rw_pol_remove_Server "HTTP.RES.HEADER(\"Server\").EXISTS" rw_act_remove_Server add rewrite policy rw_pol_insert_Permissions_Policy "HTTP.RES.HEADER(\"Permissions-Policy\").EXISTS.NOT" rw_act_insert_Permissions_Policy add rewrite policy rw_pol_insert_Cross-Origin-Embedder-Policy TRUE rw_act_insert_Cross-Origin-Embedder-Policy add rewrite policy rw_pol_insert_Cross-Origin-Opener-Policy TRUE rw_act_insert_Cross-Origin-Opener-Policy add rewrite policy rw_pol_insert_Cross-Origin-Resource-Policy TRUE rw_act_insert_Cross-Origin-Resource-Policy bind vpn vserver GW_vServer -policy rw_pol_insert_Content_security_policy -priority 100 -gotoPriorityExpression NEXT -type RESPONSE bind vpn vserver GW_vServer -policy rw_pol_enforce_Expect_CT -priority 110 -gotoPriorityExpression NEXT -type RESPONSE bind vpn vserver GW_vServer -policy rw_pol_remove_FeaturePolicy -priority 120 -gotoPriorityExpression NEXT -type RESPONSE bind vpn vserver GW_vServer -policy rw_pol_remove_Server -priority 130 -gotoPriorityExpression NEXT -type RESPONSE bind vpn vserver GW_vServer -policy rw_pol_insert_Permissions_Policy -priority 140 -gotoPriorityExpression NEXT -type RESPONSE bind vpn vserver GW_vServer -policy rw_pol_insert_Cross-Origin-Embedder-Policy -priority 150 -gotoPriorityExpression NEXT -type RESPONSE bind vpn vserver GW_vServer -policy rw_pol_insert_Cross-Origin-Opener-Policy -priority 160 -gotoPriorityExpression NEXT -type RESPONSE bind vpn vserver GW_vServer -policy rw_pol_insert_Cross-Origin-Resource-Policy -priority 170 -gotoPriorityExpression NEXT -type RESPONSE flush cache contentgroup loginstaticobjects save config
After running the script you will get this result:
The following warning will popup, as Citrix is using unsafe-inline and unsafe-eval scripts for the Gateway loginpage – Citrix is aware of that and I hope there will soon be some changes in newer 13.x builds
Because of this warning, the grade is capped at A.
This topic will be updated again and again, as there will be soon released further security headers by W3C. It’s time consuming, but always worth it to be on the safe side.
Please don’t hesitate to contact me or comment below, if you run into any issues or new findings with my script.
Thank you very much for all the detail. I have implemented what you have but instead of a Gateway VIP I am applying as rewrite response policies to Content Switching and AAA VIP’s. The AAA VIP’s don’t like the header delete policies but they take everything else (I get “Policy cannot be bound to specified policy label [HTTP.RES & HTTP response header]”)
Unfortunately the highest I am scoring is a B. I did an nstrace and looked at it and I see my header insertions in a 302 object moved HTTP packet but the 200 OK packet below it I do not see the header insertions. The CSP content that the securityheaders site shows me only show the default Citrix CSP content and not the custom ones I added with the rewrite as well as the Cross-Origin* headers in your article that I inserted don’t show up either on the results page. I’m opening a ticket with Citrix support but not sure I’m going to get very far.
Great article Julian! I would add X-Powered-By to the list of removed headers, I know NetScaler Gateway doesn’t send that one in responses, but it’s commonly used with web servers and somewhat comparable to the Server header and it tells even more than server header.
It’s interesting the Citrix Cloud Gateway seems to lack Referrer-Policy and Permissions-Policy in its responses btw.