API first – Account enumeration as a service

Published by Tobias Hofmann on

7 min read

Attention: SAP changed the service. To find out if a user is valid, you have to add check at the end. Verify was replaced by check. The url is now:

https://core-api.account.sap.com/uid-core/employee/<id>/check


In my previous blog post I wrote about my experience regarding SAP Universal ID logon. To my surprise SAP enables account enumeration. Filling out a form is mandatory, and this is a time-consuming process. To know if a working user ID is found, a validation of the response is needed. The interaction through a logon formular is not helpful when you want to check many user IDs. While scripting is possible, it still involves calling a form that is meant to be used by humans. While this allows to know if a user ID works with UID, wouldn’t it be nice to have more insights? For instance: is the user ID assigned to an employee and still active?

User ID Validation

How does the logon form know whether a user ID exists or is linked to UID? Taking a closer look at the logon form and process flow reveals how this is implemented. The logon form is divided in two screens: user ID and password input.

The first screen is used to validate the user. The “Next” button triggers a submit to the backend. Depending on the response, either the password screen or registration screen is shown.

The request is sent to

https://core-api.account.sap.com/uid-core/employee/<user id>/verify.

The placehoder <user id> is replaced with the user Id wanted to be checked. This can be a D-, I-, C-, S- or P-User, or an email address.

This service validates the provided user id and returns a JSON Object as response.

{
  "employee":false,
  "hasUid":false,
  "shared":false,
  "linkingRequired":false
}

The properties include interesting information. Security experts might question why the response contains this information. Remember: this data can be obtained by any anonymous user with access to the internet. The verify service is exposed to the internet, no authentication needed.

Account enumeration as a service

API first is one of the architectural principals that has the most impact on applications. Thankfully, the UID service applied the principles and comes with an API that can be used to obtain more information about a user ID. The API is easy to use. No complex payload needed. Just a GET request that includes the user ID under test. The API can be used for account validation: is an account assigned to an SAP employee and if is linked to SAP Universal ID. On top, the API returns additional relevant information. This was designed, discussed, and approved. This was checked and approved by SAP security. There are processes, governance, teams, experts, maybe even external checks involved. SAP UID offers account enumeration by design. SAP offers a service that exposes additional account relevant information. As security is priority #1 at SAP, the service is doing exactly for what it was designed.

I am not a security expert. Maybe this is a state of the logon process. Maybe the information returned by the API is simply what is considered best practice. Personally, I thought that as little information as possible about a user id should be made available. Maybe some security expert can share another view on this topic.

Let’s have some fun with this.

User IDs

Knowing that this service works as designed, let’s have some fun with it. Let’s go through some D-User IDs. Seems that D000101 is an ID for an SAP employee.

https://core-api.account.sap.com/uid-core/employee/D000101/verify

{
  "employee":true,
  "hasUid":false,
  "shared":false,
  "linkingRequired":false
}

What about S000101?

https://core-api.account.sap.com/uid-core/employee/S000101/verify

{
  "employee":false,
  "hasUid":false,
  "shared":false,
  "linkingRequired":false
}

This ID is not for an SAP employee. It is not possible here to find out if the ID is valid. Sending S0001000001 gives the same result.

Using e-mail addresses as user ID

UID accepts an e-mail as user ID for logons. This is the mandatory type of user ID for sap.com logons. Finding SAP e-mail addresses of current employees or ex-employees is easy. The internet does not forget. It is possible to find e-mail addresses and check them with other information available publicly. Let’s take the e-mail address of an SAP employee that is still at SAP. Taken from the public available PDF that contains the e-mail.

https://core-api.account.sap.com/uid-core/employee/thomas.fiedler@sap.com/verify

{
  "employee":true,
  "hasUid":true,
  "shared":false,
  "linkingRequired":false
}

This user ID is linked to SAP employee. It has also UID. As UID is not so old, it can be concluded that the person was at active in the last x (since when can UID link accounts?) years.

Let’s check my old e-mail address.

https://core-api.account.sap.com/uid-core/employee/tobias.hofmann@sap.com/verify

{
  "employee":true,
  "hasUid":false,
  "shared":false,
  "linkingRequired":false
}

The services returns that the email address was once valid. If it is still valid, working, or maybe even assigned to a different person: this is not disclosed. I left SAP before UID went live or even account linking. Therefore, the property hasUid cannot be set to true.

If you think: maybe the verify service is just checking for the @sap.com domain to set employee to true: let’s, try this out. Seems that I wasn’t the only Tobias Hofmann to ever get an email at SAP.

https://core-api.account.sap.com/uid-core/employee/tobias.hofmann01@sap.com/verify

{"employee":true,"hasUid":false,"shared":false,"linkingRequired":false}

https://core-api.account.sap.com/uid-core/employee/tobias.hofmann02@sap.com/verify

{"employee":true,"hasUid":true,"shared":false,"linkingRequired":false}

https://core-api.account.sap.com/uid-core/employee/tobias.hofmann03@sap.com/verify

{"employee":false,"hasUid":false,"shared":false,"linkingRequired":false}

Seems that 03 is not an employee. For SAP e-mail address the verify service allows for easy account enumeration. Let’s demonstrate this with a different e-mail.

What about the CEO? If his e-mail follows the pattern, it should be christian.klein@sap.com .

https://core-api.account.sap.com/uid-core/employee/christian.klein@sap.com/verify

{"employee":false,"hasUid":false,"shared":false,"linkingRequired":false}

No: not a valid SAP employee e-mail address. But there are valid addresses for 01 – 04.

https://core-api.account.sap.com/uid-core/employee/christian.klein01@sap.com/verify

{"employee":true,"hasUid":false,"shared":false,"linkingRequired":false}

https://core-api.account.sap.com/uid-core/employee/christian.klein02@sap.com/verify

{"employee":true,"hasUid":false,"shared":false,"linkingRequired":false}

https://core-api.account.sap.com/uid-core/employee/christian.klein03@sap.com/verify

{"employee":true,"hasUid":true,"shared":false,"linkingRequired":false}

https://core-api.account.sap.com/uid-core/employee/christian.klein04@sap.com/verify

{"employee":true,"hasUid":true,"shared":false,"linkingRequired":false}

https://core-api.account.sap.com/uid-core/employee/christian.klein05@sap.com/verify

{"employee":false,"hasUid":false,"shared":false,"linkingRequired":false}

This brings me to checking generic email address. What about CEO@sap.com? Privacy@sap.com? Security@sap.com? Press@sap.com?

https://core-api.account.sap.com/uid-core/employee/ceo@sap.com/verify

https://core-api.account.sap.com/uid-core/employee/privacy@sap.com/verify

https://core-api.account.sap.com/uid-core/employee/security@sap.com/verify

https://core-api.account.sap.com/uid-core/employee/press@sap.com/verify

All are not e-mail addresses linked to a person.

{"employee":false,"hasUid":false,"shared":false,"linkingRequired":false}
Let the world know

Tobias Hofmann

Doing stuff with SAP since 1998. Open, web, UX, cloud. I am not a Basis guy, but very knowledgeable about Basis stuff, as it's the foundation of everything I do (DevOps). Performance is king, and unit tests is something I actually do. Developing HTML5 apps when HTML5 wasn't around. HCP/SCP user since 2012, NetWeaver since 2002, ABAP since 1998.

0 Comments

Leave a Reply

Avatar placeholder

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.