Be careful when you have escape char in Key Vault secret value

I recently had some works that required to use Azure Key Vault. Specifically a secret that stored a service principal’s password that contained some special characters (escape ones).

This article just shows you my finding and how to fix it while waiting for Microsoft to work on the fix.

Reproduce Issue

To reproduce the issue, you only need to put a secret value with escape char for example mine is secret\@!

Either using REST API or Azure Python SDK the value is always escaped. Below is the sample code to call GetSecret API.

import adal
import requests
import json

AZURE_TENANT_ID = 'XXXXXX-XXXXX-XXXXXXX'
CLIENT_ID = '04b07795-8ddb-461a-bbee-02f9e1bf7b46' #AZURE CLI CLIENT ID
AUTH_URI = 'https://login.microsoftonline.com' + '/' + AZURE_TENANT_ID
VAULT_NAME = 'global-app-kv'
KV_SECRET_NAME = 'secret'

context = adal.AuthenticationContext(AUTH_URI)
code = context.acquire_user_code('https://vault.azure.net',CLIENT_ID)
message = code['message']
print(message)

token =context.acquire_token_with_device_code('https://vault.azure.net', code, CLIENT_ID)
authHeader = {
'Authorization': 'Bearer ' + token['accessToken'],
'Content-Type': 'application/json'
}

secret_uri = 'https://' + VAULT_NAME + '.vault.azure.net/secrets/' + KV_SECRET_NAME + '?api-version=7.0'
response = requests.get(secret_uri, headers=authHeader)
jsonData = response.json()
print(json.dumps(jsonData, indent=4))

and the returned value has one more backslash added

If your code relies on this value and passes the value to the next function you would receive an exception. For example when I passed my service principal’s password to Azure AD Authorization Endpoint I got error message AADSTS7000215: Invalid client secret is provided.

Not only REST API, Azure Python SDK also returns similar issue.

Workaround

Well as we know that the value is escaped when it has special char (e.g. backslash) so the workaround would be to decode it. Below is the code

jsonData['value'].encode('utf-8').decode('unicode-escape')

Note that if you use print() to print the value you would always see the valid because print() actually unescape the escaped value. And luckily by that way the printed value is correct in the console.

I submitted the bug to Microsoft and they confirmed and acknowledge.

[Updated 06/17] If you use Python SDK or REST API the output is a JSON format and your secret value must be escaped thanks to this spec. That said, you are responsible for unescaping the value if it has escape char.

This entry was posted in Security Automation and tagged . Bookmark the permalink.

Leave a Reply