Lucene search
K

IPID Sequence Scanner

🗓️ 03 Apr 2009 00:59:25Reported by kris katterjohn <[email protected]>Type 
metasploit
 metasploit
🔗 www.rapid7.com👁 19 Views

IPID Sequence Scanner module to probe and classify hosts' IPID sequences using SYN probes. It mimics Nmap's probes for IPID Idle Scan and OS Detection methods

Code
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

require 'timeout'

class MetasploitModule < Msf::Auxiliary
  include Msf::Exploit::Capture
  include Msf::Auxiliary::Scanner
  include Msf::Auxiliary::Report

  def initialize
    super(
      'Name'        => 'IPID Sequence Scanner',
      'Description' => %q{
        This module will probe hosts' IPID sequences and classify
        them using the same method Nmap uses when it's performing
        its IPID Idle Scan (-sI) and OS Detection (-O).

        Nmap's probes are SYN/ACKs while this module's are SYNs.
        While this does not change the underlying functionality,
        it does change the chance of whether or not the probe
        will be stopped by a firewall.

        Nmap's Idle Scan can use hosts whose IPID sequences are
        classified as "Incremental" or "Broken little-endian incremental".
      },
      'Author'      => 'kris katterjohn',
      'License'     => MSF_LICENSE
    )

    register_options([
      Opt::RPORT(80),
      OptInt.new('TIMEOUT', [true, "The reply read timeout in milliseconds", 500]),
      OptString.new('INTERFACE', [false, 'The name of the interface'])
    ])

    register_advanced_options([
      OptInt.new('SAMPLES', [true, "The IPID sample size", 6])
    ])

    deregister_options('FILTER','PCAPFILE')
  end

  def rport
    datastore['RPORT'].to_i
  end

  def run_host(ip)
    open_pcap

    raise "SAMPLES option must be >= 2" if datastore['SAMPLES'] < 2

    pcap = self.capture

    shost = Rex::Socket.source_address(ip)

    to = (datastore['TIMEOUT'] || 500).to_f / 1000.0

    ipids = []

    pcap.setfilter(getfilter(shost, ip, rport))

    datastore['SAMPLES'].times do
      sport = rand(0xffff - 1025) + 1025

      probe = buildprobe(shost, sport, ip, rport)

      next unless capture_sendto(probe, ip)

      reply = probereply(pcap, to)

      next if not reply

      ipids << reply.ip_id
    end

    close_pcap

    return if ipids.empty?

    print_status("#{ip}'s IPID sequence class: #{analyze(ipids)}")

    #Add Report
    report_note(
      :host	=> ip,
      :proto	=> 'ip',
      :type	=> 'IPID sequence',
      :data	=> "IPID sequence class: #{analyze(ipids)}"
    )
  end

  # Based on Nmap's get_ipid_sequence() in osscan2.cc
  def analyze(ipids)
    allzeros = true
    allsame = true
    mul256 = true
    inc = true

    # ipids.each do |ipid|
    #	print_status("Got IPID ##{ipid}")
    # end

    return "Unknown" if ipids.size < 2

    diffs = []
    i = 1

    while i < ipids.size
      p = ipids[i - 1]
      c = ipids[i]

      if p != 0 or c != 0
        allzeros = false
      end

      if p <= c
        diffs[i - 1] = c - p
      else
        diffs[i - 1] = c - p + 65536
      end

      if ipids.size > 2 and diffs[i - 1] > 20000
        return "Randomized"
      end

      i += 1
    end

    return "All zeros" if allzeros

    diffs.each do |diff|
      if diff > 1000 and ((diff % 256) != 0 or ((diff % 256) == 0 and diff >= 25600))
        return "Random positive increments"
      end

      allsame = false if diff != 0

      mul256 = false if diff > 5120 or (diff % 256) != 0

      inc = false if diff >= 10
    end

    return "Constant" if allsame

    return "Broken little-endian incremental!" if mul256

    return "Incremental!" if inc

    "Unknown"
  end

  def getfilter(shost, dhost, dport)
    "tcp and src host #{dhost} and src port #{dport} and " +
    "dst host #{shost}"
  end

  # This gets set via the usual capture_sendto interface
  def buildprobe(shost, sport, dhost, dport)
    p = PacketFu::TCPPacket.new
    p.ip_saddr = shost
    p.ip_daddr = dhost
    p.tcp_sport = sport
    p.tcp_dport = dport
    p.tcp_flags.syn = 1
    p.recalc
    p
  end

  def probereply(pcap, to)
    reply = nil

    begin
      Timeout.timeout(to) do
        pcap.each do |r|
          pkt = PacketFu::Packet.parse(r)
          next unless pkt.is_tcp?
          next unless pkt.tcp_flags.syn == 1 || pkt.tcp_flags.rst == 1
          reply = pkt
          break
        end
      end
    rescue Timeout::Error
    end

    return reply
  end
end

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation