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!

Send()-ing Myself Belated Christmas Gifts - GitHub.com's Environment Variables & GHES Shell- 1403

Ngo Wei LinPosted 1 Year Ago
  • GitHub Enterprise Servers (GHES) is a locally hosted version of Github that teams can run. It runs functionality the same as the regular Github service and is written in Ruby.
  • Reflections in Ruby are used for calling arbitrary functions on an Object. This works because there is an inheritance structure similar to that of JavaScript. By calling Kernel#send() on an object, arbitrary functions can be called on an object. The author decided to look into potential sinks where this could be called, since it's known to be an RCE sink.
  • While doing research into the possible exploit methods, they noticed that RCE would require at least two controlled parameters - they didn't see any paths for one or zero. They found a case of reflection with zero inputs at Organizations::Settings::RepositoryItemsComponent. From there, they wrote a script to enumerate the available functions and variables that would be interesting to look at within the Ruby console.
  • While testing this, they noticed a couple of weird things. First, even if there are required parameters for a call, the function can still be called with default values. Additionally, the object in question with reflection issues had 5K different functions!? While conducting local testing there GHES broke. While it was fixing itself up they decided to mess around on standard Github.
  • The function nw_fsck() was calling spawn_git. This returned a list of environmental variables for the Github server itself! To the authors surprise, this contained a lot of production access keys. How did this happen!? Upon finding this, they reported the vulnerability to Github to fix up.
  • Ruby on Rails uses a serialized session that is signed. If this can be tampered with then RCE can be trivially obtained using Ruby deserialization primitives, such as with iblue's technique. Having access to the keys is a terrible primitive as a result.
  • The difference between a local and a global instance of Github is interesting in this context. Accessing data globally is scary and all angles must be considered, especially with things like Github Actions. The enumeration of exploit paths for the deserialization was interesting to me in the post as well. The bug itself was simple but finding a meaningful impact was very difficult. Overall, great post for a super impactful bug!