PageRenderTime 45ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

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

https://bitbucket.org/jrossi/metasploit
Ruby | 229 lines | 165 code | 55 blank | 9 comment | 27 complexity | 4bfd6bef7f588dc8e4561def2d314c3b MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, BSD-3-Clause
  1. ##
  2. # $Id$
  3. ##
  4. ##
  5. # This file is part of the Metasploit Framework and may be subject to
  6. # redistribution and commercial restrictions. Please see the Metasploit
  7. # Framework web site for more information on licensing and terms of use.
  8. # http://metasploit.com/framework/
  9. ##
  10. require 'msf/core'
  11. class Metasploit3 < Msf::Auxiliary
  12. include Msf::Exploit::Remote::Capture
  13. include Msf::Auxiliary::Report
  14. include Msf::Auxiliary::Scanner
  15. def initialize
  16. super(
  17. 'Name' => 'IPv6 Local Neighbor Discovery',
  18. 'Version' => '$Revision$',
  19. 'Description' => %q{
  20. Enumerate local IPv6 hosts which respond to Neighbor Solicitations with a link-local address.
  21. Note, that like ARP scanning, this usually cannot be performed beyond the local
  22. broadcast network.
  23. },
  24. 'Author' => 'belch',
  25. 'License' => MSF_LICENSE
  26. )
  27. register_options(
  28. [
  29. OptString.new('SHOST', [false, "Source IP Address"]),
  30. OptString.new('SMAC', [true, "Source MAC Address"]),
  31. ], self.class)
  32. deregister_options('SNAPLEN', 'FILTER')
  33. end
  34. def run_batch_size
  35. datastore['BATCHSIZE'] || 256
  36. end
  37. def run_batch(hosts)
  38. print_status("Discovering IPv4 nodes via ARP...")
  39. print_status("")
  40. shost = datastore['SHOST']
  41. smac = datastore['SMAC']
  42. addrs = []
  43. open_pcap({'SNAPLEN' => 68, 'FILTER' => "arp[6:2] == 0x0002"})
  44. begin
  45. found = {}
  46. hosts.each do |dhost|
  47. shost = datastore['SHOST'] || Rex::Socket.source_address(dhost)
  48. probe = buildprobe(datastore['SHOST'], datastore['SMAC'], dhost)
  49. capture.inject(probe)
  50. while(reply = getreply())
  51. next if not reply[:arp]
  52. if not found[reply[:arp].spa]
  53. print_status(sprintf(" %16s ALIVE",reply[:arp].spa))
  54. addrs << [reply[:arp].spa, reply[:arp].sha]
  55. report_host(:host => reply[:arp].spa, :mac=>reply[:arp].sha)
  56. found[reply[:arp].spa] = true
  57. end
  58. end
  59. end
  60. etime = ::Time.now.to_f + (hosts.length * 0.05)
  61. while (::Time.now.to_f < etime)
  62. while(reply = getreply())
  63. next if not reply[:arp]
  64. if not found[reply[:arp].spa]
  65. print_status(sprintf(" %16s ALIVE",reply[:arp].spa))
  66. addrs << [reply[:arp].spa, reply[:arp].sha]
  67. report_host(:host => reply[:arp].spa, :mac=>reply[:arp].sha)
  68. found[reply[:arp].spa] = true
  69. end
  70. end
  71. ::IO.select(nil, nil, nil, 0.50)
  72. end
  73. ensure
  74. close_pcap()
  75. end
  76. neighbor_discovery(addrs)
  77. end
  78. def map_neighbor(nodes, adv)
  79. nodes.each do |node|
  80. ipv4_addr, mac_addr = node
  81. next if not adv[:eth].src_mac.eql? mac_addr
  82. ipv6_addr = Racket::L3::Misc.long2ipv6(adv[:ipv6].src_ip)
  83. return {:eth => mac_addr, :ipv4 => ipv4_addr, :ipv6 => ipv6_addr}
  84. end
  85. nil
  86. end
  87. def neighbor_discovery(neighs)
  88. print_status("Discovering IPv6 addresses for IPv4 nodes...")
  89. print_status("")
  90. smac = datastore['SMAC']
  91. open_pcap({'SNAPLEN' => 68, 'FILTER' => "icmp6"})
  92. begin
  93. neighs.each do |neigh|
  94. host, dmac = neigh
  95. shost = Racket::L3::Misc.linklocaladdr(smac)
  96. neigh = Racket::L3::Misc.linklocaladdr(dmac)
  97. probe = buildsolicitation(smac, shost, neigh)
  98. capture.inject(probe)
  99. while(adv = getadvertisement())
  100. next if not adv[:icmpv6]
  101. addr = map_neighbor(neighs, adv)
  102. next if not addr
  103. print_status(sprintf(" %16s maps to %s",addr[:ipv4], addr[:ipv6]))
  104. end
  105. end
  106. etime = ::Time.now.to_f + (neighs.length * 0.5)
  107. while (::Time.now.to_f < etime)
  108. while(adv = getadvertisement())
  109. next if not adv[:icmpv6]
  110. addr = map_neighbor(neighs, adv)
  111. next if not addr
  112. print_status(sprintf(" %16s maps to %s",addr[:ipv4], addr[:ipv6]))
  113. end
  114. ::IO.select(nil, nil, nil, 0.50)
  115. end
  116. ensure
  117. close_pcap()
  118. end
  119. end
  120. def buildprobe(shost, smac, dhost)
  121. n = Racket::Racket.new
  122. n.l2 = Racket::L2::Ethernet.new(Racket::Misc.randstring(14))
  123. n.l2.src_mac = smac
  124. n.l2.dst_mac = 'ff:ff:ff:ff:ff:ff'
  125. n.l2.ethertype = 0x0806
  126. n.l3 = Racket::L3::ARP.new
  127. n.l3.opcode = Racket::L3::ARP::ARPOP_REQUEST
  128. n.l3.sha = n.l2.src_mac
  129. n.l3.tha = n.l2.dst_mac
  130. n.l3.spa = shost
  131. n.l3.tpa = dhost
  132. n.pack
  133. end
  134. def getreply
  135. pkt = capture.next
  136. return if not pkt
  137. eth = Racket::L2::Ethernet.new(pkt)
  138. return if not eth.ethertype == 0x0806
  139. arp = Racket::L3::ARP.new(eth.payload)
  140. return if not arp.opcode == Racket::L3::ARP::ARPOP_REPLY
  141. {:raw => pkt, :eth => eth, :arp => arp}
  142. end
  143. def buildsolicitation(smac, shost, neigh)
  144. dmac = Racket::L3::Misc.soll_mcast_mac(neigh)
  145. dhost = Racket::L3::Misc.soll_mcast_addr6(neigh)
  146. n = Racket::Racket.new
  147. n.l2 = Racket::L2::Ethernet.new(Racket::Misc.randstring(14))
  148. n.l2.src_mac = smac
  149. n.l2.dst_mac = dmac
  150. n.l2.ethertype = 0x86dd
  151. n.l3 = Racket::L3::IPv6.new
  152. n.l3.src_ip = Racket::L3::Misc.ipv62long(shost)
  153. n.l3.dst_ip = Racket::L3::Misc.ipv62long(dhost)
  154. n.l3.nhead = 0x3a
  155. n.l3.ttl = 0xff
  156. n.l4 = Racket::L4::ICMPv6NeighborSolicitation.new
  157. n.l4.address = Racket::L3::Misc.ipv62long(neigh)
  158. n.l4.slla = smac
  159. n.l4.fix!(n.l3.src_ip, n.l3.dst_ip)
  160. n.pack
  161. end
  162. def getadvertisement
  163. pkt = capture.next
  164. return if not pkt
  165. eth = Racket::L2::Ethernet.new(pkt)
  166. return if not eth.ethertype == 0x86dd
  167. ipv6 = Racket::L3::IPv6.new(eth.payload)
  168. return if not ipv6.nhead == 0x3a
  169. icmpv6 = Racket::L4::ICMPv6.new(ipv6.payload)
  170. return if not icmpv6.type == Racket::L4::ICMPv6::ICMPv6_TYPE_NEIGHBOR_ADVERTISEMENT
  171. icmpv6 = Racket::L4::ICMPv6NeighborAdvertisement.new(ipv6.payload)
  172. {:raw => pkt, :eth => eth, :ipv6 => ipv6, :icmpv6 => icmpv6}
  173. end
  174. end