This blog is about something I found recently regarding Cisco Unified Call Manager (CUCM). While playing around with SeeYouCM Thief, which is designed to download parse configuration files from Cisco phone systems, I noticed something interesting within a configuration file. There was an XML element in the configuration files named <secureUDSUsersAccessURL>. The value pointed to https://cucm_server:8443/cucm-uds/users and to my surprise upon navigating there it returned an XML document containing a bunch of Active Directory users. Curious, I wanted to learn more.
The User Data Services (UDS) API is a REST-based set of operations that provide authenticated access to user resources and entities such as user’s devices, subscribed services, speed dials, and much more from the Unified Communication configuration database.
This was interesting, as I was able to pull the data without authentication. Looking further regarding authentication, I found this statement regarding authentication:
Many, but not all, UDS API requests require authentication for access. Use an end user account created by the CUCM administrator to make API calls that require authentication.
So while this API did require authentication for some resources, many did not, with the users API not requiring it.
The users resource provides search functions to locate users stored in the Cisco Unified CM database. Often times, and as was the case for my client, this database is linked directly to Active Directory via LDAP/LDAPS.
Pulling data from the API was simple, but it did have some constraints. By default, this API call only returns a maximum of 64 results. If the user search result exceeds the number specified, it returns only partial results up to the specified search limit. To enumerate beyond the first 64 entries in database, it was possible to make multiple queries with query string parameters to filter the data.
It is possible to filter on name, first name, last name, phone number, username, email, etc. I found that filtering on name was the most useful, as not all entries contained values for the other attributes. Taking a lesson from MailSniper‘s GAL dumping feature, I decided that by requesting two letter combinations from the alphabet I could narrow the scope enough to hopefully produce a query that did not exceed the 64 result limit per query. This would result in 26 * 26 (676) queries total.
Using this technique, I was able to script out this process and recover ~10,000 active directory usernames in about 53 seconds. The active Directory Environment had 11,777 users total, which put me at a 85% recovery rate. Not bad for less than 1 minute of enumeration. The smaller the environment, the higher the recovery rate. The recovery rate could be increased with additional queries, but for my purposes this was good enough.
While this entire thing can be done with a bash one-liner, I went ahead and created a small shell script to automate the entire process.
if [ $# -eq 0 ] then echo "Please provide a hostname or IP Address" exit 1 fi echo -n "Detected CUCM Version: " curl "https://$1:8443/cucm-uds/version" -k -s | xml_grep version --text_only echo 'Please wait just a moment...' for x in {a..z} do for y in {a..z} do curl "https://$1:8443/cucm-uds/users?name=$x$y" -k -s | xml_grep userName --text_only done done | sort -u > cucm_users.txt echo "User dump complete!"
Additionally, this feature has also now been ported to SeeYouCM Thief, just use the –userenum flag when targeting a CUCM server.
Update March 01, 2022:
To mitigate this, enable Contact Search Authentication.
Bug ID: CSCwa81008 bst.cloudapps.cisco.com/bugsearch/bug/ (Customer Auth Required)
Full procedure to enable Contact Search Authentication.: https://www.cisco.com/c/en/us/td/docs/voice_ip_comm/cucm/rel_notes/11_5_1/cucm_b_release-notes-cucm-imp-1151/cucm_b_release-notes-cucm-imp-1151_chapter_010.html#task_AE831C159B03176B3451FB5834A5C0B0