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.
451 452 453 |
# File 'lib/ronin/exploits/exploit.rb', line 451 def initialize(**kwargs) super(**kwargs) end |
Class Method Details
.advisories ⇒ Set<Advisory>
The advisory IDs for the exploit.
366 367 368 |
# File 'lib/ronin/exploits/exploit.rb', line 366 def self.advisories @advisories ||= Set.new end |
.advisory(id, url = Advisory.url_for(id)) ⇒ Object
Adds an advisory for the exploit.
382 383 384 |
# File 'lib/ronin/exploits/exploit.rb', line 382 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.
354 355 356 |
# File 'lib/ronin/exploits/exploit.rb', line 354 def self.disclosed? !disclosure_date.nil? end |
.disclosure_date(new_date = nil) ⇒ Date?
Gets or sets the disclosure date for the exploit.
343 344 345 346 347 |
# File 'lib/ronin/exploits/exploit.rb', line 343 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.
474 475 476 |
# File 'lib/ronin/exploits/exploit.rb', line 474 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.
438 439 440 |
# File 'lib/ronin/exploits/exploit.rb', line 438 def self.exploit_type :exploit end |
.quality(new_quality = nil) ⇒ :untested, ...
Gets or sets the quality of the exploit.
301 302 303 304 305 |
# File 'lib/ronin/exploits/exploit.rb', line 301 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.
285 286 287 288 |
# File 'lib/ronin/exploits/exploit.rb', line 285 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.
316 317 318 319 320 |
# File 'lib/ronin/exploits/exploit.rb', line 316 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.
327 328 329 |
# File 'lib/ronin/exploits/exploit.rb', line 327 def self.released? !release_date.nil? end |
.software(new_software = nil) ⇒ String?
Gets or sets the software which the exploit targets.
397 398 399 400 401 402 403 404 405 |
# File 'lib/ronin/exploits/exploit.rb', line 397 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.
418 419 420 421 422 423 424 425 426 |
# File 'lib/ronin/exploits/exploit.rb', line 418 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.
679 680 |
# File 'lib/ronin/exploits/exploit.rb', line 679 def build end |
#cleanup ⇒ Object
Place holder method that cleans up after the exploit.
703 704 |
# File 'lib/ronin/exploits/exploit.rb', line 703 def cleanup end |
#exploit(dry_run: false) {|exploit| ... } ⇒ Exploit
Builds the exploit and then launches the exploit.
560 561 562 563 564 565 566 567 568 569 570 571 572 573 |
# File 'lib/ronin/exploits/exploit.rb', line 560 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.
714 715 716 |
# File 'lib/ronin/exploits/exploit.rb', line 714 def fail() raise(ExploitFailed,) end |
#launch ⇒ Object
Place holder method that launches the exploit.
691 692 |
# File 'lib/ronin/exploits/exploit.rb', line 691 def launch end |
#NotVulnerable(message) ⇒ TestResult::NotVulnerable
Returns a not vulnerable test result for the #test method.
623 624 625 |
# File 'lib/ronin/exploits/exploit.rb', line 623 def NotVulnerable() TestResult::NotVulnerable.new() end |
#perform_build ⇒ Object
Builds the exploit.
512 513 514 |
# File 'lib/ronin/exploits/exploit.rb', line 512 def perform_build build end |
#perform_cleanup ⇒ Object
Cleans up the exploit.
534 535 536 |
# File 'lib/ronin/exploits/exploit.rb', line 534 def perform_cleanup cleanup end |
#perform_launch ⇒ Object
Launches the exploit.
523 524 525 |
# File 'lib/ronin/exploits/exploit.rb', line 523 def perform_launch launch end |
#perform_test ⇒ Object
Tests whether the target is vulnerable or not.
501 502 503 |
# File 'lib/ronin/exploits/exploit.rb', line 501 def perform_test test end |
#perform_validate ⇒ Object
Validates that the exploit is ready to be used.
489 490 491 492 |
# File 'lib/ronin/exploits/exploit.rb', line 489 def perform_validate validate_params validate end |
#test ⇒ Test::Vulnerable, ...
Place holder method for testing whether the target is vulnerable.
666 667 668 |
# File 'lib/ronin/exploits/exploit.rb', line 666 def test Unknown("no vulnerability testing logic defined") end |
#Unknown(message) ⇒ TestResult::Unknown
Returns an unknown test result for the #test method.
641 642 643 |
# File 'lib/ronin/exploits/exploit.rb', line 641 def Unknown() TestResult::Unknown.new() end |
#validate ⇒ Object
Place holder methods for additional validation logic.
588 589 |
# File 'lib/ronin/exploits/exploit.rb', line 588 def validate end |
#Vulnerable(message) ⇒ TestResult::Vulnerable
Returns a vulnerable test result for the #test method.
605 606 607 |
# File 'lib/ronin/exploits/exploit.rb', line 605 def Vulnerable() TestResult::Vulnerable.new() end |