Part II – SAP Help status page
In the first part of this small series I described how I found an “internal” page from SAP: the SAP Help Portal status page. Intended to be accessible to everyone, the layout made it appear to be for internal and authenticated access only. While this was solved rather quickly, SAP forgot to take a closer look at what was exposed regarding internal information. How I found this out, what kind of internal information was overlooked and where this took me to is part of this article (part 2).
I’ll share here now how I came across an SAP internal app by finding several small errors and combining them. Don’t worry, nothing big is going to be exposed, no data leakage, just a walkthrough how to get access to an app.
Part 2 – Exposing information
After I reported the internal site issue, SAP looked at the problem and fixed it. The internal part was removed, the site is now accessible without logon, short: it was transformed to what it was planned to be: a status page.
The colored icons in the footer triggered my attention. It is a list of social sites found on many sites: follow us on Facebook, Twitter, YouTube, LinkedIn, G+ … what? Yes, G+ was still alive here. I decided to take a closer look at the share and follow links.
The mail-to link opened my email client and added some pre-defined text. That’s very user friendly. The text provided contained a link. I clicked that link as it was not the URL I was expecting to see for help.sap.com.
The link led to some redirects and finally to an error.
Reminder: this information was all accessible to external users. With external users: every person on earth with internet access.
Getting the server’s name and dashboard part together for a working URL was easy. The app is/was protected by SAP IdP, but it worked with my S-User (don’t remember exactly, but I think it worked with a P-User too). I guess the permission was like the example SAML permission in the old WebIDE tutorials with Neo: check that the user is logged on, but not checking for a specific group, too. Nevertheless, this is what opened in my browser:
An UI5 app that emulates the Fiori Launchpad. If the responsible people would have opted to use the Fiori Launchpad available in the cloud, authorization and the FLP framework could have helped to prevent unauthorized access to the app. In my case, I was able to access the UI5 dashboard app and look at the source code. Remember: the parameter sap-ui-debug allows everyone to load the debug files of an UI5 app – if these are available. The manifest.json file is always accessible and there I saw that all tiles are just routes to different views.
Most sub app, or routes / views failed to open as the app checks if the user has permission. This is done in the function checkAdmin.
This was the moment where I understood why the health service was setting the cookies. The values of the cookies determined the role and access you have in the dashboard app.
The function checkAdmin is called when the app sets the internal model.
Setting a break point allows to alter the model and give admin permission to a person that is not an admin (aka me). Setting a break point after the model is initialized and setting the userIsAdmin property to true.
This allowed me to open the many views available in the dashboard app and act as an administrator. Of course, only in the UI5 app I was an administrator. But it served to explore more of the dashboard app. For instance, I could see the new product button and call the form.
Saving of course did not work, as the backend checked the user again and saw that I am authenticated, but not assigned the needed permissions. Luckily the backend is not just accepting anything the frontend does and checks also for permissions. Regarding security, the frontend failed, backend delivered.
I hope that after going with me through the above scenario, you understand small mistakes might not seem problematic when looked only at them, but in combination with other mistakes, they can be the source of a problem.
Internal server names should never be added to files that are publicly accessible. They might even include code names or give hints on projects. The internal name might even be used in a password shared with other users (codename123). Internal names are internal for a reason. Keep them internal.
In the last step I was not able to change or create data in the backend. The backend implements the zero-trust principle and checks the user permission. This is good and prevents that an attacker can do any further harm. But: a possible attacker might have gained some insights into the app and can construct a valid payload. From now on, the attacker might just wait until the backend fails and accepts a request. Maybe a security change that goes wrong, are a new faulty permission check is added. An attacker just needs to wait for a small new mistake. And attackers can wait, they have enough time.
The app tries to be a Fiori Launchpad and contains many apps. If this app is hacked, you get access to all apps. Better is to follow one of the Fiori ideas and have one app per use case. Use the services available. Use apps that serve a single purpose.
And the security of the frontend app? Maybe using OIDC, role based access instead of a local model where the difference between guest and admin is a property that is easily changeable? The SAP BTP portfolio offers some solutions that can help to develop secure apps.