Closed jtylerorr closed 2 years ago
Thanks for raising an issue :+1:
If you still have the environment available, you could also manually specify in your Gemfile
specific versions of rex-core:
diff --git a/Gemfile b/Gemfile
index 8ff2b3d38f..cc00dfe4b5 100755
--- a/Gemfile
+++ b/Gemfile
@@ -9,6 +9,8 @@ group :coverage do
gem 'simplecov', '0.18.2'
end
+gem 'rex-core', '0.1.21'
+
group :development do
# Markdown formatting for yard
gem 'redcarpet'
(END)
Followed by an explicit update:
bundle update rex-core
Which should generate a new Gemfile.lock:
diff --git a/Gemfile.lock b/Gemfile.lock
index e562d74c42..b8ea332300 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -364,7 +364,7 @@ GEM
rex-core
rex-struct2
rex-text
- rex-core (0.1.28)
+ rex-core (0.1.22)
rex-encoder (0.1.6)
metasm
rex-arch
@@ -526,6 +526,7 @@ DEPENDENCIES
pry-byebug
rake
redcarpet
+ rex-core (= 0.1.22)
rspec-rails
rspec-rerun
rubocop
It looks like rex-core 0.1.21 was just a small utility script, so it is most likely 0.1.22-0.1.25 that caused the issue I think π€
@adfoster-r7 - Thanks for the quick response.
I tested with rex-core
versions 0.1.21
-0.1.25
using the method you described above. While it's difficult to conclusively prove absence of the bug, it does seem very likely that it is introduced in rex-core 0.1.25
.
For reference: rex-core 0.1.25 diff
If downgrading rex-core is a sufficient fix for metasploit-framework it would be great to have it merged in ASAP and possibly have a bug reported to the rex-core project. However, it is unclear to me if any parts of metasploit-framework are dependent on newer versions of rex-core.
The rex-core 0.1.25 release was aimed to fix an issue with reverse portfwd over here - https://github.com/rapid7/metasploit-framework/issues/15968
I'm not sure why that fix would impact the RPC API just yet though π€
I noticed the same problem after the update to version 6.1.43.
When I execute a "console.write" call to the RPC server sometimes it succeeds other times it fails (returning null to the field of bytes written). The success/failure would seem to be completely random.
Hi!
This issue has been left open with no activity for a while now.
We get a lot of issues, so we currently close issues after 60 days of inactivity. Itβs been at least 30 days since the last update here. If we missed this issue or if you want to keep it open, please reply here. You can also add the label "not stale" to keep this issue open!
As a friendly reminder: the best way to see this issue, or any other, fixed is to open a Pull Request.
I've noticed the same problem when running auxiliary/scanner/snmp/snmp_login
through the RPC API.
I'm on version 6.1.27-dev and rex-core 0.1.25.
The module will succeed about 80% of the time, the other 20% is a mix of failures with no output and some with truncated output.
Confirmed with shorter replication steps
Start the daemon in the foreground:
export MSF_USERNAME=username
export MSF_PASSWORD=password
./msfrpcd -U ${MSF_USERNAME} -P ${MSF_PASSWORD} -a 127.0.0.1 -f
Connect a client:
export MSF_USERNAME=username
export MSF_PASSWORD=password
./msfrpc -U ${MSF_USERNAME} -P ${MSF_PASSWORD} -a 127.0.0.1
In the client - create a console, and write/read to it:
>> console = rpc.call('console.create')['id']; sleep 1; 10.times { puts("Write result: #{rpc.call('console.write', console, "version\n")}"); puts("Read result: #{rpc.call('console.read', console)}"); }
Output on latest release 6.2.9, with rex-core 0.1.25
Write result: {"wrote"=>8}
Read result: {"data"=>"\n ______________________________________________________________________________\n| |\n| METASPLOIT CYBER MISSILE COMMAND V5 |\n|______________________________________________________________________________|\n \\ / /\n \\ . / / x\n \\ / /\n \\ / + /\n \\ + / /\n * / /\n / . /\n X / / X\n / ###\n / # % #\n / ###\n . /\n . / . * .\n /\n *\n + *\n\n ^\n#### __ __ __ ####### __ __ __ ####\n#### / \\ / \\ / \\ ########### / \\ / \\ / \\ ####\n################################################################################\n################################################################################\n# WAVE 5 ######## SCORE 31337 ################################## HIGH FFFFFFFF #\n################################################################################\n https://metasploit.com\n\n\n =[ metasploit v6.2.9-dev-4bbae96840 ]\n+ -- --=[ 2230 exploits - 1177 auxiliary - 398 post ]\n+ -- --=[ 864 payloads - 45 encoders - 11 nops ]\n+ -- --=[ 9 evasion ]\n\nMetasploit tip: Save the current environment with the \nsave command, future console restarts will use this \nenvironment again\n\nFramework: 6.2.9-dev-4bbae96840\nConsole : 6.2.9-dev-4bbae96840\n", "prompt"=>"msf6 auxiliary(scanner/vnc/vnc_login) > ", "busy"=>false}
Write result: {"wrote"=>8}
Read result: {"data"=>"Framework: 6.2.9-dev-4bbae96840\nConsole : 6.2.9-dev-4bbae96840\n", "prompt"=>"msf6 auxiliary(scanner/vnc/vnc_login) > ", "busy"=>false}
Write result: {"wrote"=>8}
Read result: {"data"=>"", "prompt"=>"msf6 auxiliary(scanner/vnc/vnc_login) > ", "busy"=>false}
Write result: {"wrote"=>nil}
Read result: {"data"=>"", "prompt"=>"msf6 auxiliary(scanner/vnc/vnc_login) > ", "busy"=>false}
Write result: {"wrote"=>nil}
Read result: {"data"=>"", "prompt"=>"msf6 auxiliary(scanner/vnc/vnc_login) > ", "busy"=>false}
Write result: {"wrote"=>nil}
Read result: {"data"=>"", "prompt"=>"msf6 auxiliary(scanner/vnc/vnc_login) > ", "busy"=>false}
Write result: {"wrote"=>nil}
Read result: {"data"=>"", "prompt"=>"msf6 auxiliary(scanner/vnc/vnc_login) > ", "busy"=>false}
Write result: {"wrote"=>nil}
Read result: {"data"=>"", "prompt"=>"msf6 auxiliary(scanner/vnc/vnc_login) > ", "busy"=>false}
Write result: {"wrote"=>nil}
Read result: {"data"=>"", "prompt"=>"msf6 auxiliary(scanner/vnc/vnc_login) > ", "busy"=>false}
Write result: {"wrote"=>nil}
Read result: {"data"=>"", "prompt"=>"msf6 auxiliary(scanner/vnc/vnc_login) > ", "busy"=>false}
Expected output, when running gem rex-core 0.1.24
>> console = rpc.call('console.create')['id']; 10.times { puts("Write result: #{rpc.call('console.write', console, "version\n")}"); puts("Read result: #{rpc.c
all('console.read', console)}"); }
Write result: {"wrote"=>8}
Read result: {"data"=>"\nUnable to handle kernel NULL pointer dereference at virtual address 0xd34db33f\nEFLAGS: 00010046\neax: 00000001 ebx: f77c8c00 ecx: 00000000 edx: f77f0001\nesi: 803bf014 edi: 8023c755 ebp: 80237f84 esp: 80237f60\nds: 0018 es: 0018 ss: 0018\nProcess Swapper (Pid: 0, process nr: 0, stackpage=80377000)\n\n\nStack: 90909090990909090990909090\n 90909090990909090990909090\n 90909090.90909090.90909090\n 90909090.90909090.90909090\n 90909090.90909090.09090900\n 90909090.90909090.09090900\n ..........................\n cccccccccccccccccccccccccc\n cccccccccccccccccccccccccc\n ccccccccc.................\n cccccccccccccccccccccccccc\n cccccccccccccccccccccccccc\n .................ccccccccc\n cccccccccccccccccccccccccc\n cccccccccccccccccccccccccc\n ..........................\n ffffffffffffffffffffffffff\n ffffffff..................\n ffffffffffffffffffffffffff\n ffffffff..................\n ffffffff..................\n ffffffff..................\n\n\nCode: 00 00 00 00 M3 T4 SP L0 1T FR 4M 3W OR K! V3 R5 I0 N5 00 00 00 00\nAiee, Killing Interrupt handler\nKernel panic: Attempted to kill the idle task!\nIn swapper task - not syncing\n\n\n =[ metasploit v6.2.9-dev-4bbae96840 ]\n+ -- --=[ 2230 exploits - 1177 auxiliary - 398 post ]\n+ -- --=[ 864 payloads - 45 encoders - 11 nops ]\n+ -- --=[ 9 evasion ]\n\nMetasploit tip: View missing module options with show \nmissing\n\nFramework: 6.2.9-dev-4bbae96840\nConsole : 6.2.9-dev-4bbae96840\n", "prompt"=>"msf6 auxiliary(scanner/vnc/vnc_login) > ", "busy"=>false}
Write result: {"wrote"=>8}
Read result: {"data"=>"Framework: 6.2.9-dev-4bbae96840\nConsole : 6.2.9-dev-4bbae96840\n", "prompt"=>"msf6 auxiliary(scanner/vnc/vnc_login) > ", "busy"=>false}
Write result: {"wrote"=>8}
Read result: {"data"=>"Framework: 6.2.9-dev-4bbae96840\nConsole : 6.2.9-dev-4bbae96840\n", "prompt"=>"msf6 auxiliary(scanner/vnc/vnc_login) > ", "busy"=>false}
Write result: {"wrote"=>8}
Read result: {"data"=>"Framework: 6.2.9-dev-4bbae96840\nConsole : 6.2.9-dev-4bbae96840\n", "prompt"=>"msf6 auxiliary(scanner/vnc/vnc_login) > ", "busy"=>false}
Write result: {"wrote"=>8}
Read result: {"data"=>"Framework: 6.2.9-dev-4bbae96840\nConsole : 6.2.9-dev-4bbae96840\n", "prompt"=>"msf6 auxiliary(scanner/vnc/vnc_login) > ", "busy"=>false}
Write result: {"wrote"=>8}
Read result: {"data"=>"Framework: 6.2.9-dev-4bbae96840\nConsole : 6.2.9-dev-4bbae96840\n", "prompt"=>"msf6 auxiliary(scanner/vnc/vnc_login) > ", "busy"=>false}
Write result: {"wrote"=>8}
Read result: {"data"=>"Framework: 6.2.9-dev-4bbae96840\nConsole : 6.2.9-dev-4bbae96840\n", "prompt"=>"msf6 auxiliary(scanner/vnc/vnc_login) > ", "busy"=>false}
Write result: {"wrote"=>8}
Read result: {"data"=>"Framework: 6.2.9-dev-4bbae96840\nConsole : 6.2.9-dev-4bbae96840\n", "prompt"=>"msf6 auxiliary(scanner/vnc/vnc_login) > ", "busy"=>false}
Write result: {"wrote"=>8}
Read result: {"data"=>"Framework: 6.2.9-dev-4bbae96840\nConsole : 6.2.9-dev-4bbae96840\n", "prompt"=>"msf6 auxiliary(scanner/vnc/vnc_login) > ", "busy"=>false}
Write result: {"wrote"=>8}
Read result: {"data"=>"Framework: 6.2.9-dev-4bbae96840\nConsole : 6.2.9-dev-4bbae96840\n", "prompt"=>"msf6 auxiliary(scanner/vnc/vnc_login) > ", "busy"=>false}
Verified synchronously without the need for running an actual RPC service.
Running in bundle exec irb
or bundle exec ruby ./example.rb
require 'pathname'
require Pathname.new(__dir__).realpath.expand_path.join('config', 'boot')
require 'msfenv'
framework ||= Msf::Simple::Framework.create; service = OpenStruct.new(framework: framework); rpc = Msf::RPC::RPC_Console.new(service); console = rpc.rpc_create({ 'DisableBanner' => true })['id']; 10.times { puts("Write result: #{rpc.rpc_write(console, "version\n")}"); sleep 0.5; puts("Read result: #{rpc.rpc_read(console)}"); }
rex-core 0.1.24 successful:
3.0.2 :015 > framework ||= Msf::Simple::Framework.create; service = OpenStruct.new(framework: framework); rpc = Msf::RPC::RPC_Console.new(service); console = rpc.rpc_create({ 'DisableBanner' => true })['id'];
10.times { puts("Write result: #{rpc.rpc_write(console, "version\n")}"); sleep 0.5; puts("Read result: #{rpc.rpc_read(console)}"); }
Write result: {"wrote"=>8}
Read result: {"data"=>"Framework: 6.2.9-dev-4bbae96840\nConsole : 6.2.9-dev-4bbae96840\n", "prompt"=>"msf6 auxiliary(scanner/vnc/vnc_login) > ", "busy"=>false}
Write result: {"wrote"=>8}
Read result: {"data"=>"Framework: 6.2.9-dev-4bbae96840\nConsole : 6.2.9-dev-4bbae96840\n", "prompt"=>"msf6 auxiliary(scanner/vnc/vnc_login) > ", "busy"=>false}
Write result: {"wrote"=>8}
Read result: {"data"=>"Framework: 6.2.9-dev-4bbae96840\nConsole : 6.2.9-dev-4bbae96840\n", "prompt"=>"msf6 auxiliary(scanner/vnc/vnc_login) > ", "busy"=>false}
Write result: {"wrote"=>8}
Read result: {"data"=>"Framework: 6.2.9-dev-4bbae96840\nConsole : 6.2.9-dev-4bbae96840\n", "prompt"=>"msf6 auxiliary(scanner/vnc/vnc_login) > ", "busy"=>false}
Write result: {"wrote"=>8}
Read result: {"data"=>"Framework: 6.2.9-dev-4bbae96840\nConsole : 6.2.9-dev-4bbae96840\n", "prompt"=>"msf6 auxiliary(scanner/vnc/vnc_login) > ", "busy"=>false}
Write result: {"wrote"=>8}
Read result: {"data"=>"Framework: 6.2.9-dev-4bbae96840\nConsole : 6.2.9-dev-4bbae96840\n", "prompt"=>"msf6 auxiliary(scanner/vnc/vnc_login) > ", "busy"=>false}
Write result: {"wrote"=>8}
Read result: {"data"=>"Framework: 6.2.9-dev-4bbae96840\nConsole : 6.2.9-dev-4bbae96840\n", "prompt"=>"msf6 auxiliary(scanner/vnc/vnc_login) > ", "busy"=>false}
Write result: {"wrote"=>8}
Read result: {"data"=>"Framework: 6.2.9-dev-4bbae96840\nConsole : 6.2.9-dev-4bbae96840\n", "prompt"=>"msf6 auxiliary(scanner/vnc/vnc_login) > ", "busy"=>false}
Write result: {"wrote"=>8}
Read result: {"data"=>"Framework: 6.2.9-dev-4bbae96840\nConsole : 6.2.9-dev-4bbae96840\n", "prompt"=>"msf6 auxiliary(scanner/vnc/vnc_login) > ", "busy"=>false}
Write result: {"wrote"=>8}
Read result: {"data"=>"Framework: 6.2.9-dev-4bbae96840\nConsole : 6.2.9-dev-4bbae96840\n", "prompt"=>"msf6 auxiliary(scanner/vnc/vnc_login) > ", "busy"=>false}
rex-core 0.1.25 failing:
3.0.2 :007 > framework ||= Msf::Simple::Framework.create; service = OpenStruct.new(framework: framework); rpc = Msf::RPC::RPC_Console.new(service); console = rpc.rpc_create({ 'DisableBanner' => true })['id'];
10.times { puts("Write result: #{rpc.rpc_write(console, "version\n")}"); sleep 0.5; puts("Read result: #{rpc.rpc_read(console)}"); }
Write result: {"wrote"=>8}
Read result: {"data"=>"Framework: 6.2.9-dev-4bbae96840\nConsole : 6.2.9-dev-4bbae96840\n", "prompt"=>"msf6 auxiliary(scanner/vnc/vnc_login) > ", "busy"=>false}
Write result: {"wrote"=>8}
Read result: {"data"=>"Framework: 6.2.9-dev-4bbae96840\nConsole : 6.2.9-dev-4bbae96840\n", "prompt"=>"msf6 auxiliary(scanner/vnc/vnc_login) > ", "busy"=>false}
Write result: {"wrote"=>8}
Read result: {"data"=>"Framework: 6.2.9-dev-4bbae96840\nConsole : 6.2.9-dev-4bbae96840\n", "prompt"=>"msf6 auxiliary(scanner/vnc/vnc_login) > ", "busy"=>false}
Write result: {"wrote"=>8}
Read result: {"data"=>"Framework: 6.2.9-dev-4bbae96840\nConsole : 6.2.9-dev-4bbae96840\n", "prompt"=>"msf6 auxiliary(scanner/vnc/vnc_login) > ", "busy"=>false}
Write result: {"wrote"=>8}
Read result: {"data"=>"Framework: 6.2.9-dev-4bbae96840\nConsole : 6.2.9-dev-4bbae96840\n", "prompt"=>"msf6 auxiliary(scanner/vnc/vnc_login) > ", "busy"=>false}
Write result: {"wrote"=>8}
Read result: {"data"=>"Framework: 6.2.9-dev-4bbae96840\nConsole : 6.2.9-dev-4bbae96840\n", "prompt"=>"msf6 auxiliary(scanner/vnc/vnc_login) > ", "busy"=>false}
Write result: {"wrote"=>8}
Read result: {"data"=>"", "prompt"=>"msf6 auxiliary(scanner/vnc/vnc_login) > ", "busy"=>false}
Write result: {"wrote"=>nil}
Read result: {"data"=>"", "prompt"=>"msf6 auxiliary(scanner/vnc/vnc_login) > ", "busy"=>false}
Write result: {"wrote"=>nil}
Read result: {"data"=>"", "prompt"=>"msf6 auxiliary(scanner/vnc/vnc_login) > ", "busy"=>false}
Write result: {"wrote"=>nil}
Read result: {"data"=>"", "prompt"=>"msf6 auxiliary(scanner/vnc/vnc_login) > ", "busy"=>false}
Stacktrace from error log tail -f ~/.msf4/logs/framework.log
I've created a pull request up to hopefully fix this issue https://github.com/rapid7/metasploit-framework/pull/16822 - let me know if that works for you π
I've created a pull request up to hopefully fix this issue #16822 - let me know if that works for you π
@adfoster-r7 I pulled down your branch and ran it, the behavior I'm seeing is that when I first run msfrpcd ./msfrpcd -P PASSWORD -a 127.0.0.1 -f -S
my attempts to run snmp_login
fail anywhere between 10-45 times then it seems to work 100% of the time.
@rasheed-rd Thanks for taking a look! I believe your issue is different than the original error report then - as you said in your original replication steps from https://github.com/rapid7/metasploit-framework/pull/16812#issuecomment-1194304318
1- I pulled the latest metasploit docker image (Framework Version: 6.0.55-dev) and ran it starting msfrpcd.
6.0.55 is quite old, almost a year ago. The version is from before this regression/bug was introduced by rex-core 0.1.25 - Metasploit 6.1.27. I've created a separate issue for tracking the effort of building newer Docker builds over here - https://github.com/rapid7/metasploit-framework/issues/16826
I'll need to see if I can replicate your snmp_login issue, but I have a feeling it might be a race condition in your Python script rather than metasploit-framework.
For context - I think you may need to update your Python script to handle reading until busy is True at least once, or data is available and Busy is False. I believe there's a small period of time between writing a command to the console, and the command actually executing and being marked as 'busy'
@rasheed-rd It looks like pymetasploit has that logic in place already via the run_module_with_output
method:
https://github.com/DanMcInerney/pymetasploit3/blob/9776da55b0abacfa843a32204f3972ec7d9b3de7/pymetasploit3/msfrpc.py#L2258-L2267
So I believe you'd want something similar there in your own script :+1:
@adfoster-r7 Thanks for the explanation. It work perfectly after updating my script!
Overview
Beginning with version
6.1.27
, interactions with Metasploit throughmsfrpcd
are unreliable, and sometimes result in output being truncated, input being accepted but discarded, and no error being reported to the RPC client.I have narrowed down the cause of the issue to be the
rex-core
version update between6.1.26
and6.1.27
. Manually revertingrex-core
back to version0.1.20
, as used in MSF6.1.26
, fixes the buggy behavior.The issue is difficult to reliably reproduce and may require stepping through the procedure several times. Some exploits, like the one listed, seemed to produce the buggy behavior more reliably. I have confirmed the behavior with the following exploit modules, but it likely works with others:
Steps to reproduce
Start from a freshly cloned copy of
metasploit-framework
(currently version 6.1.42)Start
msfrpcd
andmsfrpc
NOTE: The exploit used in the following example was the most likely to produce the buggy behavior in my experience. However, the problem affects a wide array of exploit modules. The behavior was observed when testing against a target that was intentionally made vulnerable to the exploit (and for which the exploit succeeded using MSF <=6.1.26). Be sure to adjust options to fit your test environment.
Many of the options set in the following call are default options for the module. They are explicitly set by some libraries such as
pymetasploit3
, so I explicitly set them when usingmsfrpc
. This is likely not necessary to reproduce the buggy behavior."busy"=>false
.{"wrote"=>nil}
.Were you following a specific guide/tutorial or reading documentation?
No.
Expected behavior
This is described in detail in the steps to reproduce.
Using a reliable exploit against an intentionally vulnerable target, the exploit should always succeed in creating a meterpreter session.
Current behavior
This is described in detail in the steps to reproduce.
Even when using a reliable exploit against an intentionally vulnerable target, the console will sometimes truncate output and become non-responsive.
Metasploit version
This behavior is observed in version 6.1.27-6.1.42(current).
Additional Information
I have narrowed down the cause of the problem to being the version of dependency
rex-core
. In MSF version 6.1.26, rex-core version 0.1.20 is used. In MSF version 6.1.27, rex-core version 0.1.25 is used.For any version of MSF >= 6.1.27, manually downgrading rex-core to version 0.1.20 using the following commands removes the observed buggy behavior.
However, since I am not familiar with the metasploit-framework source code, I do not know if this dependency change will introduce other bugs.