rapid7 / ruby_smb

A native Ruby implementation of the SMB Protocol Family
Other
79 stars 82 forks source link

Add double splat operator for ruby 3.0.1 support #173

Closed adfoster-r7 closed 3 years ago

adfoster-r7 commented 3 years ago

Fixes a Ruby 3.0.1 issue for metasploit console when attempting to enumerate shares:

msf6 auxiliary(scanner/smb/smb_enumshares) > run

[-] 192.168.222.151:139   - Login Failed: Unable to negotiate SMB1 with the remote host: Not a valid SMB packet
[-] 192.168.222.151:      - Auxiliary failed: ArgumentError wrong number of arguments (given 1, expected 0; required keyword: filename)
[-] 192.168.222.151:      - Call stack:
[-] 192.168.222.151:      -   /Users/user/.rvm/gems/ruby-3.0.1/gems/ruby_smb-2.0.9/lib/ruby_smb/smb2/tree.rb:67:in `open_file'
[-] 192.168.222.151:      -   /Users/user/.rvm/gems/ruby-3.0.1/gems/ruby_smb-2.0.9/lib/ruby_smb/smb2/tree.rb:64:in `open_pipe'
[-] 192.168.222.151:      -   /Users/user/.rvm/gems/ruby-3.0.1/gems/ruby_smb-2.0.9/lib/ruby_smb/client/utils.rb:29:in `open'
[-] 192.168.222.151:      -   /Users/user/.rvm/gems/ruby-3.0.1/gems/ruby_smb-2.0.9/lib/ruby_smb/client/utils.rb:45:in `create_pipe'
[-] 192.168.222.151:      -   /Users/user/Documents/code/metasploit-framework/lib/rex/proto/smb/simple_client.rb:232:in `create_pipe'
[-] 192.168.222.151:      -   /Users/user/Documents/code/metasploit-framework/lib/rex/proto/dcerpc/client.rb:124:in `smb_connect'
[-] 192.168.222.151:      -   /Users/user/Documents/code/metasploit-framework/lib/rex/proto/dcerpc/client.rb:62:in `socket_check'
[-] 192.168.222.151:      -   /Users/user/Documents/code/metasploit-framework/lib/rex/proto/dcerpc/client.rb:37:in `initialize'
[-] 192.168.222.151:      -   /Users/user/Documents/code/metasploit-framework/lib/msf/core/exploit/remote/dcerpc.rb:120:in `new'
[-] 192.168.222.151:      -   /Users/user/Documents/code/metasploit-framework/lib/msf/core/exploit/remote/dcerpc.rb:120:in `dcerpc_bind'
[-] 192.168.222.151:      -   /Users/user/Documents/code/metasploit-framework/lib/msf/core/exploit/remote/smb/client.rb:751:in `smb_srvsvc_netshareenumall'
[-] 192.168.222.151:      -   /Users/user/Documents/code/metasploit-framework/lib/msf/core/exploit/remote/smb/client.rb:736:in `smb_netshareenumall'
[-] 192.168.222.151:      -   /Users/user/Documents/code/metasploit-framework/modules/auxiliary/scanner/smb/smb_enumshares.rb:335:in `block in run_host'
[-] 192.168.222.151:      -   /Users/user/Documents/code/metasploit-framework/modules/auxiliary/scanner/smb/smb_enumshares.rb:328:in `each'
[-] 192.168.222.151:      -   /Users/user/Documents/code/metasploit-framework/modules/auxiliary/scanner/smb/smb_enumshares.rb:328:in `run_host'
[-] 192.168.222.151:      -   /Users/user/Documents/code/metasploit-framework/lib/msf/core/auxiliary/scanner.rb:121:in `block (2 levels) in run'
[-] 192.168.222.151:      -   /Users/user/Documents/code/metasploit-framework/lib/msf/core/thread_manager.rb:105:in `block in spawn'
[*] Auxiliary module execution completed
msf6 auxiliary(scanner/smb/smb_enumshares) > 

This code path was being exercised within the rspec test suite, however, they're wrapped in rspec 'expect(...).to receive(opts)` - so they were passing, when they shouldn't have been.

Article: https://www.ruby-lang.org/en/news/2019/12/12/separation-of-positional-and-keyword-arguments-in-ruby-3-0/

I tested framework and ruby_smb together by updating the gemfile to point to my local directory and rerunning bundle

# metasploit-framework/Gemfile
gem 'ruby_smb', path: '../ruby_smb'
smcintyre-r7 commented 3 years ago

Well I was going to test this but I'm having trouble getting Metasploit to start with Ruby 3.0.0 as installed from RVM. I had to remove pcaprub-0.13.0 because that "requires ruby version ~> 2.0", after which I got the stack trace referenced below.

msfconsole Stack Trace ```  !: metasploit-framework: 14:45:46 ~-msf rvm info ruby-3.0.0: system: uname: "Linux localhost.localdomain 5.11.22-100.fc32.x86_64 #1 SMP Wed May 19 18:58:25 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux" name: "Fedora" version: "32" architecture: "x86_64" bash: "/usr/bin/bash => GNU bash, version 5.0.17(1)-release (x86_64-redhat-linux-gnu)" zsh: "/usr/bin/zsh => zsh 5.8 (x86_64-redhat-linux-gnu)" remote_path: "fedora/32/x86_64" rvm: version: "1.29.12 (latest)" updated: "3 months 26 days 4 hours 13 minutes 12 seconds ago" path: "/home/smcintyre/.rvm" autolibs: "[4] Allow RVM to use package manager if found, install missing dependencies, install package manager (only OS X)." ruby: interpreter: "ruby" version: "3.0.0p0" date: "2020-12-25" platform: "x86_64-linux" patchlevel: "2020-12-25 revision 95aff21468" full_version: "ruby 3.0.0p0 (2020-12-25 revision 95aff21468) [x86_64-linux]" homes: gem: "/home/smcintyre/.rvm/gems/ruby-3.0.0" ruby: "/home/smcintyre/.rvm/rubies/ruby-3.0.0" binaries: ruby: "/home/smcintyre/.rvm/rubies/ruby-3.0.0/bin/ruby" irb: "/home/smcintyre/.rvm/gems/ruby-3.0.0/bin/irb" gem: "/home/smcintyre/.rvm/rubies/ruby-3.0.0/bin/gem" rake: "/home/smcintyre/.rvm/gems/ruby-3.0.0/bin/rake" environment: PATH: "/home/smcintyre/.rvm/gems/ruby-3.0.0/bin:/home/smcintyre/.rvm/gems/ruby-3.0.0@global/bin:/home/smcintyre/.rvm/rubies/ruby-3.0.0/bin:/home/smcintyre/.rvm/bin:/home/smcintyre/.pyenv/shims:/home/smcintyre/.pyenv/bin:/usr/share/Modules/bin:/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/usr/local/sbin:/home/smcintyre/bin:/var/lib/snapd/snap/bin:/usr/local/sbin:/home/smcintyre/.local/bin" GEM_HOME: "/home/smcintyre/.rvm/gems/ruby-3.0.0" GEM_PATH: "/home/smcintyre/.rvm/gems/ruby-3.0.0:/home/smcintyre/.rvm/gems/ruby-3.0.0@global" MY_RUBY_HOME: "/home/smcintyre/.rvm/rubies/ruby-3.0.0" IRBRC: "/home/smcintyre/.rvm/rubies/ruby-3.0.0/.irbrc" RUBYOPT: "" gemset: ""  !: metasploit-framework: 14:47:09 ~-msf bundle exec ./msfconsole bundler: failed to load command: ./msfconsole (./msfconsole) /home/smcintyre/.rvm/gems/ruby-3.0.0/gems/actionpack-5.2.6/lib/action_dispatch/middleware/static.rb:111:in `initialize': wrong number of arguments (given 3, expected 2) (ArgumentError) from /home/smcintyre/.rvm/gems/ruby-3.0.0/gems/actionpack-5.2.6/lib/action_dispatch/middleware/stack.rb:37:in `new' from /home/smcintyre/.rvm/gems/ruby-3.0.0/gems/actionpack-5.2.6/lib/action_dispatch/middleware/stack.rb:37:in `build' from /home/smcintyre/.rvm/gems/ruby-3.0.0/gems/actionpack-5.2.6/lib/action_dispatch/middleware/stack.rb:101:in `block in build' from /home/smcintyre/.rvm/gems/ruby-3.0.0/gems/actionpack-5.2.6/lib/action_dispatch/middleware/stack.rb:101:in `each' from /home/smcintyre/.rvm/gems/ruby-3.0.0/gems/actionpack-5.2.6/lib/action_dispatch/middleware/stack.rb:101:in `inject' from /home/smcintyre/.rvm/gems/ruby-3.0.0/gems/actionpack-5.2.6/lib/action_dispatch/middleware/stack.rb:101:in `build' from /home/smcintyre/.rvm/gems/ruby-3.0.0/gems/railties-5.2.6/lib/rails/engine.rb:510:in `block in app' from /home/smcintyre/.rvm/gems/ruby-3.0.0/gems/railties-5.2.6/lib/rails/engine.rb:506:in `synchronize' from /home/smcintyre/.rvm/gems/ruby-3.0.0/gems/railties-5.2.6/lib/rails/engine.rb:506:in `app' from /home/smcintyre/.rvm/gems/ruby-3.0.0/gems/railties-5.2.6/lib/rails/application/finisher.rb:47:in `block in ' from /home/smcintyre/.rvm/gems/ruby-3.0.0/gems/railties-5.2.6/lib/rails/initializable.rb:32:in `instance_exec' from /home/smcintyre/.rvm/gems/ruby-3.0.0/gems/railties-5.2.6/lib/rails/initializable.rb:32:in `run' from /home/smcintyre/.rvm/gems/ruby-3.0.0/gems/railties-5.2.6/lib/rails/initializable.rb:61:in `block in run_initializers' from /home/smcintyre/.rvm/rubies/ruby-3.0.0/lib/ruby/3.0.0/tsort.rb:228:in `block in tsort_each' from /home/smcintyre/.rvm/rubies/ruby-3.0.0/lib/ruby/3.0.0/tsort.rb:350:in `block (2 levels) in each_strongly_connected_component' from /home/smcintyre/.rvm/rubies/ruby-3.0.0/lib/ruby/3.0.0/tsort.rb:431:in `each_strongly_connected_component_from' from /home/smcintyre/.rvm/rubies/ruby-3.0.0/lib/ruby/3.0.0/tsort.rb:349:in `block in each_strongly_connected_component' from /home/smcintyre/.rvm/rubies/ruby-3.0.0/lib/ruby/3.0.0/tsort.rb:347:in `each' from /home/smcintyre/.rvm/rubies/ruby-3.0.0/lib/ruby/3.0.0/tsort.rb:347:in `call' from /home/smcintyre/.rvm/rubies/ruby-3.0.0/lib/ruby/3.0.0/tsort.rb:347:in `each_strongly_connected_component' from /home/smcintyre/.rvm/rubies/ruby-3.0.0/lib/ruby/3.0.0/tsort.rb:226:in `tsort_each' from /home/smcintyre/.rvm/rubies/ruby-3.0.0/lib/ruby/3.0.0/tsort.rb:205:in `tsort_each' from /home/smcintyre/.rvm/gems/ruby-3.0.0/gems/railties-5.2.6/lib/rails/initializable.rb:60:in `run_initializers' from /home/smcintyre/.rvm/gems/ruby-3.0.0/gems/railties-5.2.6/lib/rails/application.rb:361:in `initialize!' from /home/smcintyre/.rvm/gems/ruby-3.0.0/gems/railties-5.2.6/lib/rails/railtie.rb:190:in `public_send' from /home/smcintyre/.rvm/gems/ruby-3.0.0/gems/railties-5.2.6/lib/rails/railtie.rb:190:in `method_missing' from /home/smcintyre/Repositories/metasploit-framework/config/environment.rb:4:in `' from /home/smcintyre/Repositories/metasploit-framework/lib/msfenv.rb:17:in `require' from /home/smcintyre/Repositories/metasploit-framework/lib/msfenv.rb:17:in `' from /home/smcintyre/Repositories/metasploit-framework/msfconsole:18:in `require' from /home/smcintyre/Repositories/metasploit-framework/msfconsole:18:in `' from /home/smcintyre/.rvm/rubies/ruby-3.0.0/lib/ruby/3.0.0/bundler/cli/exec.rb:63:in `load' from /home/smcintyre/.rvm/rubies/ruby-3.0.0/lib/ruby/3.0.0/bundler/cli/exec.rb:63:in `kernel_load' from /home/smcintyre/.rvm/rubies/ruby-3.0.0/lib/ruby/3.0.0/bundler/cli/exec.rb:28:in `run' from /home/smcintyre/.rvm/rubies/ruby-3.0.0/lib/ruby/3.0.0/bundler/cli.rb:497:in `exec' from /home/smcintyre/.rvm/rubies/ruby-3.0.0/lib/ruby/3.0.0/bundler/vendor/thor/lib/thor/command.rb:27:in `run' from /home/smcintyre/.rvm/rubies/ruby-3.0.0/lib/ruby/3.0.0/bundler/vendor/thor/lib/thor/invocation.rb:127:in `invoke_command' from /home/smcintyre/.rvm/rubies/ruby-3.0.0/lib/ruby/3.0.0/bundler/vendor/thor/lib/thor.rb:392:in `dispatch' from /home/smcintyre/.rvm/rubies/ruby-3.0.0/lib/ruby/3.0.0/bundler/cli.rb:30:in `dispatch' from /home/smcintyre/.rvm/rubies/ruby-3.0.0/lib/ruby/3.0.0/bundler/vendor/thor/lib/thor/base.rb:485:in `start' from /home/smcintyre/.rvm/rubies/ruby-3.0.0/lib/ruby/3.0.0/bundler/cli.rb:24:in `start' from /home/smcintyre/.rvm/rubies/ruby-3.0.0/lib/ruby/gems/3.0.0/gems/bundler-2.2.3/libexec/bundle:49:in `block in ' from /home/smcintyre/.rvm/rubies/ruby-3.0.0/lib/ruby/3.0.0/bundler/friendly_errors.rb:130:in `with_friendly_errors' from /home/smcintyre/.rvm/rubies/ruby-3.0.0/lib/ruby/gems/3.0.0/gems/bundler-2.2.3/libexec/bundle:37:in `' from /home/smcintyre/.rvm/rubies/ruby-3.0.0/bin/bundle:23:in `load' from /home/smcintyre/.rvm/rubies/ruby-3.0.0/bin/bundle:23:in `
' from /home/smcintyre/.rvm/gems/ruby-3.0.0/bin/ruby_executable_hooks:22:in `eval' from /home/smcintyre/.rvm/gems/ruby-3.0.0/bin/ruby_executable_hooks:22:in `
' exit status: 1   !: metasploit-framework: 14:47:14 ~-msf  ```

I see the unit tests pass when run by the automation, but I can't seem to reproduce that either. For what it's worth, it looks like the same tests are failing on both master and this PR branch when run with Ruby 3.0.0, however, when I run the tests from both branches with Ruby 2.7.2, there are no errors. Is that expected at this time?

Do you have any more details that might help with testing this?

adfoster-r7 commented 3 years ago

@smcintyre-r7 Did you try with Ruby 3.0.1 on this branch, rather than 3.0.0?

Apologies, I thought you meant in isolation you tried the ruby_smb tests with Ruby 3.0.0. If you want to test change fixes metasploit console to work you'll need:

adfoster-r7 commented 3 years ago

Note ruby_smb doesn't work with 3.0.0, only 3.0.1 due to a bug in Ruby's hash implementation which causes a bug in the bindata library

smcintyre-r7 commented 3 years ago

Thanks alot, those steps did the trick. Using Ruby 3.0.1 this time I was able to reproduce the original issue without these changes as well as confirm that the changes fix it. I was also able to run the unit tests and confirm that they all pass.

I'll get this merged in shortly, thanks @adfoster-r7 !