CSRF
Apply a CSRF filter to the gateway to help prevent cross-site request forgery attacks.
About CSRF
According to OWASP, CSRF is defined as follows:
Cross-Site Request Forgery (CSRF) is an attack that forces an end user to execute unwanted actions on a web application in which they’re currently authenticated. With a little help of social engineering (such as sending a link via email or chat), an attacker may trick the users of a web application into executing actions of the attacker’s choosing. If the victim is a normal user, a successful CSRF attack can force the user to perform state changing requests like transferring funds, changing their email address, and so forth. If the victim is an administrative account, CSRF can compromise the entire web application.
To help prevent CSRF attacks, you can enable the CSRF filter on your gateway or a specific route. For each route that you apply the CSRF 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.
POST
or PUT
.Before you begin
-
Follow the Get started guide to install kgateway.
-
Follow the Sample app guide to create a gateway proxy with an HTTP listener and deploy the httpbin sample app.
-
Get the external address of the gateway and save it in an environment variable.
export INGRESS_GW_ADDRESS=$(kubectl get svc -n kgateway-system http -o jsonpath="{.status.loadBalancer.ingress[0]['hostname','ip']}") echo $INGRESS_GW_ADDRESS
kubectl port-forward deployment/http -n kgateway-system 8080:8080
Set up CSRF
Use a TrafficPolicy resource to define your CSRF rules.
-
Create a TrafficPolicy resource to define your CSRF rules. The following example allows request from only the
allowThisOne.example.com
origin.kubectl apply -f- <<EOF apiVersion: gateway.kgateway.dev/v1alpha1 kind: TrafficPolicy metadata: name: csrf namespace: httpbin spec: csrf: percentageEnabled: 100 additionalOrigins: - exact: allowThisOne.example.com ignoreCase: false EOF
Review the following table to understand this configuration. For more information, see the API docs.
Field Description percentageEnabled
The percentage of requests for which the CSRF policy is enabled. A value of 100
means that all requests are enforced by the CSRF rules.additionalOrigins
Additional origins that the CSRF policy allows, besides the destination origin. Possible values include exact
,prefix
,suffix
,contains
,safeRegex
, and anignoreCase
boolean. At least one ofexact
,prefix
,suffix
,contains
, orsafeRegex
must be set. The example allows requests from theallowThisOne.example.com
exact origin. -
Create an HTTPRoute resource for the httpbin app that applies the TrafficPolicy resource that you just created.
kubectl apply -f- <<EOF apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: httpbin-csrf namespace: httpbin spec: parentRefs: - name: http namespace: kgateway-system hostnames: - csrf.example rules: - filters: - type: ExtensionRef extensionRef: group: gateway.kgateway.dev kind: TrafficPolicy name: csrf backendRefs: - name: httpbin port: 8000 EOF
-
Send a request to the httpbin app on the
csrf.example
domain. Verify that you get back a 403 HTTP response code because no origin is set in your request.curl -vi -X POST http://$INGRESS_GW_ADDRESS:8080/post -H "host: csrf.example:8080"
curl -vi -X POST localhost:8080/post -H "host: csrf.example"
Example output:
HTTP/1.1 403 Forbidden ... Invalid origin
-
Send another request to the httpbin app. This time, you include the
allowThisOne.example.com
origin header. Verify that you get back a 200 HTTP response code, because the origin matches the origin that you specified in the TrafficPolicy resource.curl -vi -X POST http://$INGRESS_GW_ADDRESS:8080/post -H "host: csrf.example:8080" -H "origin: allowThisOne.example.com"
curl -vi -X POST localhost:8080/post -H "host: csrf.example" -H "origin: allowThisOne.example.com"
Example output:
HTTP/1.1 200 OK ... { "args": {}, "headers": { "Accept": [ "*/*" ], "Content-Length": [ "0" ], "Host": [ "csrf.example:8080" ], "Origin": [ "allowThisOne.example.com" ], "User-Agent": [ "curl/7.77.0" ], "X-Envoy-Expected-Rq-Timeout-Ms": [ "15000" ], "X-Forwarded-Proto": [ "http" ], "X-Request-Id": [ "b1b53950-f7b3-47e6-8b7b-45a44196f1c4" ] }, "origin": "10.X.X.XX:33896", "url": "http://csrf.example:8080/post", "data": "", "files": null, "form": null, "json": null }
Monitor CSRF metrics
-
Port-forward the gateway proxy.
kubectl port-forward -n kgateway-system deploy/http 19000
-
Open the
/stats
endpoint. -
Find the statistics for
csrf
.Example output:
http.http.csrf.missing_source_origin: 1 http.http.csrf.request_invalid: 0 http.http.csrf.request_valid: 1 ...
missing_source_origin
: The number of requests that were sent without an origin. The number is1
because you sent the first request without an origin.request_invalid
: The number of requests that were sent with an origin that did not match the destination origin. The number is0
because you did not send an invalid request.request_valid
: The number of requests that were sent with an origin that matched the destination origin. The number is1
because you sent a valid request in your second request.
Cleanup
You can remove the resources that you created in this guide.kubectl delete TrafficPolicy csrf -n httpbin
kubectl delete httproute httpbin-csrf -n httpbin