Hacker News new | comments | show | ask | jobs | submitlogin
Ruby 2.x Universal RCE Deserialization Gadget Chain (www.elttam.com.au)
96 points by fpunit 4 months ago | hide | past | web | 18 comments | favorite

For anyone interested in gadget chains for other languages, these Github repos are quite interesting:

- Java: https://github.com/frohoff/ysoserial

- .NET: https://github.com/pwntester/ysoserial.net

- PHP: https://github.com/ambionics/phpggc

This is interesting, although not that novel. Marshal deserialization has always been unsafe, and in > 10 years as a Ruby engineer I’ve never seen it used in a production system. I would guess that finding a system vulnerable to this exploit would be a more interesting story than the exploit itself.

As a pen tester, I wholeheartedly disagree. It’s probably more common to see unsafe YAML deserialization, rather than directly deserializing marshaled Ruby objects, but both are impactful and these types of vulnerabilities do exist. Just recently I assessed an application that used unsafe serialization to pass around an object encoded in the value of a cookie. It contained transient data related to the user’s session (e.g. what page they last visited). Last year I assessed an application that allowed users to upload YAML files, which would get parsed and deseralized as Ruby objects. Unfortunately I didn’t have a universal gadget chain then, so I had to note it as theoretically exploitable in my report. That’s troublesome because some clients may take it less seriously.

I’m personally very impressed with this research and I think it does a net good, demonstrating that deserialization of Ruby objects in any form is unsafe when you can’t trust the input.

As it were we can get an idea of in-the-wild usage here, https://github.com/search?l=Ruby&p=6&q=Marshal.load&type=Cod... and it's mostly test code.

I have seen marshal show up in the bowels of gems where one wouldnt expect it, and most users obviously aren’t digging through gem sources.

I've only done Ruby half as long and yeah, this is my experience as well.

It's tough to think of a use case where anybody would even want to do this. "Hey, let's let users upload.... arbitrary binary representations.... of.... Ruby objects? And then deserialize them! YEAH! PROFIT!!!! SYNERGY!!! WOOOOOOO!!!!"

I'm trying to interpret what this means. I think it's saying that a previous result showed that `Marshal.load` on user-supplied input gave an RCE if you were running Rails (basically, see the 3 conditions under "Previous Payloads"), but the new result is that `Marshal.load` is always unsafe, with just the stdlib. Does that sound right to other folks?

`Marshal.load` was already always unsafe -- what this changes is the difficulty of writing a malicious payload.

Previously (for Marshal anyways, not sure about pickle), you would need to know a least a little bit about how the input is being used, so that you could monkeypatch one of the methods eventually used by it. This makes it possible to get RCE without any knowledge of the codebase.

Yes, that's why they are pushing the word universal...

"we want to craft a gadget chain that has no dependencies, gadgets can only be sourced from the standard library"

But, you would still need to find something that unmarshalls unstrusted input. Don't know how hard that is to find.

If you wonder how to execute code via git clone:

  $ git clone --config=core.gitProxy=awk 'git://BEGIN{system("cowsay pwned > \x2fdev\x2ftty")}/'
  Cloning into 'BEGIN{system("cowsay pwned > \x2fdev\x2ftty")}'...
  < pwned >
          \   ^__^
           \  (oo)\_______
              (__)\       )\/\
                  ||----w |
                  ||     ||
  fatal: Could not read from remote repository.
  Please make sure you have the correct access rights
  and the repository exists.

Why \x2f (in \x2fdev\x2ftty)?

Only hostname (i.e. the thing between git:// and the next slash) is passed as an argument to the proxy command, so slashes in the payload had to be escaped.

The title is kinda misleading. This should mention Payload for vulnerabilities within the Ruby libs.

That is fully captured in the notion of a universal deserialization gadget chain. However, for those not familiar with the concept of gadgets, yes, I can see how it might be a bit confusing at first.

The only known way for this to work on a Rails application was setting "Content-Type:application/xml" and then injecting the gadget chain payload to the request data like -

<bang type="yaml"> #{gadget payload} </bang>

But this has been fixed in Rails since CVE-2013-0156- https://groups.google.com/forum/#!topic/rubyonrails-security...

Is this RCE possible on Rails application having fix for CVE-2013-0156 and using Ruby versions 2 to 2.5 ?

The "RCE" acronym is only used in the title, what is it?

Remote command execution

Aha, thanks!

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | DMCA | Apply to YC | Contact