CyberArk's Credential Provider loopback communications on TCP port 18923 are encrypted with key material that has extremely low entropy. In all currently-known use cases, the effective key space is less than 2^16. For an attacker who understands the key derivation scheme and encryption mechanics, knowledge of the source port and access to the payloads of a given client-server exchange are sufficient to reduce effective key space to one. In cases where the source port is not known, the encrypted payloads will be unable to withstand a brute force attack. Additionally, the user identification mechanism used by CyberArk's Credential Provider is vulnerable to a race condition where an unauthorized/unprivileged user can submit one or more encrypted query requests. If the race is won, the attacker will be able to retrieve sensitive information including passwords and password metadata. Versions prior to 12.1 are affected.
a5595be791e4ba068a17e6e8dfc3f175
KL-001-2021-009: CyberArk Credential Provider Race Condition And Authorization Bypass
Title: CyberArk Credential Provider Race Condition And Authorization Bypass
Advisory ID: KL-001-2021-009
Publication Date: 2021.09.01
Publication URL: https://korelogic.com/Resources/Advisories/KL-001-2021-009.txt
1. Vulnerability Details
Affected Vendor: CyberArk
Affected Product: Application Access Manager/Credential Provider
Affected Version: Prior to 12.1
Platform: Linux/Windows/zOS
CWE Classification: CWE-326: Inadequate Encryption Strength,
CWE-362: Concurrent Execution using Shared Resource with Improper Synchronization ('Race
Condition'),
CWE-923: Improper Restriction of Communication Channel to Intended Endpoints
CVE ID: CVE-2021-31797
2. Vulnerability Description
CyberArk's Credential Provider loopback communications on TCP
port 18923 are encrypted with key material that has extremely
low entropy. In all currently-known use cases, the effective
key space is less than 2^16. For an attacker who understands the
key derivation scheme and encryption mechanics, knowledge of the
source port and access to the payloads of a given client-server
exchange are sufficient to reduce effective key space to one. In
cases where the source port is not known, the encrypted payloads
will be unable to withstand a brute force attack.
Additionally, the user identification mechanism used
by CyberArk's Credential Provider is vulnerable to a race
condition where an unauthorized/unprivileged user can submit
one or more encrypted query requests. If the race is won,
the attacker will be able to retrieve sensitive information
including passwords and password metadata.
3. Technical Description
Based on analysis and observations, the key derivation process
for CyberArk's Credential Provider loopback communications on
TCP port 18923 can be summarized as follows:
- start a SHA1 hash (Hash1)
- update Hash1 with the decimal representation of the source port
- update Hash1 with an undocumented, hard-coded byte sequence
- finalize Hash1
- construct encryption key using Hash1[0:16]
Capturing loopback communications (e.g., with a sniffer)
requires elevated privilege. Thus, the risk associated with
this attack vector can be partially mitigated through basic
system hardening.
However, access to loopback communications is not the only
method by which the Credential Provider can be attacked. An
unprivileged user can simply open a connection, submit an
encrypted request, and if the conditions are right, the
Credential Provider may be "tricked" into generating a valid
response.
Below, a summary of two distinct races is given. Each race
consists of two query requests: one made by an authorized user
(u_auth) and the other made by an unauthorized/unprivileged user
(u_unauth). Observe (see details provided below) that only the
authorized query is satisfied in the first race, while both
queries are satisfied in the second race. By piggybacking on a
lock file created during u_auth's request, the user controlling
u_unauth's account is able to retrieve information s/he is
not authorized to view/possess. Clearly, this is a security
breach. Factors that make this attack possible include:
- The key material generated for these communications is
weak. The effective key space is less than 2^16 because
the key is derived from the TCP source port used to make
the request and an undocumented, hard-coded byte sequence
embedded in the key derivation code (henceforth referred to
as Suffix1).
- The user identification mechanism used by the Credential
Provider is vulnerable to a race condition where a shared,
ephemeral lock file exists in a common folder from the
time that the client makes its request to the time that the
Credential Provider's response is received/processed. The
window of time in which this file persists affords an
unauthorized user the opportunity to submit one or more
distinct requests that subsequently induce the provider
to reuse the yet-to-be-removed lock file. At that point,
pending requests (piggyback requests) will be deemed to have
originated from the same user as the first request (original
request), and if that user is authorized to make each request,
then each will be satisfied by the Credential Provider so
long as the lock file persists. An attacker who understands
how this mechanism works, can simply wait for a lock file
to come into existence (or predict its existence based
on process table monitoring and TCP port allocation). Once
detected (or predicted), a piggyback request can be submitted
provided that it originates from the "same" source port as
the original request.
- Requests originating from loopback addresses other than
127.0.0.1 (e.g., 127.0.0.{2,3,4}, etc.) are honored by the
Credential Provider. This makes it possible for an attacker
to make a piggyback request from the "same" source port
as the original request. Without the SO_REUSEPORT socket
option and cooperating processes, each source address/port
tuple must be unique on a given system. In other words,
two non-cooperating processes can't simultaneously bind to
the same source address/port (e.g., 127.0.0.1:10000). One or
the other will be rejected by the operating system. However,
since 127.0.0.1:10000 and 127.0.0.2:10000 are distinct tuples,
they are viewed as distinct endpoints (by the operating
system) and are therefore allowed to coexist. The Credential
Provider, upon receiving a request from either endpoint,
ignores (or discards) the source address, and incorrectly
associates that communication as having originated from the
"same" port (i.e., port 10000 per the example at hand).
- Note that if the Credential Provider is unable to
communicate with the Vault, it will continue to answer cached
queries. If log records are world readable, they can reveal
past queries that were both legitimate and successful. If
the provider is configured to maintain a cache, those query
results are likely still resident in the cache. Thus, an
attacker may use knowledge of cache behavior and available
log records to construct piggyback requests that are likely
to be satisfied when the race is won.
Below, a sanitized excerpt of the authorization policy
recovered from the Credential Provider's local cache
(appprovider_cache.dat) on [NAME REDACTED] is shown. Observe
that u_auth is listed as an authorized user. The scope of this
authorization is not fully known. Through testing, it was
determined that u_auth is authorized to make password queries
from at least two distinct safes (AIM_SAFE1 and AIM_SAFE2).
--- policy ---
<?xml version="1.0" encoding="UTF-8"?>
<AppMetaData>
<AIM>
<AuthMechanism Type="AppID" />
<AuthReq LastID="142">
<IPAuth>
<IPReqData ReqVal="10.10.1.11" ID="11" />
<IPReqData ReqVal="10.10.1.12" ID="12" />
...
<IPReqData ReqVal="10.10.1.140" ID="140" />
</IPAuth>
<OSUserAuth>
...
<OSUserReqData ReqVal="u_auth" ID="6" />
...
</OSUserAuth>
</AuthReq>
<ExtendedApplicationRestrictions isEnable="True" />
</AIM>
</AppMetaData>
--- policy ---
Below, the result of an authorized query made by u_auth to
retrieve app_123's password located in the AIM_SAFE1 safe
is shown. Note that the CyberArk "clipasswordsdk" utility
transparently encrypts the request and decrypts the response.
$ clipasswordsdk GetPassword -p AppDescs.AppID=APP_ID -p Query="Address=enco;TokenID=APP123Pass;Env=env1" -o Password
--- output ---
[PASSWORD REDACTED]
--- output ---
Below, the result of two unauthorized queries made by u_unauth
are shown. These queries attempt to retrieve app_456's password
located in the AIM_SAFE2 safe. Note that these responses
are essentially what an observer could capture if sniffing
the loopback interface. Also note that the Elements field
contains encrypted query results. Once decrypted (as shown
farther below), it is evident that the first response contains
an error message indicating that the query failed. Hence,
that race was lost. However, the second response clearly
contains valid data. Hence, that race was won. This implies
that no single race is a sure bet. Rather, factors such as
current system load, number of processors, processor speed,
etc. will influence the outcome of any given race. Note that
an unconstrained user may be able to influence system load
sufficiently to consistently win the race.
--- RESPONSE_1_BEGIN [TCP_PORT=44222] ---
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<Message>
<Header>
<ProtocolVersion>995000</ProtocolVersion>
<ProtocolInfo>3</ProtocolInfo>
</Header>
<Elements>9232456D7707CEBCC280184CB311F0871521DBFF0546A5E858974FE9E4AC8B4260FB4C579ACFB603905D1CFD1CA8EF76CD9AC32AE6C7CD6EC85FA57BD3E035514EEB72E767FBEA3FF2F4FA45D6F3D7E34B0DDACF9E2A3443E43C24D84544534A65046A6A4CCBED7CF6C72733F7B05CFD2F805E51B277100E1A9D42DA8D759EE6DE43F0D26ED41750EE428F82481CC96C8A3177C09F8A882138C294A4ADBDC270DE55128ABDCFCD6A5451A692DF4AE4035CB8D23C38176E78669903C680C89C14B00798568718FECAA1B7143ABAEEE612CE394DA4B7BD550338DB319BE607EED7F57EBCA05AA52CFAC03B02A4EC49F8F6B9E60375C32CEAA963017F590E3FBBAF4652664FC79AB355CB23EF50581A76FFC207731975FAF04CAAFD32F10B508E16660F0BCF6A55FDF3C2322110FBA425CFD06530B373B493957EF76E62100788D9FF1954BD12CBDD9D4E0393D3F6F411BD28AC788A55D6291BCDC439D895AA24E3A307A479EF420524AA3131C137F2EB9F</Elements>
</Message>
--- RESPONSE_1_END [TCP_PORT=44222] ---
--- RESPONSE_2_BEGIN [TCP_PORT=44228] ---
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<Message>
<Header>
<ProtocolVersion>995000</ProtocolVersion>
<ProtocolInfo>3</ProtocolInfo>
</Header>
<Elements>3681C9C1467C74EC3FFB7982B5E2639602D87E70D4E00EDCD6A65AFAF2093077B7CA27126C26A6F23DAEFB90287E9CDF99C20ED9F1835BC849855F8B7CFA437F72C8EF57EA077FA14DA625FAE93C0AAA0883FC130DA386E03622C80439A2F35F6508D08218E8ABE0D2000A2944908D13B5AE20854C4D8DCF30E790E25D6C4642BE52C6BA494FDDAB5A422C644C1D4A4688A9E9450F681BFD0949AB1A3358A355DFA797F2D416A9B1C2EF4C960A2A0B4C2F6F278B0B705D29F3DC3CFC9DA79B43B341D1AD8C45F602796CF627D5721DE7278B984E59CA5B5364A62CEFFAF0EDB9E7E33DCE349781AD0934DDD58E0A27EE669879D4641170C74FF237AD69C2F2C74263F48433213952F3E436EAFA65A69E12833EE189416F5F29A7A420D284180ED3C37D58DBE06600E4F3E01FF13C8AC98A101396E2FB0C382CF2C44C5E9487A31BE8665C2C6CC03F8982E719928537F2446068A849397A7132245F5521C990CA037C9C88C707F661CDD688AC9C45CC23A4B508EEE5E858E47E1C0BC31843BE43522F80DD29F0D6CD4233622D1F95A563C5425DEC73DBD47655525DCA19BBE64C177F8A0462D073FE99F135F2C056108D1F3D7B91CF055681DE5FBB12ABC92C08F872FACCE86C703B2F5CBFD49DB85DFBB484AB4C9308E804053F96D73E2DFD79D1EC55AE26358F4C02D33D0719300627B336B4FF99C294E0A713B6D33381DAB0241448A409E8346AA35F8352E1B0851BC1338EA6863E49DDB98B8CAB8EBB566C257F079BA16B6C28C4F1BA590B61B8F301E941867D3162231016DAA0C738C64C7B4DF355A8C8FCB08B866B81D9C23B9CAB626FFE53601D114D04E370D085B97473E8EE56DE4B7083D645C7E11CC51EF8BEA72A424BFD7FE3DCB6DF2EB58D95D907347627E450E83DD8CFEDA1F438953BFFAF52BEE65A3980F50DED183D6AFA6F0CD1C4B4F28A0FC16540055B76E063015D13100BE3492B9B32C02F45819506B39247CF4CA65CF04BE4BCDCF38EB4E3F44696299AFF93177E9F3E0B8ABD14BF51C35E3493B604173E83B6C00E85B580639A57B961A340881738D925068817F15E5FA565C95B8E913E200F82E21AA51C23C751AD75C3CE32C50B3BCF7B10C680A7CBA7356D2A8027D138AC6B0294AD760F1C71BA7DA8F53B997E60B185998A72693C3A88C43817648D285BFAFCC9F26CD3C37B96862BCED33EB48E536EDA29DBB1E0D7EC5680478BD99361D2C04B5F9E079EE8DC0D2CD76362507C8C13759156D450F1EE283171D3A5D9C8C3B9D284D3BF3B7729529E0FACC3424B27C1A62392B9A127AAF98982318459F20B5A1C60B9DB4AAA1F9AD0F2EEE373E46DC0231FF106</Elements>
</Message>
--- RESPONSE_2_END [TCP_PORT=44228] ---
--- DECRYPTED_ELEMENTS_RESPONSE_1_BEGIN [TCP_PORT=44222] ---
<Elements>
<Element>
<ElementType>ErrorResponse</ElementType>
<ResponseBase>
<ResponseId>1</ResponseId>
<ErrorResponse>
<ErrorCode>-1</ErrorCode>
<ErrorMsg>APPAP087E Application authentication failure</ErrorMsg>
</ErrorResponse>
</ResponseBase>
</Element>
</Elements>
--- DECRYPTED_ELEMENTS_RESPONSE_1_END [TCP_PORT=44222] ---
--- DECRYPTED_ELEMENTS_RESPONSE_2_BEGIN [TCP_PORT=44228] ---
<Elements>
<Element>
<ElementType>PasswordResponse</ElementType>
<ResponseBase>
<ResponseId>1</ResponseId>
<PasswordResponse>
<Password>REDACTED</Password>
<Flags>0</Flags>
<AlterPassword></AlterPassword>
<PassProps>
<Address>appprodapplication</Address>
<ApplicationName>APP</ApplicationName>
<ClassType>Class H</ClassType>
<CreationMethod>PVWA</CreationMethod>
<Description>SR0118365</Description>
<DeviceType>Operating System</DeviceType>
<Env>all-prod</Env>
<PolicyID>H_SRV_GENERIC_Q_XXX_APC</PolicyID>
<RegSCI>ISCI</RegSCI>
<TokenID>APPPassword</TokenID>
<UserName>app_456</UserName>
</PassProps>
<PasswordChangeInProcess>false</PasswordChangeInProcess>
</PasswordResponse>
</ResponseBase>
</Element>
</Elements>
--- DECRYPTED_ELEMENTS_RESPONSE_2_END [TCP_PORT=44228] ---
Below, the relevant log entries generated for queries made
during the first race are shown. Note how all timestamps
are identical. Note also that the reason the race was lost is
revealed by the first record in APPConsole.log. Essentially, the
authorized query (first entry in APPAudit.log) was satisfied
and its associated lock file (/tmp/AIM44222) was removed
before the unauthorized query (second entry in APPAudit.log)
could be processed by the Credential Provider. And since the
lock file was removed, the provider had no means to look up
the process ID of the requesting process.
--- APPAudit.log ---
[DATE | 18:09:08] | :: | APPAU001I Provider Prov_[REDACTED] has successfully fetched password
[safe=AIM_SAFE1,folder=Root,name=[REDACTED]] with query [Address=enco;TokenID=APP123Pass;Env=env1] for application
[APP_ID]. Fetch reason: []
[DATE | 18:09:08] | :: | APPAU002E Provider Prov_[REDACTED] has failed to fetch password with query
[Address=appprodapplication;Env=all-prod;TokenID=APPPassword] for application [APP_ID]. Fetch reason: []. Failure
reason: [APPAP087E Application authentication failure]
--- APPAudit.log ---
--- APPConsole.log ---
[DATE | 18:09:08] | :: | APPAP087E Application authentication failure for Application APP_ID (CASCU086E Failed
to find application process id. (Error: The lock file (/tmp/AIM44222) couldn't be opened, Error code: 2).)
[DATE | 18:09:08] | :: | APPAP002E Provider Prov_[REDACTED] has failed to fetch password with query
[Address=appprodapplication;Env=all-prod;TokenID=APPPassword] for application [APP_ID]. Fetch reason: []. Failure
reason: [APPAP087E Application authentication failure]
--- APPConsole.log ---
Below, the relevant log entries generated for queries made
during the second race are shown. Note how all timestamps are
identical. The authorized query corresponds to the first entry
in APPAudit.log, and the unauthorized query corresponds to the
second entry. Note how two distinct safes were queried. This
suggests that safes not normally accessed/queried by a given
Credential Provider may be targeted by an attacker from
a different system. Clients should be cautioned that the
contents of any given safe should be confined to a single
security domain.
--- APPAudit.log ---
[DATE | 18:09:13] | :: | APPAU001I Provider Prov_[REDACTED] has successfully fetched password
[safe=AIM_SAFE1,folder=Root,name=[REDACTED]] with query [Address=enco;TokenID=APP123Pass;Env=env1] for application
[APP_ID]. Fetch reason: []
[DATE | 18:09:13] | :: | APPAU001I Provider Prov_[REDACTED] has successfully fetched password
[safe=AIM_SAFE2,folder=Root,name=[REDACTED]] with query [Address=appprodapplication;Env=all-prod;TokenID=APPPassword]
for application [APP_ID]. Fetch reason: []
--- APPAudit.log ---
4. Mitigation and Remediation Recommendation
The vendor has released an updated version (v12.1) which
remediates the described vulnerability. Release notes are
available at:
https://docs.cyberark.com/Product-Doc/OnlineHelp/PAS/Latest/en/Content/Release%20Notes/RN-WhatsNew12-1-CPs.htm?tocpath=Get%20Started%7CWhat%E2%80%99s%20New%7CRelease%20Notes%7C_____4
5. Credit
This vulnerability was discovered by Klayton Monroe of
KoreLogic, Inc.
6. Disclosure Timeline
2020.11.04 - KoreLogic submits vulnerability details to
CyberArk.
2020.11.05 - CyberArk acknowledges receipt and the intention
to investigate.
2020.11.16 - KoreLogic and CyberArk meet to discuss the
details of this and other reported
vulnerabilities. Both parties agree that the
remediation timeline will extend significantly
longer than the standard 45 business days specified
in the KoreLogic Public Disclosure Policy.
2021.01.14 - 45 business days have elapsed since the
vulnerability was reported to CyberArk.
2021.01.21 - KoreLogic and CyberArk meet to discuss proposed
remediation efforts for this and other reported
vulnerabilities.
2021.03.24 - 90 business days have elapsed since the
vulnerability was reported to CyberArk.
2021.04.22 - CyberArk notifies KoreLogic that the reported
vulnerability will be mitigated in a version
scheduled for release in late May, 2021.
2021.05.10 - 120 business days have elapsed since the
vulnerability was reported to CyberArk.
2021.05.10 - CyberArk provides KoreLogic with the CVE for this
vulnerability. Vendor requests KoreLogic delay
public disclosure until the end of June, 2021.
2021.06.08 - KoreLogic and CyberArk meet to discuss the details
of the product release and revisit timeline for
public disclosure. CyberArk informs KoreLogic that
the Linux/Windows version of the Credential
Provider will be released at the end of June, 2021.
A Credential Provider for the zOS platform will be
released at the end of July, 2021. KoreLogic agrees
to delay public disclosure of this and other
reported vulnerabilities until 2021.08.15.
2021.06.23 - CyberArk releases Credential Provider v12.1 for
Linux/Windows platforms.
2021.08.05 - 180 business days have elapsed since the
vulnerability was reported to CyberArk.
2021.08.10 - CyberArk informs KoreLogic that the zOS Credential
Provider update has been released to their
customers. Requests that KoreLogic forgo
publication of the Proof of Concept code as an
unforseen issue prevents some customers from
updating in the near term.
2021.08.27 - KoreLogic suggests delaying the release of the
Proof of Concept until a to-be-determined future
date.
2021.08.30 - CyberArk tenders 2022.01.01 release date for the
Proof of Concept.
2021.09.01 - KoreLogic public disclosure.
7. Proof of Concept
At the vendor's request, KoreLogic has agreed to delay
publication of the Proof of Concept while customers continue
to deploy the updated versions of the product.
The contents of this advisory are copyright(c) 2021
KoreLogic, Inc. and are licensed under a Creative Commons
Attribution Share-Alike 4.0 (United States) License:
http://creativecommons.org/licenses/by-sa/4.0/
KoreLogic, Inc. is a founder-owned and operated company with a
proven track record of providing security services to entities
ranging from Fortune 500 to small and mid-sized companies. We
are a highly skilled team of senior security consultants doing
by-hand security assessments for the most important networks in
the U.S. and around the world. We are also developers of various
tools and resources aimed at helping the security community.
https://www.korelogic.com/about-korelogic.html
Our public vulnerability disclosure policy is available at:
https://korelogic.com/KoreLogic-Public-Vulnerability-Disclosure-Policy.v2.3.txt