Resources

People often ask me "How did you learn how to hack?" The answer: by reading. This page is a collection of the blog posts and other articles that I have accumulated over the years of my journey. Enjoy!

Chaining Three Bugs to Access All Your ServiceNow Data- 1450

Asset NotePosted 1 Year Ago
  • ServiceNow is a business platform similar to Salesforce. It has data from HR, to employee management, to many other things. ServiceNow is mostly cloud hosted but there is a self-hosted version that's a 20GB jar file.
  • ServiceNow has a ton of functionality. To better understand the vulnerability, the author puts out a list of things to know and goes through the routing of the app:
    • Table: All service now data is stored in tables. From users to pages to configurations. There is a simple way to update tables thorugh the UI with an included ACL.
    • Processors: Effectively, an API endpoint. A user can write code for their JavaScript engine Rhino to create custom endpoints. Since most setups are multi-tenent, there is a lot of sandboxing on it.
    • UI Pages: UI pages come from XML templates by the Apache Jelly library. These allow custom UIs on the app.
  • Executing custom code can be very hard to do. So, they started looking how this worked. They learned that there are multiple evaluations that occur - one for g and ${} then another for g2 and $[]. Double evaluation on templates is a known issue. In particular, if any content from stage 1 with the special tags gets into stage 2, then we have template injection.
  • Within the system, there was also the <g:no_escape> tag. Within one of the default templates, they found that the title of the page was injectable! In particular, they had something similar to register_globals, which meant that it was controllable anywhere, including the login page.
  • Sadly, a HTML santizier is ran over the page title, which could prevent the adding of arbitrary XML. While looking through the allowlist, they noticed that the style tag was allowed. From the context of the HTML parser, anything within the style is fine! But, this can still be processed in the rendering as XML later, allowing us to smuggle in payloads.
  • Without mitigations for Jelly injection, this would have been game over. So, they took a deep dive into how the evaluation process worked. It works in two stages.
    1. First, the j: is bound to Jelly core and g: is bound to ServiceNow custom tags. Then,j2: and g2: are bound to the null namespace, making them passed over.
    2. Next, it changes j2 to use Jelly Core and g2 to us the custom tags from ServiceNow with the original ones set to null to make it run over only the second set of tags.
  • With this, they tried creating their own namespace, which was rejected because Glide (Service Nows tags) can only be bound to g and g2. What about rebinding g from the null namespace TO the glide once again. Of course, another defense in depth measure was triggered to prevent this. However, it was a flimsy string match that was easy to bypass with using single quotes instead of double quotes! With that, OG glide tags are evaluated on the second pass, after our initial injection point.
  • Arbitrary JavaScript execution from a user clicking on a malicious link is pretty hype! But, the tables that could be accessed from this was limited. So, they wanted a permission break on a hardened instance. They looked into the file reading process to see a denylist of locations that couldn't be accessed, such as database creds. The denylist was super solid and didn't seem possible to bypass by itself.
  • However, this is when they had an idea something: "what if the processing for getBufferedReader() can mutate the path in some way?" It turned out that adding a .. into the middle of the path would be REMOVED when a clean up routine is done on the path. As a result, the denylist can be bypassed! Crazy that the normalization which is normally good for security actually caused the issue here.
  • Once there, ServiceNow has a mechanism to run arbitrary code on the box, by design. With all of the permissions we now have, it's game over. I love the hurdles that were required to get over this! The mitigations were well thought out and strong but enough of a deep dive led to compromise with the double eval on the templates.