06-21-2021 08:05 PM
I have a fresh community7.0 installation via zip distribution and ansible.
When enable SSL in /etc/nginx/conf.d/, the alfresco orange login page loads securely (https), but when I attempt to authenticate, I see the following CSRF errors in alfresco.log.
2021-06-21 15:01:47,561 ERROR [alfresco.web.site] [http-nio-8080-exec-10] javax.servlet.ServletException: Possible CSRF attack noted when asserting referer header 'https://alfresco.domain.com/share/page/'. Request: POST /share/page/dologin, FAILED TEST: Assert referer POST /share/page/dologin :: referer: 'https://alfresco.domain.com/share/page/' vs server & context: http://127.0.0.1:8080/ (string) or (regexp)
Is this something I need to fix in nginx config, alfresco.properties, or web-extension xml?
/etc/nginx/conf.d/alfresco.conf:
server { access_log /var/log/alfresco/access.log; error_log /var/log/alfresco/error.log error; listen 443 ssl; listen [::]:443 ssl;
server_name alfresco.domain.com; ssl_certificate /etc/certs/server.crt; ssl_certificate_key /etc/certs/server.key; ssl_session_cache shared:SSL:1m; ssl_session_timeout 5m; client_max_body_size 0; set $allowOriginSite *; proxy_pass_request_headers on; proxy_pass_header Set-Cookie; # Protect access to SOLR APIs location ~ ^(/.*/service/api/solr/.*)$ {return 403;} location ~ ^(/.*/s/api/solr/.*)$ {return 403;} location ~ ^(/.*/wcservice/api/solr/.*)$ {return 403;} location ~ ^(/.*/wcs/api/solr/.*)$ {return 403;} location ~ ^(/.*/proxy/.*/api/solr/.*)$ {return 403 ;} location ~ ^(/.*/-default-/proxy/.*/api/.*)$ {return 403;} # Protect access to Prometheus endpoint location ~ ^(/.*/s/prometheus)$ {return 403;} location / { proxy_pass http://127.0.0.1:8080; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass_header Set-Cookie; proxy_set_header X-Forwarded-Proto https; } # External settings, do not remove #ENV_ACCESS_LOG location /share/ { proxy_pass http://127.0.0.1:8080; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass_header Set-Cookie; proxy_set_header X-Forwarded-Proto https; } location /alfresco/ { proxy_pass http://127.0.0.1:8080; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass_header Set-Cookie; proxy_set_header X-Forwarded-Proto https; } location /api-explorer/ { proxy_pass http://127.0.0.1:8080; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass_header Set-Cookie; proxy_set_header X-Forwarded-Proto https; } }
06-22-2021 03:57 PM
Much thanks Afaust!
Here is my now working SSL configuration through haproxy, Nginx, and alfresco/content-services!
/etc/nginx/conf.d/alfresco.conf:
...snip... listen 443 ssl; listen [::]:443 ssl; server_name alfresco.domain.com; ssl_certificate /etc/certs/server.crt; ssl_certificate_key /etc/certs/server.key; ssl_session_cache shared:SSL:1m; ssl_session_timeout 5m; ...snip... location /share/ { proxy_pass http://127.0.0.1:8080; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-NginX-Proxy true; proxy_set_header Host $http_host; proxy_set_header Upgrade $http_upgrade; proxy_pass_header Set-Cookie; proxy_set_header X-Forwarded-Proto https; } ...snip...
/etc/opt/alfresco/content-services/classpath/alfresco-global.properties:
...snip...
# CSRF filter overrides
csrf.filter.enabled=true
csrf.filter.referer=^https?://alfresco\.domain\.com(/.*)?
csrf.filter.referer.always=false
csrf.filter.origin=^https?://alfresco\.domain\.com(/.*)?
csrf.filter.origin.always=false
...snip...
/etc/opt/alfresco/content-services/classpath/alfresco/web-extension/share-config-custom.xml:
...snip...
<properties> <!-- There is normally no need to override this property --> <token>Alfresco-CSRFToken</token> <!-- Override and set this property with a regexp that if you have placed Share behind a proxy that does not rewrite the Referer header. --> <referer>^https?://alfresco\.domain\.com(/.*)?</referer> <!-- Override and set this property with a regexp that if you have placed Share behind a proxy that does not rewrite the Origin header. --> <origin>^https?://alfresco\.domain\.com(/.*)?</origin> </properties>
...snip...
06-22-2021 04:00 AM
This has not much do to with your nginx config. Rather your CSRF configuration in Alfresco is incomplete, missing the CSRF referrer / origin patterns for your public URL. In Share this is done via the share-config-custom.xml by setting the CSRFPolicy's origin/referrer sub-elements. In ACS Repository, this is done via alfresco-global.properties by setting the appropriate referrer/origin properties.
06-22-2021 12:48 PM
I tried setting "csrf.filter.enabled=false" in my global properties file with no success so I tried my best to add the needed settings to make it work but that also was unsuccessful. 😞
My Environment is Community7 behind HAPROXY which then forwards the https traffic to NGINX which then forwards that to community7 on my private network.
host1= HAPROXY: https://alfresco.domain.com
host2= NGINX: https://alfresco.dmz.domain.com
host2= ALFRESCO http://127.0.0.1:8080/share
I have csrf.filter(s) set in my properties file
/etc/opt/alfresco/content-services/classpath/alfresco-global.properties:
...
# CSRF filter overrides csrf.filter.enabled=enabled csrf.filter.referer=https://alfresco.dmz.domain.com/.* csrf.filter.referer.always=false csrf.filter.origin=https://alfresco.dmz.domain.com csrf.filter.origin.always=false
...
HOWEVER, I'm not familiar share-config-custom.xml syntax or positioning the CSRF settings in the correct location of the xml code.
This is what I have uncommented out but I still see CSRF errors in my share.log...
/etc/opt/alfresco/content-services/classpath/alfresco/web-extension/share-config-custom.xml:
...
<!-- CSRF filter config to mitigate CSRF/Seasurfing/XSRF attacks To disable the CSRF filter override the <filter> to not contain any values, see share-config-custom.xml for an example. If you have a custom resource(s) that a client POST to that can't accept a token, for whatever reason, then make sure to copy the entire CSRFPolicy config and place it in your share-config-custom.xml file with the replace="true" attribute and make sure to add a new <rule> in the top of the <filter> element, which has a <request> element matching your requests, and uses only the "assertReferer" & "assertOrigin" actions. I.e.
--> <rule> <request> <method>POST</method> <path>/proxy/alfresco/custom/repoWebscript/withoutParams|/service/custom/shareResource/thatMayHaveParams(\?.+)?</path> </request> <action name="assertReferer"> <param name="referer">{referer}</param> </action> <action name="assertOrigin"> <param name="origin">{origin}</param> </action> </rule> <config evaluator="string-compare" condition="CSRFPolicy" replace="true"> <!-- Properties that may be used inside the rest of the CSRFPolicy config to avoid repetition but also making it possible to provide different values in different environments. I.e. Different "Referer" & "Origin" properties for test & production etc. Reference a property using "{propertyName}". --> <properties> <!-- There is normally no need to override this property --> <token>Alfresco-CSRFToken</token> <!-- Override and set this property with a regexp that if you have placed Share behind a proxy that does not rewrite the Referer header. --> <referer>alfresco.dmz.domain.com</referer> <!-- Override and set this property with a regexp that if you have placed Share behind a proxy that does not rewrite the Origin header. --> <origin>alfresco.dmz.domain.com</origin> </properties> <!-- Will be used and exposed to the client side code in Alfresco.contants.CSRF_POLICY. Use the Alfresco.util.CSRFPolicy.getHeader() or Alfresco.util.CSRFPolicy.getParameter() with Alfresco.util.CSRFPolicy.getToken() to set the token in custom 3rd party code. --> <client> <cookie>{token}</cookie> <header>{token}</header> <parameter>{token}</parameter> </client>
...
06-22-2021 02:46 PM
You need to set the public base URL that users will use as the referrer / origin in the CSRF policy section, so if they go through HAProxy, then that would be https://alfresco.domain.com. Note that technically, referrer and origin are regular expressions, so the technically correct values would be
https://alfresco\.domain\.com(/.*)?
Also note that you do not need to uncomment / use the whole CSRF policy section. It is completely sufficient to use
<config evaluator="string-compare" condition="CSRFPolicy" replace="true"> <properties> <token>Alfresco-CSRFToken</token> <referer>https://alfresco\.domain\.com(/.*)?</referer> <origin>https://alfresco\.domain\.com(/.*)?</origin> </properties> </config>
06-22-2021 03:57 PM
Much thanks Afaust!
Here is my now working SSL configuration through haproxy, Nginx, and alfresco/content-services!
/etc/nginx/conf.d/alfresco.conf:
...snip... listen 443 ssl; listen [::]:443 ssl; server_name alfresco.domain.com; ssl_certificate /etc/certs/server.crt; ssl_certificate_key /etc/certs/server.key; ssl_session_cache shared:SSL:1m; ssl_session_timeout 5m; ...snip... location /share/ { proxy_pass http://127.0.0.1:8080; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-NginX-Proxy true; proxy_set_header Host $http_host; proxy_set_header Upgrade $http_upgrade; proxy_pass_header Set-Cookie; proxy_set_header X-Forwarded-Proto https; } ...snip...
/etc/opt/alfresco/content-services/classpath/alfresco-global.properties:
...snip...
# CSRF filter overrides
csrf.filter.enabled=true
csrf.filter.referer=^https?://alfresco\.domain\.com(/.*)?
csrf.filter.referer.always=false
csrf.filter.origin=^https?://alfresco\.domain\.com(/.*)?
csrf.filter.origin.always=false
...snip...
/etc/opt/alfresco/content-services/classpath/alfresco/web-extension/share-config-custom.xml:
...snip...
<properties> <!-- There is normally no need to override this property --> <token>Alfresco-CSRFToken</token> <!-- Override and set this property with a regexp that if you have placed Share behind a proxy that does not rewrite the Referer header. --> <referer>^https?://alfresco\.domain\.com(/.*)?</referer> <!-- Override and set this property with a regexp that if you have placed Share behind a proxy that does not rewrite the Origin header. --> <origin>^https?://alfresco\.domain\.com(/.*)?</origin> </properties>
...snip...
Explore our Alfresco products with the links below. Use labels to filter content by product module.