To help prevent CSRF attacks, you can use this policy to create a CSRF filter. For each route that you apply the policy to, the filter checks to make sure that a request’s origin matches its destination. If the origin and destination do not match, a 403 Forbidden error code is returned. Note that because CSRF attacks specifically target state-changing requests, the filter only acts on HTTP requests that have a state-changing method such as POST or PUT.

For more information, see the following resources.

Before you begin

  1. Set up Gloo Mesh Gateway in a single cluster.
  2. Install Bookinfo and other sample apps.
  3. Configure an HTTP listener on your gateway and set up basic routing for the sample apps.

Configure CSRF policies

You can apply a CSRF policy at the route level. For more information, see Applying policies.

Review the following sample configuration file. Continue to the Verify CSRF policies section for example steps on how to check that the CSRF filter is working.

  apiVersion: security.policy.gloo.solo.io/v2
kind: CSRFPolicy
metadata:
  annotations:
    cluster.solo.io/cluster: ""
  name: csrf-policy
  namespace: bookinfo
spec:
  applyToRoutes:
  - route:
      labels:
        route: ratings
  config:
    additionalOrigins:
    - regex: allowThisOne.solo.io
    filterEnabled: true
  

Review the following table to understand this configuration.

SettingDescription
spec.applyToRoutesUse labels to configure which routes to apply the policy to. This example label matches the app and route from the example route table that you apply separately. If omitted and you do not have another selector such as applyToDestinations, the policy applies to all routes in the workspace.
spec.config.additionalOriginsSet any additional origins to allow besides the destination origin. For allowed string matching, see the API reference.
spec.config.filterEnabledSet to true so that the CSRF policy is enforced. Replace with shadowEnabled: true to track metrics but not enforce blocking.

Enable CSRF metrics

  1. To enable CSRF metrics, edit the istio-ingressgateway deployment. If your gateway is in a different namespace, update the command accordingly.
      kubectl edit deploy $(kubectl get deployment -l "app=istio-ingressgateway" -n gloo-mesh-gateways -o jsonpath='{.items[].metadata.name}') -n gloo-mesh-gateways
      
  2. Add the following annotation to the istio-ingressgateway.
      
    spec:
      template:
        metadata:
          annotations:
            proxy.istio.io/config: |
              proxyStatsMatcher:
                inclusionRegexps:
                - .*csrf.*
      

Now, when you port-forward the istio-ingressgateway pod on the Envoy admin port 15000, you can review CSRF metrics. These metrics track the number of valid requests, the number of total invalid requests, and the number of invalid requests due to a missing origin.

  • Continue to the Verify CSRF policies section for example steps on how to check the metrics.
  • For more information about the metrics, see the Envoy docs.

Verify CSRF policies

  1. Update and apply the example CSRF policy in the cluster with the Bookinfo workspace in your example setup.

      kubectl apply -f - << EOF
    apiVersion: security.policy.gloo.solo.io/v2
    kind: CSRFPolicy
    metadata:
      annotations:
        cluster.solo.io/cluster: ""
      name: csrf-policy
      namespace: bookinfo
    spec:
      applyToRoutes:
      - route:
          labels:
            route: ratings
      config:
        additionalOrigins:
        - regex: allowThisOne.solo.io
        filterEnabled: true
    EOF
      
  2. Send a request to the ratings app through the ingress gateway that the route table is attached to. Do not include an origin header in the request. Note that because CSRF attacks specifically target state-changing requests, the filter only acts on HTTP requests that have a state-changing method such as POST or PUT.

    Note that the response is a 403 Forbidden error code because no origin is set.

      HTTP/1.1 403 Forbidden
      
  3. Send the request again. This time, set the origin to a different domain than you used in the policy, such as http://istio.io.

    Note that the response is still a 403 Forbidden error code because the origins do not match.

      HTTP/1.1 403 Forbidden
      
  4. Send the request again. This time, set the origin to match the allowed origin in your CSRF policy.

    Note that the response is successful.

      HTTP/1.1 200 OK
      
  5. If you enabled CSRF metrics, port-forward the istio-ingressgateway pod on the Envoy admin port 15000. If your gateway is in a different namespace, update the command accordingly.

      kubectl port-forward -n gloo-mesh-gateways $(kubectl get pods -l "app=istio-ingressgateway" -n gloo-mesh-gateways -o jsonpath='{.items[].metadata.name}') 15000
      
  6. Open your browser to the localhost stats to review CSRF metrics. In the output, search for csrf.

    • Example metrics:
      http.outbound_0.0.0.0_8443.csrf.request_valid: 1
    http.outbound_0.0.0.0_8443.csrf.request_invalid: 1
    http.outbound_0.0.0.0_8443.csrf.missing_source_origin: 1
      

Cleanup

You can optionally remove the resources that you set up as part of this guide.
  kubectl -n bookinfo delete csrfpolicy csrf-policy