Class: Rex::Proto::DHCP::Server

Inherits:
Object
  • Object
show all
Includes:
Socket
Defined in:
lib/rex/proto/dhcp/server.rb

Overview

DHCP Server class not completely configurable - written specifically for a PXE server

  • scriptjunkie

extended to support testing/exploiting CVE-2011-0997

Constant Summary

Constants included from Socket

Socket::MATCH_IPV4, Socket::MATCH_IPV4_PRIVATE, Socket::MATCH_IPV6

Instance Attribute Summary collapse

Attributes included from Socket

#ipv, #localhost, #localport, #peerhost, #peerport

Instance Method Summary collapse

Methods included from Socket

addr_atoc, addr_atoi, addr_atoi_list, addr_aton, addr_ctoa, addr_itoa, addr_iton, addr_ntoa, addr_ntoi, bit2netmask, cidr_crack, compress_address, create, create_ip, create_param, create_tcp, create_tcp_server, create_udp, dotted_ip?, eth_aton, eth_ntoa, #fd, from_sockaddr, getaddress, getaddresses, gethostbyname, #getlocalname, #getpeername, #getsockname, #initsock, ipv6_link_address, ipv6_mac, is_internal?, is_ipv4?, is_ipv6?, net2bitmask, portlist_to_portspec, portspec_crack, portspec_to_portlist, resolv_nbo, resolv_nbo_i, resolv_nbo_i_list, resolv_nbo_list, resolv_to_dotted, source_address, support_ipv6?, tcp_socket_pair, to_sockaddr, #type?, udp_socket_pair

Constructor Details

#initialize(hash, context = {}) ⇒ Server

Returns a new instance of Server


24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/rex/proto/dhcp/server.rb', line 24

def initialize(hash, context = {})
  self.listen_host = '0.0.0.0' # clients don't already have addresses. Needs to be 0.0.0.0
  self.listen_port = 67 # mandatory (bootps)
  self.context = context
  self.sock = nil

  self.myfilename = hash['FILENAME'] || ""
  self.myfilename << ("\x00" * (128 - self.myfilename.length))

  source = hash['SRVHOST'] || Rex::Socket.source_address
  self.ipstring = Rex::Socket.addr_aton(source)

  ipstart = hash['DHCPIPSTART']
  if ipstart
    self.start_ip = Rex::Socket.addr_atoi(ipstart)
  else
    # Use the first 3 octects of the server's IP to construct the
    # default range of x.x.x.32-254
    self.start_ip = "#{self.ipstring[0..2]}\x20".unpack("N").first
  end
  self.current_ip = start_ip

  ipend = hash['DHCPIPEND']
  if ipend
    self.end_ip = Rex::Socket.addr_atoi(ipend)
  else
    # Use the first 3 octects of the server's IP to construct the
    # default range of x.x.x.32-254
    self.end_ip = "#{self.ipstring[0..2]}\xfe".unpack("N").first
  end

  # netmask
  netmask = hash['NETMASK'] || "255.255.255.0"
  self.netmaskn = Rex::Socket.addr_aton(netmask)

  # router
  router = hash['ROUTER'] || source
  self.router = Rex::Socket.addr_aton(router)

  # dns
  dnsserv = hash['DNSSERVER'] || source
  self.dnsserv = Rex::Socket.addr_aton(dnsserv)

  # broadcast
  if hash['BROADCAST']
    self.broadcasta = Rex::Socket.addr_aton(hash['BROADCAST'])
  else
    self.broadcasta = Rex::Socket.addr_itoa( self.start_ip | (Rex::Socket.addr_ntoi(self.netmaskn) ^ 0xffffffff) )
  end

  self.served = {}
  self.serveOnce = hash.include?('SERVEONCE')

  self.servePXE = (hash.include?('PXE') or hash.include?('FILENAME') or hash.include?('PXEONLY'))
  self.serveOnlyPXE = hash.include?('PXEONLY')

  # Always assume we don't give out hostnames ...
  self.give_hostname = false
  self.served_over = 0
  if (hash['HOSTNAME'])
    self.give_hostname = true
    self.served_hostname = hash['HOSTNAME']
    if ( hash['HOSTSTART'] )
      self.served_over = hash['HOSTSTART'].to_i
    end
  end

  self.leasetime = 600
  self.relayip = "\x00\x00\x00\x00" # relay ip - not currently suported
  self.pxeconfigfile = "update2"
  self.pxealtconfigfile = "update0"
  self.pxepathprefix = ""
  self.pxereboottime = 2000
end

Instance Attribute Details

#broadcastaObject

Returns the value of attribute broadcasta


155
156
157
# File 'lib/rex/proto/dhcp/server.rb', line 155

def broadcasta
  @broadcasta
end

#contextObject

Returns the value of attribute context


153
154
155
# File 'lib/rex/proto/dhcp/server.rb', line 153

def context
  @context
end

#current_ipObject

Returns the value of attribute current_ip


155
156
157
# File 'lib/rex/proto/dhcp/server.rb', line 155

def current_ip
  @current_ip
end

#dnsservObject

Returns the value of attribute dnsserv


153
154
155
# File 'lib/rex/proto/dhcp/server.rb', line 153

def dnsserv
  @dnsserv
end

#end_ipObject

Returns the value of attribute end_ip


155
156
157
# File 'lib/rex/proto/dhcp/server.rb', line 155

def end_ip
  @end_ip
end

#give_hostnameObject

Returns the value of attribute give_hostname


157
158
159
# File 'lib/rex/proto/dhcp/server.rb', line 157

def give_hostname
  @give_hostname
end

#ipstringObject

Returns the value of attribute ipstring


154
155
156
# File 'lib/rex/proto/dhcp/server.rb', line 154

def ipstring
  @ipstring
end

#leasetimeObject

Returns the value of attribute leasetime


153
154
155
# File 'lib/rex/proto/dhcp/server.rb', line 153

def leasetime
  @leasetime
end

#listen_hostObject

Returns the value of attribute listen_host


153
154
155
# File 'lib/rex/proto/dhcp/server.rb', line 153

def listen_host
  @listen_host
end

#listen_portObject

Returns the value of attribute listen_port


153
154
155
# File 'lib/rex/proto/dhcp/server.rb', line 153

def listen_port
  @listen_port
end

#myfilenameObject

Returns the value of attribute myfilename


154
155
156
# File 'lib/rex/proto/dhcp/server.rb', line 154

def myfilename
  @myfilename
end

#netmasknObject

Returns the value of attribute netmaskn


155
156
157
# File 'lib/rex/proto/dhcp/server.rb', line 155

def netmaskn
  @netmaskn
end

#pxealtconfigfileObject

Returns the value of attribute pxealtconfigfile


156
157
158
# File 'lib/rex/proto/dhcp/server.rb', line 156

def pxealtconfigfile
  @pxealtconfigfile
end

#pxeconfigfileObject

Returns the value of attribute pxeconfigfile


156
157
158
# File 'lib/rex/proto/dhcp/server.rb', line 156

def pxeconfigfile
  @pxeconfigfile
end

#pxepathprefixObject

Returns the value of attribute pxepathprefix


156
157
158
# File 'lib/rex/proto/dhcp/server.rb', line 156

def pxepathprefix
  @pxepathprefix
end

#pxereboottimeObject

Returns the value of attribute pxereboottime


156
157
158
# File 'lib/rex/proto/dhcp/server.rb', line 156

def pxereboottime
  @pxereboottime
end

#relayipObject

Returns the value of attribute relayip


153
154
155
# File 'lib/rex/proto/dhcp/server.rb', line 153

def relayip
  @relayip
end

#reporterObject

Returns the value of attribute reporter


157
158
159
# File 'lib/rex/proto/dhcp/server.rb', line 157

def reporter
  @reporter
end

#routerObject

Returns the value of attribute router


153
154
155
# File 'lib/rex/proto/dhcp/server.rb', line 153

def router
  @router
end

#servedObject

Returns the value of attribute served


154
155
156
# File 'lib/rex/proto/dhcp/server.rb', line 154

def served
  @served
end

#served_hostnameObject

Returns the value of attribute served_hostname


157
158
159
# File 'lib/rex/proto/dhcp/server.rb', line 157

def served_hostname
  @served_hostname
end

#served_overObject

Returns the value of attribute served_over


157
158
159
# File 'lib/rex/proto/dhcp/server.rb', line 157

def served_over
  @served_over
end

#serveOnceObject

Returns the value of attribute serveOnce


154
155
156
# File 'lib/rex/proto/dhcp/server.rb', line 154

def serveOnce
  @serveOnce
end

#serveOnlyPXEObject

Returns the value of attribute serveOnlyPXE


156
157
158
# File 'lib/rex/proto/dhcp/server.rb', line 156

def serveOnlyPXE
  @serveOnlyPXE
end

#servePXEObject

Returns the value of attribute servePXE


156
157
158
# File 'lib/rex/proto/dhcp/server.rb', line 156

def servePXE
  @servePXE
end

#sockObject

Returns the value of attribute sock


154
155
156
# File 'lib/rex/proto/dhcp/server.rb', line 154

def sock
  @sock
end

#start_ipObject

Returns the value of attribute start_ip


155
156
157
# File 'lib/rex/proto/dhcp/server.rb', line 155

def start_ip
  @start_ip
end

#threadObject

Returns the value of attribute thread


154
155
156
# File 'lib/rex/proto/dhcp/server.rb', line 154

def thread
  @thread
end

Instance Method Details

#report(&block) ⇒ Object


99
100
101
# File 'lib/rex/proto/dhcp/server.rb', line 99

def report(&block)
  self.reporter = block
end

#send_packet(ip, pkt) ⇒ Object

Send a single packet to the specified host


142
143
144
145
146
147
148
149
150
151
# File 'lib/rex/proto/dhcp/server.rb', line 142

def send_packet(ip, pkt)
  port = 68 # bootpc
  if ip
    self.sock.sendto( pkt, ip, port )
  else
    if not self.sock.sendto( pkt, '255.255.255.255', port )
      self.sock.sendto( pkt, self.broadcasta, port )
    end
  end
end

#set_option(opts) ⇒ Object

Set an option


125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/rex/proto/dhcp/server.rb', line 125

def set_option(opts)
  allowed_options = [
    :serveOnce, :pxealtconfigfile, :servePXE, :relayip, :leasetime, :dnsserv,
    :pxeconfigfile, :pxepathprefix, :pxereboottime, :router,
    :give_hostname, :served_hostname, :served_over, :serveOnlyPXE
  ]

  opts.each_pair { |k,v|
    next if not v
    if allowed_options.include?(k)
      self.instance_variable_set("@#{k}", v)
    end
  }
end

#startObject

Start the DHCP server


104
105
106
107
108
109
110
111
112
113
114
# File 'lib/rex/proto/dhcp/server.rb', line 104

def start
  self.sock = Rex::Socket::Udp.create(
    'LocalHost' => listen_host,
    'LocalPort' => listen_port,
    'Context'   => context
  )

  self.thread = Rex::ThreadFactory.spawn("DHCPServerMonitor", false) {
    monitor_socket
  }
end

#stopObject

Stop the DHCP server


117
118
119
120
121
# File 'lib/rex/proto/dhcp/server.rb', line 117

def stop
  self.thread.kill
  self.served = {}
  self.sock.close rescue nil
end