Azure Active directory differentiates two types of permission for apps. The “on behalf of a user” permission and the “access without a user” permission. Although both are interesting from a security perspective the access without a user permission is especially interesting.
An application can have basically the same permissions as a user including; directory read/write or even global admin permissions. Secondly Client ID/Secret combinations are basically the same as a username/password combination without any MFA. The life time of a Client ID/Secret can be set to 1 year / 2 years or never expire. Combine that with the fact that service principals do not need to worry about conditional access restrictions and you can potentially have quite a serious security issue. If a hacker can create a service principle with a decent set of permissions with a never expiring secret, would you know it happened?
Getting a good understanding which of your apps have these kinds of permissions can be really hard so I wrote a script. It retrieves the name of the app, the resource it has access to, the permissions it has within that resource and the end date of the secret and / or certificate. It also finds any Azure AD Group or Roles an app is assigned to. You can find it on my GitHub.
Ow, and just any regular user of Azure AD can run this script.. it’s read only and any Azure AD user has read access. I have seen some pretty spooky stuff running this script at some of my customers.