Citrix ADC – Latest Insights about Security Headers

Reading Time: 6 minutes

Overview

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.

Report Summary

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:

Default report without config on Gateway vServer

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:

Content-Security-Policy response header after enabling the new default

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.

Configuration

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?

Citrix Workspace app client detection

There are three requests (initiated by jQuery) to StoreFront, which are responsible for the detection and are processed in the following sequence:

  1. https://gateway.customer.com/Citrix/StoreWeb/ClientAssistant/GetDetectionTicket
  2. receiver://gateway.customer.com/Citrix/Store/clientAssistant/reportDetectionStatus
  3. https://gateway.customer.com/Citrix/StoreWeb/ClientAssistant/GetDetectionStatus

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.

AAA_Response rewrite policies to AAA vServer

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:

Result after running the script

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

CSP warnings after implementation of the script

Because of this warning, the grade is capped at A.

Summary

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.

Leave a Reply

Your email address will not be published.