diff --git a/lib/rex/proto/mssql/client_mixin.rb b/lib/rex/proto/mssql/client_mixin.rb index 153f582d59d2a..2c00c7ba869e1 100644 --- a/lib/rex/proto/mssql/client_mixin.rb +++ b/lib/rex/proto/mssql/client_mixin.rb @@ -79,7 +79,7 @@ def mssql_print_reply(info) ) info[:rows].each do |row| - tbl << row + tbl << row.map{ |x| x.nil? ? 'nil' : x } end print_line(tbl.to_s) @@ -206,6 +206,15 @@ def mssql_parse_tds_reply(data, info) when 50 col[:id] = :bit + when 99 + col[:id] = :ntext + col[:max_size] = data.slice!(0, 4).unpack('V')[0] + col[:codepage] = data.slice!(0, 2).unpack('v')[0] + col[:cflags] = data.slice!(0, 2).unpack('v')[0] + col[:charset_id] = data.slice!(0, 1).unpack('C')[0] + col[:namelen] = data.slice!(0, 1).unpack('C')[0] + col[:table_name] = data.slice!(0, (col[:namelen] * 2) + 1).gsub("\x00", '') + when 104 col[:id] = :bitn col[:int_size] = data.slice!(0, 1).unpack('C')[0] @@ -328,6 +337,22 @@ def mssql_parse_tds_row(data, info) end row << str.gsub("\x00", '') + when :ntext + str = nil + ptrlen = data.slice!(0, 1).unpack("C")[0] + ptr = data.slice!(0, ptrlen) + unless ptrlen == 0 + timestamp = data.slice!(0, 8) + datalen = data.slice!(0, 4).unpack("V")[0] + if datalen > 0 && datalen < 65535 + str = data.slice!(0, datalen).gsub("\x00", '') + else + str = '' + end + end + row << str + + when :datetime row << data.slice!(0, 8).unpack("H*")[0] diff --git a/modules/auxiliary/scanner/mssql/mssql_hashdump.rb b/modules/auxiliary/scanner/mssql/mssql_hashdump.rb index cfac867a4f7ba..2297eaecd7d12 100644 --- a/modules/auxiliary/scanner/mssql/mssql_hashdump.rb +++ b/modules/auxiliary/scanner/mssql/mssql_hashdump.rb @@ -79,8 +79,10 @@ def run_host(ip) unless is_sysadmin == 0 mssql_hashes = mssql_hashdump(version_year) - unless mssql_hashes.nil? + unless mssql_hashes.nil? || mssql_hashes.empty? report_hashes(mssql_hashes,version_year) + else + print_error("Unsupported SQL Version: #{version_year}") end end end @@ -93,7 +95,6 @@ def report_hashes(mssql_hashes, version_year) case version_year when "2000" hashtype = "mssql" - when "2005", "2008" hashtype = "mssql05" when "2012", "2014" diff --git a/modules/auxiliary/scanner/mssql/mssql_schemadump.rb b/modules/auxiliary/scanner/mssql/mssql_schemadump.rb index bd4f5ad9ab8d5..105f25434aa98 100644 --- a/modules/auxiliary/scanner/mssql/mssql_schemadump.rb +++ b/modules/auxiliary/scanner/mssql/mssql_schemadump.rb @@ -49,7 +49,11 @@ def run_host(ip) # Grab all the DB schema and save it as notes mssql_schema = get_mssql_schema - return nil if mssql_schema.nil? or mssql_schema.empty? + if mssql_schema.nil? or mssql_schema.empty? + print_good output if datastore['DISPLAY_RESULTS'] + print_error("Unable to retrieve schema information") + return nil + end mssql_schema.each do |db| report_note( :host => mssql_client.peerhost, diff --git a/spec/acceptance/mssql_spec.rb b/spec/acceptance/mssql_spec.rb index 7fa4adc695c46..aace4cbb12100 100644 --- a/spec/acceptance/mssql_spec.rb +++ b/spec/acceptance/mssql_spec.rb @@ -35,7 +35,7 @@ lines: { all: { required: [ - 'Instance Name:' + /Instance Name: "\w+"/, ] }, } @@ -64,8 +64,8 @@ lines: { all: { required: [ - 'Instance Name:', - 'Scanned 1 of 1 hosts (100% complete)' + /Instance Name: "\w+"/, + '[+] Microsoft SQL Server Schema', ] }, } @@ -78,9 +78,7 @@ lines: { all: { required: [ - # Default module query "Response", - # Result "Microsoft SQL Server", ] }, diff --git a/test/modules/post/test/mssql.rb b/test/modules/post/test/mssql.rb index 385b1e721ecf2..11690a615761a 100644 --- a/test/modules/post/test/mssql.rb +++ b/test/modules/post/test/mssql.rb @@ -41,6 +41,16 @@ def test_console_query end end + def test_datatypes + it "should support ntext TDS datatype" do + stdout = with_mocked_console(session) {|console| console.run_single(%{ query "select cast('foo' as ntext);"})} + ret = true + require 'pry-byebug'; binding.pry + ret &&= stdout.buf.match?(/0 foo/) + ret + end + end + def test_console_help it "should support the help command" do stdout = with_mocked_console(session) { |console| console.run_single("help") }