PageRenderTime 79ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/msf/core/exploit/ipv6.rb

https://bitbucket.org/jrossi/metasploit
Ruby | 263 lines | 170 code | 55 blank | 38 comment | 43 complexity | 6b620d6481dc93bfaf1d6f209a4df8f5 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, BSD-3-Clause
  1. ##
  2. # $Id$
  3. ##
  4. module Msf
  5. ###
  6. #
  7. # This module provides common tools for IPv6
  8. #
  9. ###
  10. module Exploit::Remote::Ipv6
  11. require 'racket'
  12. #
  13. # Initializes an instance of an exploit module that captures traffic
  14. #
  15. def initialize(info = {})
  16. super
  17. register_options(
  18. [
  19. OptString.new('INTERFACE', [false, 'The name of the interface']),
  20. OptString.new("SMAC", [ false, "The source MAC address"]),
  21. OptAddress.new("SHOST", [ false, "The source IPv6 address" ] ),
  22. OptInt.new("TIMEOUT", [ true, "Timeout when waiting for host response.", 5])
  23. ], Msf::Exploit::Remote::Ipv6
  24. )
  25. begin
  26. require 'pcaprub'
  27. @pcaprub_loaded = true
  28. rescue ::Exception => e
  29. @pcaprub_loaded = false
  30. @pcaprub_error = e
  31. end
  32. end
  33. #
  34. # Shortcut method for resolving our local interface name
  35. #
  36. def ipv6_interface(opts={})
  37. opts['INTERFACE'] || datastore['INTERFACE'] || ::Pcap.lookupdev
  38. end
  39. #
  40. # Shortcut method for determining our link-local address
  41. #
  42. def ipv6_link_address(opts={})
  43. Rex::Socket.ipv6_link_address(ipv6_interface(opts))
  44. end
  45. #
  46. # Shortcut method for determining our MAC address
  47. #
  48. def ipv6_mac(opts={})
  49. Rex::Socket.ipv6_mac(ipv6_interface(opts))
  50. end
  51. #
  52. # Opens a pcaprub capture interface to inject packets, and sniff ICMPv6 packets
  53. #
  54. def open_icmp_pcap(opts = {})
  55. check_pcaprub_loaded
  56. dev = ipv6_interface(opts)
  57. len = 65535
  58. tim = 0
  59. @ipv6_icmp6_capture = ::Pcap.open_live(dev, len, true, tim)
  60. @ipv6_icmp6_capture.setfilter("icmp6")
  61. end
  62. #
  63. # Close the capture interface
  64. #
  65. def close_icmp_pcap()
  66. check_pcaprub_loaded
  67. return if not @ipv6_icmp6_capture
  68. @ipv6_icmp6_capture = nil
  69. GC.start()
  70. end
  71. #
  72. # Send out a ICMPv6 neighbor solicitation, and
  73. # return the associated MAC address
  74. #
  75. def solicit_ipv6_mac(dhost, opts = {})
  76. check_pcaprub_loaded
  77. dhost_intf = dhost + '%' + ipv6_interface(opts)
  78. smac = opts['SMAC'] || datastore['SMAC'] || ipv6_mac
  79. shost = opts['SHOST'] || datastore['SHOST'] || Rex::Socket.source_address(dhost_intf)
  80. timeout = opts['TIMEOUT'] || datastore['TIMEOUT'] || 3
  81. open_icmp_pcap()
  82. p = Racket::Racket.new()
  83. p.l2 = Racket::L2::Ethernet.new()
  84. p.l2.src_mac = smac
  85. p.l2.dst_mac = Racket::L3::Misc.soll_mcast_mac(dhost)
  86. p.l2.ethertype = Racket::L2::Ethernet::ETHERTYPE_IPV6
  87. p.l3 = Racket::L3::IPv6.new()
  88. p.l3.src_ip = Racket::L3::Misc.ipv62long(shost)
  89. p.l3.dst_ip = Racket::L3::Misc.ipv62long(Racket::L3::Misc.soll_mcast_addr6(dhost))
  90. p.l3.ttl = 255
  91. p.l3.nhead = 0x3a
  92. p.l3.fix!()
  93. p.l4 = Racket::L4::ICMPv6NeighborSolicitation.new()
  94. p.l4.address = Racket::L3::Misc.ipv62long(dhost)
  95. p.l4.add_option(0x01, Racket::L2::Misc.mac2string(p.l2.src_mac))
  96. p.l4.fix!(p.l3.src_ip, p.l3.dst_ip)
  97. @ipv6_icmp6_capture.inject(p.pack())
  98. # Wait for a response
  99. max_epoch = ::Time.now.to_i + timeout
  100. while(::Time.now.to_i < max_epoch)
  101. pkt = @ipv6_icmp6_capture.next()
  102. next if not pkt
  103. eth = Racket::L2::Ethernet.new(pkt)
  104. next if eth.ethertype != Racket::L2::Ethernet::ETHERTYPE_IPV6
  105. ipv6 = Racket::L3::IPv6.new(eth.payload)
  106. next if ipv6.nhead != 0x3a
  107. icmpv6 = Racket::L4::ICMPv6.new(ipv6.payload)
  108. next if icmpv6.type != Racket::L4::ICMPv6Generic::ICMPv6_TYPE_NEIGHBOR_ADVERTISEMENT
  109. icmpv6 = Racket::L4::ICMPv6NeighborAdvertisement.new(ipv6.payload)
  110. if(icmpv6 and
  111. ipv6.dst_ip == Racket::L3::Misc.ipv62long(shost) and
  112. ipv6.src_ip == Racket::L3::Misc.ipv62long(dhost))
  113. icmpv6options = icmpv6.get_options()
  114. icmpv6options.each() do |opt|
  115. id = opt[1]
  116. if(id == ICMPv6OptionLinkAddress::ICMPv6_OPTION_TYPE_ID)
  117. addr = ICMPv6OptionLinkAddress.new(opt[2]).lladdr
  118. close_icmp_pcap()
  119. return(addr)
  120. end
  121. end
  122. # If there is no addr option, return the ethernet mac
  123. close_icmp_pcap()
  124. return(eth.src_mac)
  125. end
  126. end
  127. close_icmp_pcap()
  128. return(nil)
  129. end
  130. #
  131. # Send a ICMPv6 Echo Request, and wait for the
  132. # associated ICMPv6 Echo Response
  133. #
  134. def ping6(dhost, opts={})
  135. check_pcaprub_loaded
  136. dhost_intf = dhost + '%' + ipv6_interface(opts)
  137. smac = opts['SMAC'] || datastore['SMAC'] || ipv6_mac
  138. shost = opts['SHOST'] || datastore['SHOST'] || Rex::Socket.source_address(dhost_intf)
  139. dmac = opts['DMAC'] || solicit_ipv6_mac(dhost)
  140. timeout = opts['TIMEOUT'] || datastore['TIMEOUT']
  141. wait = opts['WAIT']
  142. if(wait.eql?(nil))
  143. wait = true
  144. end
  145. dmac.eql?(nil) and return false
  146. open_icmp_pcap()
  147. # Create ICMPv6 Request
  148. p = Racket::Racket.new()
  149. p.l2 = Racket::L2::Ethernet.new()
  150. p.l2.src_mac = smac
  151. p.l2.dst_mac = dmac
  152. p.l2.ethertype = Racket::L2::Ethernet::ETHERTYPE_IPV6
  153. p.l3 = Racket::L3::IPv6.new()
  154. p.l3.src_ip = Racket::L3::Misc.ipv62long(shost)
  155. p.l3.dst_ip = Racket::L3::Misc.ipv62long(dhost)
  156. p.l3.nhead = 0x3a
  157. p.l3.fix!()
  158. p.l4 = Racket::L4::ICMPv6EchoRequest.new()
  159. p.l4.id = rand(65000)
  160. p.l4.sequence = 1
  161. p.l4.payload = Rex::Text.rand_text(8)
  162. p.l4.fix!(p.l3.src_ip, p.l3.dst_ip)
  163. @ipv6_icmp6_capture.inject(p.pack())
  164. if(wait.eql?(true))
  165. print_status("Waiting for ping reply...")
  166. print_line("")
  167. # Wait for a response
  168. max_epoch = ::Time.now.to_i + timeout
  169. while(::Time.now.to_i < max_epoch)
  170. pkt = @ipv6_icmp6_capture.next()
  171. next if not pkt
  172. eth = Racket::L2::Ethernet.new(pkt)
  173. next if eth.ethertype != Racket::L2::Ethernet::ETHERTYPE_IPV6
  174. ipv6 = Racket::L3::IPv6.new(eth.payload)
  175. next if ipv6.nhead != 0x3a
  176. icmpv6 = Racket::L4::ICMPv6.new(ipv6.payload)
  177. next if icmpv6.type != Racket::L4::ICMPv6Generic::ICMPv6_TYPE_ECHO_REPLY
  178. icmpv6 = Racket::L4::ICMPv6EchoReply.new(ipv6.payload)
  179. if(icmpv6 and
  180. ipv6.dst_ip == p.l3.src_ip and
  181. ipv6.src_ip == p.l3.dst_ip and
  182. icmpv6.id == p.l4.id and
  183. icmpv6.sequence == p.l4.sequence)
  184. close_icmp_pcap()
  185. return(true)
  186. end
  187. end # End while
  188. end
  189. close_icmp_pcap()
  190. return(false)
  191. end
  192. def check_pcaprub_loaded
  193. unless @pcaprub_loaded
  194. print_status("The Pcaprub module is not available: #{@pcaprub_error}")
  195. raise RuntimeError, "Pcaprub not available"
  196. else
  197. true
  198. end
  199. end
  200. class ICMPv6OptionLinkAddress < RacketPart
  201. ICMPv6_OPTION_TYPE_ID = 1
  202. hex_octets :lladdr, 48
  203. def initialize(*args)
  204. super(*args)
  205. end
  206. end
  207. end
  208. end