Class: Ronin::Exploits::Exploit
- Inherits:
-
Object
- Object
- Ronin::Exploits::Exploit
- Includes:
- Core::Metadata::Authors, Core::Metadata::Description, Core::Metadata::ID, Core::Metadata::References, Core::Metadata::Summary, Core::Params::Mixin, Support::CLI::Printing
- Defined in:
- lib/ronin/exploits/exploit.rb
Overview
The Exploit class allows for describing exploits for security vulnerabilities, purely in Ruby. Exploits contain metadata about the exploit/vulnerability and methods which defines the functionality of the exploit. Exploits may also include additional mixin modules to add additional functionality, such as defining targets or loading in a payload.
Philosophy
Exploits are just programs with steps to build and launch the exploit. Exploits also typically contain metadata that describes the exploit's author(s), release date, what the exploit does, etc.
The Exploit class defines six key parts:
- Metadata - defines information about the exploit.
- Params - user configurable parameters.
- test - optional method that tests whether the target is vulnerable or not.
- build - method which builds the exploit.
- launch - method which launches the exploit.
- cleanup - optional Method which performs additional cleanup steps.
Example
require 'ronin/exploits/exploit'
require 'ronin/exploits/mixins/remote_tcp'
module Ronin
module Exploits
class MyExploit < Exploit
include Mixins::RemoteTCP
register 'my_exploit'
summary 'My first exploit'
description <<~EOS
This is my first exploit.
Bla bla bla bla.
EOS
'...'
'...', email: '...', twitter: '...'
disclosure_date 'YYY-MM-DD'
release_date 'YYYY-MM-DD'
advisory 'CVE-YYYY-NNNN'
advisory 'GHSA-XXXXXX'
software 'TestHTTP'
software_versions '1.0.0'..'1.5.4'
param :cmd, desc: 'The command to run'
def test
# ...
end
def build
# ...
end
def launch
# ...
end
def cleanup
# ...
end
end
end
end
register
Registers the exploit with Ronin::Exploits.
register 'my_exploit'
quality
Defines the quality level of the exploit. Accepted values are:
:untested
:testing
:poc
:weaponized
quality :poc
summary
Defines a short one-sentence description of the exploit.
summary 'My first exploit'
description
Defines a longer multi-paragraph description of the exploit.
description <<~EOS
This is my first exploit.
Bla bla bla bla.
EOS
Note: that <<~
heredoc, unlike the regular <<
heredoc, removes
leading whitespace.
author
Add an author's name and additional information to the exploit.
'John Smith'
'doctor_doom', email: '...', twitter: '...'
software
Defines the software which the exploit targets.
software 'TestApp'
software_versions
Defines the software versions which the exploit targets:
software_versions %w[
1.0.0
1.0.1
1.0.2
1.1.0
]
software_versions '1.0.0'..'1.5.4'
param
Defines a user configurable param. Params may have a type class, but
default to String
. Params must have a one-line description.
param :str, desc: 'A basic string param'
param :feature_flag, Boolean, desc: 'A boolean param'
param :enum, Enum[:one, :two, :three],
desc: 'An enum param'
param :num1, Integer, desc: 'An integer param'
param :num2, Integer, default: 42,
desc: 'A param with a default value'
param :num3, Integer, default: ->{ rand(42) },
desc: 'A param with a dynamic default value'
param :float, Float, 'Floating point param'
param :url, URI, desc: 'URL param'
param :pattern, Regexp, desc: 'Regular Expression param'
Params may then be accessed in instance methods using params
Hash.
param :padding, Integer, desc: 'Amount of additional padding'
def build
# ...
if params[:padding]
@buffer << 'A' * params[:padding]
end
end
test
The method which may define tests which confirm whether the target is vulnerable. The method must return a Vulnerable, NotVulnerable, or an #Unknown object.
def test
case http.get_body('/')
when /Powered by Foo 4\.19\./
Vulnerable('host is vulnerable')
when /Powered by Foo 4\.2[0-9]\./
NotVulnerable('host is patched')
else
Unknown('cannot determine whether the host is vulnerable or not')
end
end
build
The method which defines the logic that builds the exploit before launching it.
def build
@buffer = "..."
@buffer << "..."
end
launch
The method which launches the built exploit against the target.
def launch
@socket = tcp_connect do |socket|
socket.write(@buffer)
end
end
cleanup
The method which defines additional cleanup tasks after the exploit has successfully launched and any post-exploitation tasks have been completed.
def cleanup
@socket.close
end
Direct Known Subclasses
Exploit API Methods collapse
-
#build ⇒ Object
abstract
Place holder method that builds the exploit.
-
#cleanup ⇒ Object
abstract
Place holder method that cleans up after the exploit.
-
#fail(message) ⇒ Object
Indicates that the exploit has failed.
-
#launch ⇒ Object
abstract
Place holder method that launches the exploit.
-
#NotVulnerable(message) ⇒ TestResult::NotVulnerable
Returns a not vulnerable test result for the #test method.
-
#test ⇒ Test::Vulnerable, ...
abstract
Place holder method for testing whether the target is vulnerable.
-
#Unknown(message) ⇒ TestResult::Unknown
Returns an unknown test result for the #test method.
-
#validate ⇒ Object
abstract
Place holder methods for additional validation logic.
-
#Vulnerable(message) ⇒ TestResult::Vulnerable
Returns a vulnerable test result for the #test method.
Class Method Summary collapse
-
.advisories ⇒ Set<Advisory>
The advisory IDs for the exploit.
-
.advisory(id, url = Advisory.url_for(id)) ⇒ Object
Adds an advisory for the exploit.
-
.disclosed? ⇒ Boolean
Determines whether the exploit has been disclosed yet.
-
.disclosure_date(new_date = nil) ⇒ Date?
Gets or sets the disclosure date for the exploit.
-
.exploit(**kwargs) {|exploit| ... } ⇒ Exploit
Initializes and runs the exploit.
-
.exploit_type ⇒ Symbol
private
Returns the type or kind of exploit.
-
.quality(new_quality = nil) ⇒ :untested, ...
Gets or sets the quality of the exploit.
-
.register(exploit_id) ⇒ Object
Registers the exploit with the given name.
-
.release_date(new_date = nil) ⇒ Date?
Gets or sets the release date for the exploit.
-
.released? ⇒ Boolean
Determines whether the exploit has been publicly released yet.
-
.software(new_software = nil) ⇒ String?
Gets or sets the software which the exploit targets.
-
.software_versions(new_software_versions = nil) ⇒ Array<String>, ...
Gets or sets the software version(s) which the exploit targets.
Instance Method Summary collapse
-
#exploit(dry_run: false) {|exploit| ... } ⇒ Exploit
Builds the exploit and then launches the exploit.
-
#initialize(**kwargs) ⇒ Exploit
constructor
Initializes the exploit.
-
#perform_build ⇒ Object
Builds the exploit.
-
#perform_cleanup ⇒ Object
Cleans up the exploit.
-
#perform_launch ⇒ Object
Launches the exploit.
-
#perform_test ⇒ Object
Tests whether the target is vulnerable or not.
-
#perform_validate ⇒ Object
Validates that the exploit is ready to be used.
Constructor Details
#initialize(**kwargs) ⇒ Exploit
Initializes the exploit.
452 453 454 |
# File 'lib/ronin/exploits/exploit.rb', line 452 def initialize(**kwargs) super(**kwargs) end |
Class Method Details
.advisories ⇒ Set<Advisory>
The advisory IDs for the exploit.
367 368 369 |
# File 'lib/ronin/exploits/exploit.rb', line 367 def self.advisories @advisories ||= Set.new end |
.advisory(id, url = Advisory.url_for(id)) ⇒ Object
Adds an advisory for the exploit.
383 384 385 |
# File 'lib/ronin/exploits/exploit.rb', line 383 def self.advisory(id,url=Advisory.url_for(id)) advisories << Advisory.new(id,url) end |
.disclosed? ⇒ Boolean
Determines whether the exploit has been disclosed yet.
355 356 357 |
# File 'lib/ronin/exploits/exploit.rb', line 355 def self.disclosed? !disclosure_date.nil? end |
.disclosure_date(new_date = nil) ⇒ Date?
Gets or sets the disclosure date for the exploit.
344 345 346 347 348 |
# File 'lib/ronin/exploits/exploit.rb', line 344 def self.disclosure_date(new_date=nil) if new_date then @disclosure_date = Date.parse(new_date) else @disclosure_date end end |
.exploit(**kwargs) {|exploit| ... } ⇒ Exploit
Initializes and runs the exploit.
475 476 477 |
# File 'lib/ronin/exploits/exploit.rb', line 475 def self.exploit(**kwargs,&block) new(**kwargs).exploit(&block) end |
.exploit_type ⇒ Symbol
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
This is used internally to map an exploit class to a printable type.
Returns the type or kind of exploit.
439 440 441 |
# File 'lib/ronin/exploits/exploit.rb', line 439 def self.exploit_type :exploit end |
.quality(new_quality = nil) ⇒ :untested, ...
Gets or sets the quality of the exploit.
302 303 304 305 306 |
# File 'lib/ronin/exploits/exploit.rb', line 302 def self.quality(new_quality=nil) if new_quality then @new_quality = new_quality else @new_quality end end |
.register(exploit_id) ⇒ Object
Registers the exploit with the given name.
286 287 288 289 |
# File 'lib/ronin/exploits/exploit.rb', line 286 def self.register(exploit_id) id(exploit_id) Exploits.register(exploit_id,self) end |
.release_date(new_date = nil) ⇒ Date?
Gets or sets the release date for the exploit.
317 318 319 320 321 |
# File 'lib/ronin/exploits/exploit.rb', line 317 def self.release_date(new_date=nil) if new_date then @release_date = Date.parse(new_date) else @release_date end end |
.released? ⇒ Boolean
Determines whether the exploit has been publicly released yet.
328 329 330 |
# File 'lib/ronin/exploits/exploit.rb', line 328 def self.released? !release_date.nil? end |
.software(new_software = nil) ⇒ String?
Gets or sets the software which the exploit targets.
398 399 400 401 402 403 404 405 406 |
# File 'lib/ronin/exploits/exploit.rb', line 398 def self.software(new_software=nil) if new_software @software = new_software else @software ||= if superclass < Exploit superclass.software end end end |
.software_versions(new_software_versions = nil) ⇒ Array<String>, ...
Gets or sets the software version(s) which the exploit targets.
419 420 421 422 423 424 425 426 427 |
# File 'lib/ronin/exploits/exploit.rb', line 419 def self.software_versions(new_software_versions=nil) if new_software_versions @software_versions = new_software_versions else @software_versions ||= if superclass < Exploit superclass.software_versions end end end |
Instance Method Details
#build ⇒ Object
Place holder method that builds the exploit.
680 681 |
# File 'lib/ronin/exploits/exploit.rb', line 680 def build end |
#cleanup ⇒ Object
Place holder method that cleans up after the exploit.
704 705 |
# File 'lib/ronin/exploits/exploit.rb', line 704 def cleanup end |
#exploit(dry_run: false) {|exploit| ... } ⇒ Exploit
Builds the exploit and then launches the exploit.
561 562 563 564 565 566 567 568 569 570 571 572 573 574 |
# File 'lib/ronin/exploits/exploit.rb', line 561 def exploit(dry_run: false) perform_build unless dry_run perform_launch if block_given? yield self perform_cleanup end end return self end |
#fail(message) ⇒ Object
Indicates that the exploit has failed.
715 716 717 |
# File 'lib/ronin/exploits/exploit.rb', line 715 def fail() raise(ExploitFailed,) end |
#launch ⇒ Object
Place holder method that launches the exploit.
692 693 |
# File 'lib/ronin/exploits/exploit.rb', line 692 def launch end |
#NotVulnerable(message) ⇒ TestResult::NotVulnerable
Returns a not vulnerable test result for the #test method.
624 625 626 |
# File 'lib/ronin/exploits/exploit.rb', line 624 def NotVulnerable() TestResult::NotVulnerable.new() end |
#perform_build ⇒ Object
Builds the exploit.
513 514 515 |
# File 'lib/ronin/exploits/exploit.rb', line 513 def perform_build build end |
#perform_cleanup ⇒ Object
Cleans up the exploit.
535 536 537 |
# File 'lib/ronin/exploits/exploit.rb', line 535 def perform_cleanup cleanup end |
#perform_launch ⇒ Object
Launches the exploit.
524 525 526 |
# File 'lib/ronin/exploits/exploit.rb', line 524 def perform_launch launch end |
#perform_test ⇒ Object
Tests whether the target is vulnerable or not.
502 503 504 |
# File 'lib/ronin/exploits/exploit.rb', line 502 def perform_test test end |
#perform_validate ⇒ Object
Validates that the exploit is ready to be used.
490 491 492 493 |
# File 'lib/ronin/exploits/exploit.rb', line 490 def perform_validate validate_params validate end |
#test ⇒ Test::Vulnerable, ...
Place holder method for testing whether the target is vulnerable.
667 668 669 |
# File 'lib/ronin/exploits/exploit.rb', line 667 def test Unknown("no vulnerability testing logic defined") end |
#Unknown(message) ⇒ TestResult::Unknown
Returns an unknown test result for the #test method.
642 643 644 |
# File 'lib/ronin/exploits/exploit.rb', line 642 def Unknown() TestResult::Unknown.new() end |
#validate ⇒ Object
Place holder methods for additional validation logic.
589 590 |
# File 'lib/ronin/exploits/exploit.rb', line 589 def validate end |
#Vulnerable(message) ⇒ TestResult::Vulnerable
Returns a vulnerable test result for the #test method.
606 607 608 |
# File 'lib/ronin/exploits/exploit.rb', line 606 def Vulnerable() TestResult::Vulnerable.new() end |