Skip to content

Commit

Permalink
Allow exploit targets to define a range of software versions (closes #…
Browse files Browse the repository at this point in the history
…150).

* Changed `Target#initialize(software_version: ...)` to accept both an
  exact version or a version range. Both are parsed using
  `Ronin::Support::Software::VersionRange.parse`.
* Changed `Target#software_version` to return a
  `Ronin::Support::Software::VersionRange`.
* Changed `Mixins::HasTargets#select_target` to parse the given
  `software_version:` String using `Ronin::Support::Software::Version`
  and compare it against the `#software_version` of each target.
  • Loading branch information
postmodern committed Dec 9, 2024
1 parent 3ee5f09 commit 06a2926
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 14 deletions.
7 changes: 7 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,10 @@ Style/NegatedIfElseCondition:
Exclude:
- 'lib/ronin/exploits/sqli.rb'
- 'lib/ronin/exploits/mixins/html.rb'

# We need to use the === operator to compare Ronin::Support::Software::Version
# objects against Ronin::Support::Software::VersionRange objects.
Style/CaseEquality:
Exclude:
- 'lib/ronin/exploits/mixins/has_targets.rb'
- 'spec/mixins/has_targets_spec.rb'
6 changes: 5 additions & 1 deletion lib/ronin/exploits/mixins/has_targets.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
require_relative '../target'
require_relative '../exceptions'

require 'ronin/support/software/version'

module Ronin
module Exploits
module Mixins
Expand Down Expand Up @@ -200,8 +202,10 @@ def select_target(arch: nil, os: nil, os_version: nil, software: nil, software_v
end

if software_version
version = Support::Software::Version.parse(software_version)

targets = targets.select do |target|
target.software_version == software_version
target.software_version && target.software_version === version
end
end

Expand Down
13 changes: 9 additions & 4 deletions lib/ronin/exploits/target.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
# along with ronin-exploits. If not, see <https://www.gnu.org/licenses/>.
#

require 'ronin/support/software/version_range'

require 'ostruct'

module Ronin
Expand Down Expand Up @@ -53,7 +55,7 @@ class Target < OpenStruct

# The target's software version.
#
# @return [String, nil]
# @return [Ronin::Support::Software::VersionRange, nil]
#
# @since 1.2.0
attr_reader :software_version
Expand All @@ -76,7 +78,8 @@ class Target < OpenStruct
# The software name of the target (ex: `"Apache"`).
#
# @param [String, nil] software_version
# The software version of the target (ex: `"2.4.54"`).
# The software version of the target
# (ex: `"2.4.54"` or `">= 1.2.3, < 2.0.0"`).
#
# @param [String, nil] version
# Alias for `software_version:`.
Expand All @@ -100,9 +103,11 @@ def initialize(arch: nil,

@os = os
@os_version = os_version
@software = software

@software = software
@software_version = software_version || version
if (string = (software_version || version))
@software_version = Support::Software::VersionRange.parse(string)
end

yield self if block_given?
end
Expand Down
45 changes: 40 additions & 5 deletions spec/mixins/has_targets_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -290,12 +290,47 @@ class ExampleExploit < Ronin::Exploits::Exploit
end

context "when given the software_version: keyword argument" do
let(:software_version) { '1.22.0' }
context "and when the targets in .targets define exact software versions" do
let(:software_version) { '1.22.0' }

it "must find the target in .targets with the matching #software_version" do
subject.select_target(software_version: software_version)

it "must find the target in .targets with the matching #software_version" do
subject.select_target(software_version: software_version)
expect(subject.target.software_version.string).to eq(software_version)
end
end

context "but the targets in .targets define software version ranges" do
module TestHasTargets
class ExampleExploitWithVersionRanges < Ronin::Exploits::Exploit
include Ronin::Exploits::Mixins::HasTargets

expect(subject.target.software_version).to eq(software_version)
target arch: :x86_64,
os: :linux,
os_version: '5.18.1',
software: 'Apache',
software_version: '>= 2.4.53',
foo: 1

target arch: :arm,
os: :macos,
os_version: '10.13',
software: 'nginx',
software_version: '>= 1.22.0, < 1.23.0',
foo: 2
end
end

let(:test_class) { TestHasTargets::ExampleExploitWithVersionRanges }
let(:software_version) { '1.22.1' }

it "must find the target in .targets who's #software_version version range includes the given software version" do
subject.select_target(software_version: software_version)

expect(subject.target.software_version).to include(
Ronin::Support::Software::Version.parse(software_version)
)
end
end
end

Expand All @@ -319,7 +354,7 @@ class ExampleExploit < Ronin::Exploits::Exploit
expect(subject.target.os).to eq(os)
expect(subject.target.os_version).to eq(os_version)
expect(subject.target.software).to eq(software)
expect(subject.target.software_version).to eq(software_version)
expect(subject.target.software_version).to be === Ronin::Support::Software::Version.parse(software_version)
end
end

Expand Down
28 changes: 24 additions & 4 deletions spec/target_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,18 @@

subject { described_class.new(software_version: software_version) }

it "must set #software_version" do
expect(subject.software_version).to be(software_version)
it "must set #software_version to a new Ronin::Support::Software::VersionRange object" do
expect(subject.software_version).to be_kind_of(Ronin::Support::Software::VersionRange)
expect(subject.software_version.string).to eq(software_version)
end

context "but the software_version: value is a version range String" do
let(:software_version) { '>= 1.2.3, < 2.0.0' }

it "must accept and parse the version range String" do
expect(subject.software_version).to be_kind_of(Ronin::Support::Software::VersionRange)
expect(subject.software_version.string).to eq(software_version)
end
end
end

Expand All @@ -82,8 +92,18 @@

subject { described_class.new(version: version) }

it "must set #software_version" do
expect(subject.software_version).to be(version)
it "must set #software_version to a new Ronin::Support::Software::VersionRange object" do
expect(subject.software_version).to be_kind_of(Ronin::Support::Software::VersionRange)
expect(subject.software_version.string).to eq(version)
end

context "but the version: value is a version range String" do
let(:version) { '>= 1.2.3, < 2.0.0' }

it "must accept and parse the version range String" do
expect(subject.software_version).to be_kind_of(Ronin::Support::Software::VersionRange)
expect(subject.software_version.string).to eq(version)
end
end
end

Expand Down

0 comments on commit 06a2926

Please sign in to comment.