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:
: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) ⇒ :testing, ...
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.
450 451 452 |
# File 'lib/ronin/exploits/exploit.rb', line 450 def initialize(**kwargs) super(**kwargs) end |
Class Method Details
.advisories ⇒ Set<Advisory>
The advisory IDs for the exploit.
365 366 367 |
# File 'lib/ronin/exploits/exploit.rb', line 365 def self.advisories @advisories ||= Set.new end |
.advisory(id, url = Advisory.url_for(id)) ⇒ Object
Adds an advisory for the exploit.
381 382 383 |
# File 'lib/ronin/exploits/exploit.rb', line 381 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.
353 354 355 |
# File 'lib/ronin/exploits/exploit.rb', line 353 def self.disclosed? !disclosure_date.nil? end |
.disclosure_date(new_date = nil) ⇒ Date?
Gets or sets the disclosure date for the exploit.
342 343 344 345 346 |
# File 'lib/ronin/exploits/exploit.rb', line 342 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.
473 474 475 |
# File 'lib/ronin/exploits/exploit.rb', line 473 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.
437 438 439 |
# File 'lib/ronin/exploits/exploit.rb', line 437 def self.exploit_type :exploit end |
.quality(new_quality = nil) ⇒ :testing, ...
Gets or sets the quality of the exploit.
300 301 302 303 304 |
# File 'lib/ronin/exploits/exploit.rb', line 300 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.
284 285 286 287 |
# File 'lib/ronin/exploits/exploit.rb', line 284 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.
315 316 317 318 319 |
# File 'lib/ronin/exploits/exploit.rb', line 315 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.
326 327 328 |
# File 'lib/ronin/exploits/exploit.rb', line 326 def self.released? !release_date.nil? end |
.software(new_software = nil) ⇒ String?
Gets or sets the software which the exploit targets.
396 397 398 399 400 401 402 403 404 |
# File 'lib/ronin/exploits/exploit.rb', line 396 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.
417 418 419 420 421 422 423 424 425 |
# File 'lib/ronin/exploits/exploit.rb', line 417 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.
678 679 |
# File 'lib/ronin/exploits/exploit.rb', line 678 def build end |
#cleanup ⇒ Object
Place holder method that cleans up after the exploit.
702 703 |
# File 'lib/ronin/exploits/exploit.rb', line 702 def cleanup end |
#exploit(dry_run: false) {|exploit| ... } ⇒ Exploit
Builds the exploit and then launches the exploit.
559 560 561 562 563 564 565 566 567 568 569 570 571 572 |
# File 'lib/ronin/exploits/exploit.rb', line 559 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.
713 714 715 |
# File 'lib/ronin/exploits/exploit.rb', line 713 def fail() raise(ExploitFailed,) end |
#launch ⇒ Object
Place holder method that launches the exploit.
690 691 |
# File 'lib/ronin/exploits/exploit.rb', line 690 def launch end |
#NotVulnerable(message) ⇒ TestResult::NotVulnerable
Returns a not vulnerable test result for the #test method.
622 623 624 |
# File 'lib/ronin/exploits/exploit.rb', line 622 def NotVulnerable() TestResult::NotVulnerable.new() end |
#perform_build ⇒ Object
Builds the exploit.
511 512 513 |
# File 'lib/ronin/exploits/exploit.rb', line 511 def perform_build build end |
#perform_cleanup ⇒ Object
Cleans up the exploit.
533 534 535 |
# File 'lib/ronin/exploits/exploit.rb', line 533 def perform_cleanup cleanup end |
#perform_launch ⇒ Object
Launches the exploit.
522 523 524 |
# File 'lib/ronin/exploits/exploit.rb', line 522 def perform_launch launch end |
#perform_test ⇒ Object
Tests whether the target is vulnerable or not.
500 501 502 |
# File 'lib/ronin/exploits/exploit.rb', line 500 def perform_test test end |
#perform_validate ⇒ Object
Validates that the exploit is ready to be used.
488 489 490 491 |
# File 'lib/ronin/exploits/exploit.rb', line 488 def perform_validate validate_params validate end |
#test ⇒ Test::Vulnerable, ...
Place holder method for testing whether the target is vulnerable.
665 666 667 |
# File 'lib/ronin/exploits/exploit.rb', line 665 def test Unknown("no vulnerability testing logic defined") end |
#Unknown(message) ⇒ TestResult::Unknown
Returns an unknown test result for the #test method.
640 641 642 |
# File 'lib/ronin/exploits/exploit.rb', line 640 def Unknown() TestResult::Unknown.new() end |
#validate ⇒ Object
Place holder methods for additional validation logic.
587 588 |
# File 'lib/ronin/exploits/exploit.rb', line 587 def validate end |
#Vulnerable(message) ⇒ TestResult::Vulnerable
Returns a vulnerable test result for the #test method.
604 605 606 |
# File 'lib/ronin/exploits/exploit.rb', line 604 def Vulnerable() TestResult::Vulnerable.new() end |