Module: Msf::DBManager::Service
- Included in:
- Msf::DBManager
- Defined in:
- lib/msf/core/db_manager/service.rb
Instance Method Summary collapse
-
#delete_service(opts) ⇒ Object
Deletes a port and associated vulns matching this port.
-
#each_service(wspace = framework.db.workspace, &block) ⇒ Object
Iterates over the services table calling the supplied block with the service instance of each entry.
- #find_or_create_service(opts) ⇒ Object
- #process_service_chain(host, services) ⇒ Object
-
#report_service(opts) ⇒ Mdm::Service?
Record a service in the database.
-
#services(opts) ⇒ Object
Returns a list of all services in the database.
- #update_service(opts) ⇒ Object
Instance Method Details
#delete_service(opts) ⇒ Object
Deletes a port and associated vulns matching this port
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
# File 'lib/msf/core/db_manager/service.rb', line 3 def delete_service(opts) raise ArgumentError.new("The following options are required: :ids") if opts[:ids].nil? ::ApplicationRecord.connection_pool.with_connection { deleted = [] opts[:ids].each do |service_id| begin service = Mdm::Service.find(service_id) rescue ActiveRecord::RecordNotFound # This happens when the service was the child of another service we have already deleted # Deletion of children is automatic via dependent: :destroy on the association dlog("Service with id #{service_id} already deleted") next end begin deleted << service.destroy rescue elog("Forcibly deleting #{service.name}") deleted << service.delete end end return deleted } end |
#each_service(wspace = framework.db.workspace, &block) ⇒ Object
Iterates over the services table calling the supplied block with the service instance of each entry.
31 32 33 34 35 36 37 |
# File 'lib/msf/core/db_manager/service.rb', line 31 def each_service(wspace=framework.db.workspace, &block) ::ApplicationRecord.connection_pool.with_connection { wspace.services.each do |service| block.call(service) end } end |
#find_or_create_service(opts) ⇒ Object
39 40 41 |
# File 'lib/msf/core/db_manager/service.rb', line 39 def find_or_create_service(opts) report_service(opts) end |
#process_service_chain(host, services) ⇒ Object
193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 |
# File 'lib/msf/core/db_manager/service.rb', line 193 def process_service_chain(host, services) return if services.nil? || host.nil? return unless services.is_a?(Hash) || services.is_a?(::Array) return unless host.is_a?(Mdm::Host) services = [services] unless services.is_a?(Array) services.map do |service| return unless service.is_a?(Hash) return if service[:port].nil? || service[:proto].nil? parents = nil if service[:parents]&.any? parents = process_service_chain(host, service[:parents]) end service_info = { port: service[:port].to_i, proto: service[:proto].to_s.downcase, } service_info[:name] = service[:name].downcase if service[:name] service_info[:resource] = service[:resource] if service[:resource] service_obj = host.services.find_or_create_by(service_info) if service_obj.id.nil? elog("Failed to create service #{service_info.inspect} for host #{host.name} (#{host.address})") return end service_obj.state ||= Msf::ServiceState::Open service_obj.info = service[:info] ? service[:info] : '' if parents parents.each do |parent| service_obj.parents << parent if parent && !service_obj.parents.include?(parent) end end service_obj end end |
#report_service(opts) ⇒ Mdm::Service?
Record a service in the database.
opts MUST contain
:host-
the host where this service is running
:port-
the port where this service listens
:proto-
the transport layer protocol (e.g. tcp, udp)
:workspace-
the workspace for the service
opts may contain
:name-
the application layer protocol (e.g. ssh, mssql, smb)
:sname-
an alias for the above
:info-
detailed information about the service such as name and version information
:state-
the current listening state of the service (one of: open, closed, filtered, unknown)
:resource-
the resource this service is associated with, such as a a DN for an an LDAP object base URI for a web application, pipe name for DCERPC service, etc.
:parents-
a single service Hash or an Array of service Hash representing the parent services this service is associated with, such as a HTTP service for a web application.
‘
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 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
# File 'lib/msf/core/db_manager/service.rb', line 63 def report_service(opts) return if !active ::ApplicationRecord.connection_pool.with_connection { |conn| opts = opts.clone() # protect the original caller's opts addr = opts.delete(:host) || return hname = opts.delete(:host_name) hmac = opts.delete(:mac) host = nil wspace = Msf::Util::DBManager.process_opts_workspace(opts, framework) opts.delete(:workspace) # this may not be needed however the service creation below might complain if missing hopts = {:workspace => wspace, :host => addr} hopts[:name] = hname if hname hopts[:mac] = hmac if hmac # Other report_* methods take :sname to mean the service name, so we # map it here to ensure it ends up in the right place despite not being # a real column. if opts[:sname] opts[:name] = opts.delete(:sname) end opts[:name] = opts[:name].to_s.downcase if opts[:name] if addr.kind_of? ::Mdm::Host host = addr addr = host.address else host = report_host(hopts) end if opts[:port].to_i.zero? dlog("Skipping port zero for service '%s' on host '%s'" % [opts[:name],host.address]) return nil end proto = opts[:proto] || Msf::DBManager::DEFAULT_SERVICE_PROTO sopts = { port: opts[:port].to_i, proto: proto } sopts[:name] = opts[:name] if opts[:name] sopts[:resource] = opts[:resource] if opts[:resource] service = host.services.where(sopts).first_or_initialize ostate = service.state opts.each { |k,v| if (service.attribute_names.include?(k.to_s)) service[k] = ((v and k == :name) ? v.to_s.downcase : v) elsif !v.blank? dlog("Unknown attribute for Service: #{k}") end } service.state ||= Msf::ServiceState::Open service.info ||= "" parents = process_service_chain(host, opts.delete(:parents)) if opts[:parents] if parents parents.each do |parent| service.parents << parent if parent && !service.parents.include?(parent) end end begin framework.events.on_db_service(service) if service.new_record? rescue ::Exception => e wlog("Exception in on_db_service event handler: #{e.class}: #{e}") wlog("Call Stack\n#{e.backtrace.join("\n")}") end begin framework.events.on_db_service_state(service, service.port, ostate) if service.state != ostate rescue ::Exception => e wlog("Exception in on_db_service_state event handler: #{e.class}: #{e}") wlog("Call Stack\n#{e.backtrace.join("\n")}") end if (service and service.changed?) service.save! end if opts[:task] Mdm::TaskService.where( :task => opts[:task], :service => service ).first_or_create end service } end |
#services(opts) ⇒ Object
Returns a list of all services in the database
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 |
# File 'lib/msf/core/db_manager/service.rb', line 155 def services(opts) opts = opts.clone() search_term = opts.delete(:search_term) order_args = [:port] order_args.unshift(Mdm::Host.arel_table[:address]) if opts.key?(:hosts) ::ApplicationRecord.connection_pool.with_connection { # If we have the ID, there is no point in creating a complex query. if opts[:id] && !opts[:id].to_s.empty? return Array.wrap(Mdm::Service.find(opts[:id])) end opts = opts.clone() # protect the original caller's opts wspace = Msf::Util::DBManager.process_opts_workspace(opts, framework) opts.delete(:workspace) if search_term && !search_term.empty? column_search_conditions = Msf::Util::DBManager.create_all_column_search_conditions(Mdm::Service, search_term) wspace.services.includes(:host).where(opts).where(column_search_conditions).order(*order_args) else wspace.services.includes(:host).where(opts).order(*order_args) end } end |
#update_service(opts) ⇒ Object
181 182 183 184 185 186 187 188 189 190 191 |
# File 'lib/msf/core/db_manager/service.rb', line 181 def update_service(opts) opts = opts.clone() # it is not polite to change arguments passed from callers opts.delete(:workspace) # Workspace isn't used with Mdm::Service. So strip it if it's present. ::ApplicationRecord.connection_pool.with_connection { id = opts.delete(:id) service = Mdm::Service.find(id) service.update!(opts) return service } end |