cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
7679
Views
20
Helpful
15
Replies

X-CSRF-TOKEN handling

mikoconn
Cisco Employee
Cisco Employee

Hi,

 

Trying to create an endpoint using the API while CSRF Check is enabled; everything works if that check is disabled.

 

Using Python3, sending a GET request first to 'fetch' the token and then feeding that back into the headers for a POST request to /ers/config/endpoint.

 

Here's my initial GET request and response that works:

 

GET /ers/config/endpointgroup/name/groupGreen HTTP/1.1
Host: 10.81.127.170:9060
Accept-Encoding: identity
accept: application/json
content-type: application/json
authorization: Basic [redacted]
cache-control: no-cache
X-CSRF-TOKEN: fetch
---------------------
Cache-Control: no-cache, no-store, must-revalidate
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Set-Cookie: JSESSIONIDSSO=9E81D20C04095E5C0F82668222D54193; Path=/; Secure; HttpOnly
Set-Cookie: APPSESSIONID=5AFA8F314D99A5921C61817BCF21997D; Path=/ers; Secure; HttpOnly
X-CSRF-Token: C883A27FBEA77E4BAAF85028FD0E229E
Pragma: no-cache
ETag: "D5755A00DC6F46C650D6B5D8E550DBE0"
Date: Tue, 05 Feb 2019 22:59:13 GMT
Content-Type: application/json;charset=utf-8
Content-Length: 322

 

So I have my CSRF token to feed into the POST to add the endpoint: 

POST /ers/config/endpoint HTTP/1.1
Host: 10.81.127.170:9060
Accept-Encoding: identity
Content-Length: 183
X-CSRF-Token: C883A27FBEA77E4BAAF85028FD0E229E
accept: application/json
content-type: application/json
authorization: Basic [redacted]
cache-control: no-cache
------------------
Status: 404
Set-Cookie: JSESSIONIDSSO=C4AF34E0D41D8D0CEBC9309A0F7777E6; Path=/; Secure; HttpOnly
Set-Cookie: APPSESSIONID=E45F80818D77D32377B8F3F3C0351B97; Path=/ers; Secure; HttpOnly
X-CSRF-Token: Required
Content-Length: 0
Date: Tue, 05 Feb 2019 22:59:13 GMT

Why is my token not accepted?

 

Is this CSCvi80094? Not sure a 403 Forbidden would actually help me here.

 

Thanks,

Mike.

 

 

 

1 Accepted Solution

Accepted Solutions

hslai
Cisco Employee
Cisco Employee

Now it seems requiring the same cookies returned from the fetch request. See the attached example using cURL wrapped in a bash shell script.

View solution in original post

15 Replies 15

Jason Kunst
Cisco Employee
Cisco Employee
investigating

hslai
Cisco Employee
Cisco Employee

The token is per-session but only good for a few minutes. Thus, we would likely need a fresh token right before an ERS request.

It's in one Python script that runs in about 2 seconds.

I don't need to handle the JSESSIONIDSSO and APPSESSIONID cookies too, do I? They aren't mentioned in the docs and the script works as intended if I turn off the CSRF check.

No need to handle the other cookies. Last I tried this option, I was only able to use the same token for one or two requests.

Here's my python code:

#!/usr/local/bin/python3

###########################################################################
#                                                                         #
# This script demonstrates how to use the ISE ERS internal users          #
# API  by executing a Python script.                                      #
#                                                                         #
# SECURITY WARNING - DO NOT USE THIS SCRIPT IN PRODUCTION!                #
# The script allows connections to SSL sites without trusting             #
# the server certificates.                                                #
# For production, it is required to add certificate check.                #
#                                                                         #
# Usage: create-endpoint.py <ise-ip-address> <username> <password>        #
#      <description> <Endpoint MAC Address> <group>'                      #
###########################################################################

import http.client
import base64
import ssl
import sys
import json

# host and authentication credentials
host = sys.argv[1] # "10.20.30.40"
user = sys.argv[2] # "ersad"
password = sys.argv[3] # "Password1"

#parameters
description = sys.argv[4] 
mac = sys.argv[5]
groupName = sys.argv[6]

# create BASE64 encoded auth from CLI creds
creds = str.encode(':'.join((user, password)))
encodedAuth = bytes.decode(base64.b64encode(creds))

# Lookup the group ID by its name

headers1 = {
    'accept': "application/json",
    'content-type': "application/json",
    'authorization': " ".join(("Basic",encodedAuth)),
    'cache-control': "no-cache",
    'X-CSRF-TOKEN': "fetch"
    }

# This is run through a local proxy on 8080 for testing purposes conn = http.client.HTTPSConnection("localhost",8080, context=ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)) conn.set_tunnel(host, port=9060) #conn.debuglevel = 2 conn.request("GET", "/ers/config/endpointgroup/name/{}".format(groupName), headers=headers1) res1 = conn.getresponse() data1 = res1.read() csrfToken = res1.getheader('X-CSRF-Token') groupJSON = json.loads(data1.decode("utf-8")) groupID = groupJSON['EndPointGroup']['id'] print("=== Group Lookup ===\nStatus: {}".format(res1.status)) print("Header:\n{}".format(res1.headers)) print("CSRF Token: {}".format(csrfToken)) print("Group: {} ➤ {}".format(groupName,groupID)) cookies = res1.getheader('Set-Cookie') print("Cookie\n{}".format(cookies)) # Add endpoint to group headers2 = { 'X-CSRF-Token': csrfToken, 'accept': "application/json", 'content-type': "application/json", 'authorization': " ".join(("Basic",encodedAuth)), 'cache-control': "no-cache", } print("\nHeaders: {}\n\n".format(headers2)) req_body_json = """ {{ "ERSEndPoint" : {{ "description" : "{}", "mac" : "{}", "groupId" : "{}", "staticGroupAssignment" : true }} }} """.format(description,mac,groupID) conn.request("POST", "/ers/config/endpoint", headers=headers2, body=req_body_json) res2 = conn.getresponse() data2 = res2.read() print("\n=== Endpoint Create ===\nStatus: {}".format(res2.status)) print("Header:\n{}".format(res2.headers)) print("Body:\n{}".format(data2.decode("utf-8")))

And the output:

$ ./create-endpoint-csrf.py 10.1.1.1 apiuser ******** csrf-test 00:01:02:03:04:05 groupGreen
=== Group Lookup ===
Status: 200
Header:
Cache-Control: no-cache, no-store, must-revalidate
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Set-Cookie: JSESSIONIDSSO=005413EF42E504EFA5BEB4C9023C9CB5; Path=/; Secure; HttpOnly
Set-Cookie: APPSESSIONID=EE1CA8DC3F1B1831EAE1E6A714D55619; Path=/ers; Secure; HttpOnly
X-CSRF-Token: 87B6304D78217E1620DA519BF1454786
Pragma: no-cache
ETag: "D5755A00DC6F46C650D6B5D8E550DBE0"
Date: Thu, 07 Feb 2019 09:50:30 GMT
Content-Type: application/json;charset=utf-8
Content-Length: 322
Connection: close
Server: 


CSRF Token: 87B6304D78217E1620DA519BF1454786
Group: groupGreen ➤ bb6b38b0-298b-11e9-9d19-005056a47a4e
Cookie
JSESSIONIDSSO=005413EF42E504EFA5BEB4C9023C9CB5; Path=/; Secure; HttpOnly, APPSESSIONID=EE1CA8DC3F1B1831EAE1E6A714D55619; Path=/ers; Secure; HttpOnly

Headers: {'X-CSRF-Token': '87B6304D78217E1620DA519BF1454786', 'accept': 'application/json', 'content-type': 'application/json', 'authorization': 'Basic bGVldDoxMzM3aDRYMHI=', 'cache-control': 'no-cache'}



=== Endpoint Create ===
Status: 404
Header:
Set-Cookie: JSESSIONIDSSO=DF4C74D1F4AC909D9DE41BA41DDE883A; Path=/; Secure; HttpOnly
Set-Cookie: APPSESSIONID=3528AA65F48759B3FA9260DC87707D66; Path=/ers; Secure; HttpOnly
X-CSRF-Token: Required
Content-Length: 0
Date: Thu, 07 Feb 2019 09:50:31 GMT
Connection: close
Server: 


Body:

I am also unable to get this to work. Please disable the CSRF validation for now. I will check with our engineering team.

Thank you 😀

Hi,

any update on this? I guess this issue is still there in ISE 2.4 Patch 6 - correct?

Correct.

According to the release notes this bug is fixed with 2.4 Patch 8

(https://www.cisco.com/c/en/us/td/docs/security/ise/2-4/release_notes/b_ise_24_rn.html#id_105872)

However, I haven't tested it yet.

Patch 8 includes the fix for CSCvi80094 but that is a different issue and does not fix the CSRF issue which is being tracked as CSCvp22075.