Class: Dobby::VulnSource::Debian

Inherits:
AbstractVulnSource show all
Defined in:
lib/dobby/vuln_source/debian.rb

Overview

Vulnerability database source for Debian systems. This uses the JSON file provided by the Debian Security Tracker as its' remote source.

Defined Under Namespace

Classes: BadResponseError, NoDataError

Constant Summary collapse

DEFAULT_RELEASE =
'jessie'
URGENCY_MAP =

Map of DST-provided urgencies to a common severity format

Hash.new(Severity::Unknown).merge(
  'not-yet-assigned' => Severity::Unknown,
  'end-of-life'      => Severity::Negligible,
  'unimportant'      => Severity::Negligible,
  'low'              => Severity::Low,
  'low*'             => Severity::Low,
  'low**'            => Severity::Low,
  'medium'           => Severity::Medium,
  'medium*'          => Severity::Medium,
  'medium**'         => Severity::Medium,
  'high'             => Severity::High,
  'high*'            => Severity::High,
  'high**'           => Severity::Critical
)

Instance Attribute Summary

Attributes included from Strategy

#options

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from AbstractVulnSource

#clean

Methods included from Strategy

included, #initialize, #inspect, #log

Class Method Details

.cli_optionsObject

rubocop:disable Layout/AlignArray



19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/dobby/vuln_source/debian.rb', line 19

def self.cli_options
  [
    ['--releases ONE,TWO',    'Limit the packages returned by a VulnSource to',
                              'these releases. Default varies with selected',
                              'VulnSource.'],
    ['--dst-json-uri URI',    'VulnSource::Debian -- specify a URI to the',
                              "Debian Security Tracker's JSON file."],
    ['--dst-local-file PATH', 'VulnSource::Debian -- If provided, read from',
                              'the specified file instead of requesting the',
                              'DST json file from a remote.'],
    ['--cve-url-prefix URI',  'URI prefix used for building CVE links.']
  ]
end

Instance Method Details

#choose_version(fixed, status) ⇒ String

Given a 'fixed in' version and a defect status, determine what version represents the status for comparison.

Parameters:

  • fixed (String)

    version that the vuln src says a defect is fixed in

  • status (String)

    the current status of the defect

Returns:

  • (String)

    version string



138
139
140
141
142
143
144
145
# File 'lib/dobby/vuln_source/debian.rb', line 138

def choose_version(fixed, status)
  return unless status
  return Package::MIN_VERSION if fixed == '0'
  return Package::MAX_VERSION if status == 'open'
  return fixed if status == 'resolved'

  nil
end

#fetch_from_remote(url) ⇒ String

Retrieve the DST json file

Parameters:

  • url (String)

Returns:

  • (String)

Raises:



155
156
157
158
159
160
161
162
163
# File 'lib/dobby/vuln_source/debian.rb', line 155

def fetch_from_remote(url)
  return File.read(options.dst_local_file) if options.dst_local_file

  curl = Curl::Easy.perform(url)
  raise BadResponseError, curl unless curl.response_code.to_i == 200
  raise NoDataError unless curl.body_str

  curl.body_str
end

#setupObject

Initialize callback.



72
73
74
# File 'lib/dobby/vuln_source/debian.rb', line 72

def setup
  @last_hash = nil
end

#updateUpdateResponse

Provide an UpdateResponse sourced from the Debian Security Tracker's JSON. If the SHA256 of the returned JSON matches the last attempt, UpdateResponse.changed? will be false. Otherwise, UpdateResponse.content will be a Hashpackage_name=>Array<Defect>

Returns:



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
# File 'lib/dobby/vuln_source/debian.rb', line 82

def update
  data = fetch_from_remote(options.dst_json_uri)

  hash = Digest::SHA256.hexdigest(data)
  return UpdateResponse.new(false) if hash == @last_hash

  debian_vulns = Oj.load(data)

  vuln_entries = Hash.new { |h, k| h[k] = [] }
  debian_vulns.each do |package, vulns|
    vulns.each do |identifier, vuln|
      # If a permanent ID has not been assigned to the vuln, skip it
      next unless identifier.start_with?('CVE-', 'OVE-')

      severity = Severity::Unknown
      fixed_versions = []

      vuln['releases'].each do |release, info|
        next unless options.releases.include?(release)

        version = choose_version(info['fixed_version'], info['status'])
        next unless version

        # For a given Defect, it may have differing severities across
        # different Debian releases. Set the severity of the Defect to
        # the highest value.
        new_severity = URGENCY_MAP[info['urgency']]
        severity = new_severity if severity < new_severity

        fixed_versions << Package.new(
          name: package,
          version: version,
          release: release
        )
      end

      vuln_entries[package] << Defect.new(
        identifier: identifier,
        description: vuln['description'],
        severity: severity,
        fixed_in: fixed_versions,
        link: options.cve_url_prefix + identifier
      )
    end
  end
  @last_hash = hash
  UpdateResponse.new(true, vuln_entries)
end