Protect Against CSRF Attacks

In a Cross Site Request Forgery (CSRF) attack, a user unknowingly executes a malicious request on a website where they are authenticated. A CSRF attack usually includes a link or script in a web page. When a user accesses the link or script, the page executes an HTTP request on the site where the user is authenticated.

CSRF attacks interact with HTTP requests as follows:

  • CSRF attacks can execute POST, PUT, and DELETE requests on the targeted server. For example, a CSRF attack can transfer funds out of a bank account or change a user’s password.

  • Because of same-origin policy, CSRF attacks cannot access any response from the targeted server.

When IG processes POST, PUT, and DELETE requests, it checks a custom HTTP header in the request. If a CSRF token is not present in the header or not valid, IG rejects the request and returns a valid CSRF token in the response.

Rogue websites that attempt CSRF attacks operate in a different website domain to the targeted website. Because of same-origin policy, rogue websites can’t access a response from the targeted website, and cannot, therefore, access the response or CSRF token.

The following example shows the data flow when an authenticated user sends a POST request to an application protected against CSRF:

csrf-legit

The following example shows the data flow when an authenticated user sends a POST request from a rogue site to an application protected against CSRF:

csrf-ilegit
Protect Against CSRF Attacks
  1. Set up SSO, so that AM authenticates users to the sample app through IG:

    1. Set up AM and IG as described in Authenticate With SSO Through the Default Authentication Service.

    2. Remove the condition in sso.json, so that the route matches all requests:

      "condition": "${matches(request.uri.path, '^/home/sso')}"
  2. Test the setup without CSRF protection:

    1. Go to http://openig.example.com:8080/bank/index, and log in to the Sample App Bank through AM, as user demo, password Ch4ng31t.

    2. Send a bank transfer of $10 to Bob, and note that the transfer is successful.

    3. Go to http://localhost:8081/bank/attack-autosubmit to simulate a CSRF attack.

      When you access this page, a hidden HTML form is automatically submitted to transfer $1000 to the rogue user, using the IG session cookie to authenticate to the bank.

      In the bank transaction history, note that $1000 has been debited.

  3. Test the setup with CSRF protection:

    1. In IG, replace sso.json with the following route:

      {
        "name": "Csrf",
        "baseURI": "http://app.example.com:8081",
        "heap": [
          {
            "name": "SystemAndEnvSecretStore-1",
            "type": "SystemAndEnvSecretStore"
          },
          {
            "name": "AmService-1",
            "type": "AmService",
            "config": {
              "agent": {
                "username": "ig_agent",
                "passwordSecretId": "agent.secret.id"
              },
              "secretsProvider": "SystemAndEnvSecretStore-1",
              "url": "http://openam.example.com:8088/openam/",
              "version": "7.1"
            }
          },
          {
            "name": "FailureHandler-1",
            "type": "StaticResponseHandler",
            "config": {
              "status": 403,
              "headers": {
                "Content-Type": [ "text/plain" ]
              },
              "entity": "Request forbidden"
            }
          }
        ],
        "handler": {
          "type": "Chain",
          "config": {
            "filters": [
              {
                "name": "SingleSignOnFilter-1",
                "type": "SingleSignOnFilter",
                "config": {
                  "amService": "AmService-1"
                }
              },
              {
                "name": "CsrfFilter-1",
                "type": "CsrfFilter",
                "config": {
                  "cookieName": "iPlanetDirectoryPro",
                  "failureHandler": "FailureHandler-1"
                }
              }
            ],
            "handler": "ReverseProxyHandler"
          }
        }
      }

      Notice the following features of the route compared to sso.json:

      • The CsrfFilter checks the AM session cookie for the X-CSRF-Token header. If a CSRF token is not present in the header or not valid, the filter rejects the request and provides a valid CSRF token in the header.

    2. Go to http://openig.example.com:8080/bank/index, and send a bank transfer of $10 to Alice.

      Because there is no CSRF token, IG responds with an HTTP 403, and provides the token.

    3. Send the transfer again, and note that because the CSRF token is provided the transfer is successful.

    4. Go to http://localhost:8081/bank/attack-autosubmit to automatically send a rogue transfer.

      Because there is no CSRF token, IG rejects the request and provides the CSRF token. However, because the rogue site is in a different domain to openig.example.com it can’t access the CSRF token.