diff --git a/lib/msf/core/exploit/remote/smtp_deliver.rb b/lib/msf/core/exploit/remote/smtp_deliver.rb index e5f1f49c17..d44609f8ce 100755 --- a/lib/msf/core/exploit/remote/smtp_deliver.rb +++ b/lib/msf/core/exploit/remote/smtp_deliver.rb @@ -249,7 +249,8 @@ module Exploit::Remote::SMTPDeliver while !(res =~ /(^|\r\n)\d{3}( .*|)\r\n$/) && chunk = nsock.get_once res += chunk end - rescue + raise RuntimeError.new("SMTP response is incomplete or contains extra data") unless res =~ /(^|\r\n)\d{3}( .*|)\r\n$/ + rescue EOFError return nil end # Don't truncate the server output because it might be helpful for diff --git a/spec/lib/msf/core/exploit/remote/smtp_delivery_spec.rb b/spec/lib/msf/core/exploit/remote/smtp_delivery_spec.rb index 8ed5ece27f..60f1b5166e 100644 --- a/spec/lib/msf/core/exploit/remote/smtp_delivery_spec.rb +++ b/spec/lib/msf/core/exploit/remote/smtp_delivery_spec.rb @@ -38,6 +38,22 @@ RSpec.describe Msf::Exploit::Remote::SMTPDeliver do expect(response).to end_with(ehlo_resp3 + ehlo_resp4) end + context "when a single response occurs" do + let(:ehlo_resp1) { + "250 DSN\r\n" + } + + before { + allow(socket).to receive(:get_once).and_return(ehlo_resp1) + } + + + it "passes" do + response = instance.smtp_send_recv(cmd, socket) + expect(response).to end_with(ehlo_resp1) + end + end + context "when the server response is terse" do let(:ehlo_resp3) { "250" @@ -49,15 +65,28 @@ RSpec.describe Msf::Exploit::Remote::SMTPDeliver do end end - context "when invalid response are received" do + context "when incomplete response is received" do # a nil from `get_once` simulates a Timeout expired let(:ehlo_resp4){ nil } - it "should return the incomplete response when no data is left to read" do - response = instance.smtp_send_recv(cmd, socket) - expect(response).to end_with(ehlo_resp3) + it "should raise error when the response is incomplete" do + expect {instance.smtp_send_recv(cmd, socket)}.to raise_error RuntimeError + end + end + + context "when excess data response is received" do + # a nil from `get_once` simulates a Timeout expired + let(:ehlo_resp3){ + "250 DSN\r\n253 additional unexpected data" + } + let(:ehlo_resp4){ + nil + } + + it "should raise error when the response is incomplete" do + expect {instance.smtp_send_recv(cmd, socket)}.to raise_error RuntimeError end end end