PageRenderTime 47ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/modules/auxiliary/scanner/discovery/ipv6_neighbor.rb

https://github.com/Jonono2/metasploit-framework
Ruby | 220 lines | 173 code | 43 blank | 4 comment | 20 complexity | b0e8d23d4ebb8f5af6d5567172e0cfcf MD5 | raw file
Possible License(s): BSD-3-Clause, Apache-2.0, GPL-3.0, LGPL-2.1, GPL-2.0
  1. ##
  2. # This module requires Metasploit: http//metasploit.com/download
  3. # Current source: https://github.com/rapid7/metasploit-framework
  4. ##
  5. require 'msf/core'
  6. class Metasploit3 < Msf::Auxiliary
  7. include Msf::Exploit::Remote::Ipv6
  8. include Msf::Exploit::Remote::Capture
  9. include Msf::Auxiliary::Report
  10. include Msf::Auxiliary::Scanner
  11. def initialize
  12. super(
  13. 'Name' => 'IPv6 Local Neighbor Discovery',
  14. 'Description' => %q{
  15. Enumerate local IPv6 hosts which respond to Neighbor Solicitations with a link-local address.
  16. Note, that like ARP scanning, this usually cannot be performed beyond the local
  17. broadcast network.
  18. },
  19. 'Author' => 'belch',
  20. 'License' => MSF_LICENSE
  21. )
  22. register_options(
  23. [
  24. OptString.new('SHOST', [false, "Source IP Address"]),
  25. OptString.new('SMAC', [false, "Source MAC Address"]),
  26. ], self.class)
  27. deregister_options('SNAPLEN', 'FILTER')
  28. end
  29. def run_batch_size
  30. datastore['BATCHSIZE'] || 256
  31. end
  32. def run_batch(hosts)
  33. open_pcap({'SNAPLEN' => 68, 'FILTER' => "arp[6:2] == 0x0002"})
  34. @netifaces = true
  35. if not netifaces_implemented?
  36. print_error("WARNING : Pcaprub is not uptodate, some functionality will not be available")
  37. @netifaces = false
  38. end
  39. print_status("Discovering IPv4 nodes via ARP...")
  40. @interface = datastore['INTERFACE'] || Pcap.lookupdev
  41. @shost = datastore['SHOST']
  42. @shost ||= get_ipv4_addr(@interface) if @netifaces
  43. raise RuntimeError ,'SHOST should be defined' unless @shost
  44. @smac = datastore['SMAC']
  45. @smac ||= get_mac(@interface) if @netifaces
  46. raise RuntimeError ,'SMAC should be defined' unless @smac
  47. addrs = []
  48. begin
  49. found = {}
  50. hosts.each do |dhost|
  51. probe = buildprobe(@shost, @smac, dhost)
  52. capture.inject(probe)
  53. while(reply = getreply())
  54. next unless reply.is_arp?
  55. if not found[reply.arp_saddr_ip]
  56. print_status(sprintf(" %16s ALIVE",reply.arp_saddr_ip))
  57. addrs << [reply.arp_saddr_ip, reply.arp_saddr_mac]
  58. report_host(:host => reply.arp_saddr_ip, :mac=>reply.arp_saddr_mac)
  59. found[reply.arp_saddr_ip] = true
  60. end
  61. end
  62. end
  63. etime = ::Time.now.to_f + (hosts.length * 0.05)
  64. while (::Time.now.to_f < etime)
  65. while(reply = getreply())
  66. next unless reply.is_arp?
  67. if not found[reply.arp_saddr_ip]
  68. print_status(sprintf(" %16s ALIVE",reply.arp_saddr_ip))
  69. addrs << [reply.arp_saddr_ip, reply.arp_saddr_mac]
  70. report_host(:host => reply.arp_saddr_ip, :mac=>reply.arp_saddr_mac)
  71. found[reply.arp_saddr_ip] = true
  72. end
  73. end
  74. ::IO.select(nil, nil, nil, 0.50)
  75. end
  76. ensure
  77. close_pcap()
  78. end
  79. neighbor_discovery(addrs)
  80. end
  81. def map_neighbor(nodes, adv)
  82. nodes.each do |node|
  83. ipv4_addr, mac_addr = node
  84. next unless adv.eth_saddr == mac_addr
  85. ipv6_addr = adv.ipv6_saddr
  86. return {:eth => mac_addr, :ipv4 => ipv4_addr, :ipv6 => ipv6_addr}
  87. end
  88. nil
  89. end
  90. def neighbor_discovery(neighs)
  91. print_status("Discovering IPv6 addresses for IPv4 nodes...")
  92. print_status("")
  93. smac = @smac
  94. open_pcap({'SNAPLEN' => 68, 'FILTER' => "icmp6"})
  95. begin
  96. neighs.each do |neigh|
  97. host, dmac = neigh
  98. shost = ipv6_linklocaladdr(smac)
  99. neigh = ipv6_linklocaladdr(dmac)
  100. probe = buildsolicitation(smac, shost, neigh)
  101. capture.inject(probe)
  102. Kernel.select(nil,nil,nil,0.1)
  103. while(adv = getadvertisement())
  104. next unless adv.is_ipv6?
  105. addr = map_neighbor(neighs, adv)
  106. next if not addr
  107. print_status(sprintf(" %16s maps to %s",addr[:ipv4], addr[:ipv6]))
  108. report_note(
  109. :host => addr[:ipv4],
  110. :type => 'host.ipv4.ipv6.mapping',
  111. :data => "system with IPv4 address #{addr[:ipv4]} matches to IPv6 address #{addr[:ipv6]}"
  112. ) # with this we have the results in our database
  113. end
  114. end
  115. etime = ::Time.now.to_f + (neighs.length * 0.5)
  116. while (::Time.now.to_f < etime)
  117. while(adv = getadvertisement())
  118. next if not adv
  119. addr = map_neighbor(neighs, adv)
  120. next if not addr
  121. print_status(sprintf(" %16s maps to %s",addr[:ipv4], addr[:ipv6]))
  122. end
  123. ::IO.select(nil, nil, nil, 0.50)
  124. end
  125. ensure
  126. close_pcap()
  127. end
  128. end
  129. def buildprobe(shost, smac, dhost)
  130. p = PacketFu::ARPPacket.new
  131. p.eth_saddr = smac
  132. p.eth_daddr = "ff:ff:ff:ff:ff:ff"
  133. p.arp_opcode = 1
  134. p.arp_saddr_mac = p.eth_saddr
  135. p.arp_daddr_mac = p.eth_daddr
  136. p.arp_saddr_ip = shost
  137. p.arp_daddr_ip = dhost
  138. p.to_s
  139. end
  140. def getreply
  141. pkt = capture.next
  142. Kernel.select(nil,nil,nil,0.1)
  143. return if not pkt
  144. p = PacketFu::Packet.parse(pkt)
  145. return unless p.is_arp?
  146. return unless p.arp_opcode == 2
  147. p
  148. end
  149. def buildsolicitation(smac, shost, neigh)
  150. dmac = ipv6_soll_mcast_mac(neigh)
  151. dhost = ipv6_soll_mcast_addr6(neigh)
  152. p = PacketFu::IPv6Packet.new
  153. p.eth_saddr = smac
  154. p.eth_daddr = dmac
  155. p.ipv6_saddr = shost
  156. p.ipv6_daddr = dhost
  157. p.ipv6_next = 0x3a
  158. p.ipv6_hop = 255
  159. p.payload = ipv6_neighbor_solicitation(
  160. IPAddr.new(neigh).to_i,
  161. p.eth_src
  162. )
  163. p.ipv6_len = p.payload.size
  164. ipv6_checksum!(p)
  165. p.to_s
  166. end
  167. def getadvertisement
  168. pkt = capture.next
  169. Kernel.select(nil,nil,nil,0.1)
  170. return if not pkt
  171. p = PacketFu::Packet.parse(pkt)
  172. return unless p.is_ipv6?
  173. return unless p.ipv6_next == 0x3a
  174. return unless p.payload[0,2] == "\x88\x00"
  175. p
  176. end
  177. end