cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
10071
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.

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.

Good to know with the cookie.... however, it's still not working as expected, right? The ERS API documentation doesn't say anything about cookies.


@Johannes Luther wrote:

... however, it's still not working as expected, right? The ERS API documentation doesn't say anything about cookies.


This is how this feature working in ISE. CSCvp22075 is now used to update the on-box documentation.