hacking on msfweb
git-svn-id: file:///home/svn/incoming/trunk@3069 4d416f70-5f16-0410-b530-b9f4589650daunstable
parent
def6c64abf
commit
adc09f4aa1
Binary file not shown.
After Width: | Height: | Size: 65 KiB |
|
@ -0,0 +1,15 @@
|
|||
<%
|
||||
if ($:.include?(driver.server_local_directory) == false)
|
||||
$:.unshift(driver.server_local_directory)
|
||||
require 'msfweb_common'
|
||||
end
|
||||
%>
|
||||
|
||||
<%= Msf::Ui::Web::Common.header %>
|
||||
|
||||
<br>
|
||||
<div align='center'>
|
||||
Welcome to the Metasploit Framework.
|
||||
</div>
|
||||
|
||||
<%= Msf::Ui::Web::Common.footer %>
|
|
@ -0,0 +1,60 @@
|
|||
module Msf
|
||||
module Ui
|
||||
module Web
|
||||
|
||||
###
|
||||
#
|
||||
# This class implements helper methods for sharing across web pages.
|
||||
#
|
||||
###
|
||||
module Common
|
||||
|
||||
def self.header(active = "none")
|
||||
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">
|
||||
<html>
|
||||
<head>
|
||||
<title>Metasploit Framework Web Console v<%= framework.version %></title>
|
||||
<link type='text/css' rel='stylesheet' href='style.css'/>
|
||||
</head>
|
||||
<body>
|
||||
<br/>
|
||||
|
||||
<div align='center'>
|
||||
<img src='images/logo.jpg' alt='msfweb'/>
|
||||
</div>
|
||||
|
||||
<table align='center' cellpadding='8' border='0' cellspacing='1' width='100%' class='tblInner'>
|
||||
<tr>
|
||||
<td>
|
||||
<table align='center' cellpadding='8' cellspacing='1' width='100%' class='tblOuter'>
|
||||
<tr>
|
||||
<td class='tab" + ((active == "exploits") ? "Light" : "Dark") + "' width='33%' align='center'>
|
||||
<a href='exploits.rhtml'>EXPLOITS</a>
|
||||
</td>
|
||||
<td class='tab" + ((active == "payloads") ? "Light" : "Dark") + "' width='33%' align='center'>
|
||||
<a href='payloads.rhtml'>PAYLOADS</a>
|
||||
</td>
|
||||
<td class='tab" + ((active == "sessions") ? "Light" : "Dark") + "' width='33%' align='center'>
|
||||
<a href='sessions.rhtml'>SESSIONS</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
"
|
||||
end
|
||||
|
||||
def self.footer
|
||||
"
|
||||
<br/>
|
||||
</body>
|
||||
</html>
|
||||
"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,243 @@
|
|||
html {
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
body
|
||||
{
|
||||
background: white;
|
||||
font-family: Verdana, Tahoma, Arial, Helvetica, sans-serif;
|
||||
color: black;
|
||||
font-size: 10pt;
|
||||
margin: 0.1cm 0.5cm 0.1cm 0.5cm;
|
||||
}
|
||||
|
||||
A {
|
||||
font-size: 10pt;
|
||||
text-decoration: none;
|
||||
color: navy;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
|
||||
A:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.tabDark {
|
||||
background: #dddddd;
|
||||
}
|
||||
A.tabDark {
|
||||
|
||||
}
|
||||
|
||||
.tabLight {
|
||||
background: #eeeeee;
|
||||
}
|
||||
A.tabLight {
|
||||
|
||||
}
|
||||
|
||||
.tabActive {
|
||||
|
||||
}
|
||||
A.tabActive {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
|
||||
.sectionTitle {
|
||||
color: black;
|
||||
font-size: 10pt;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.listBody {
|
||||
background: white;
|
||||
color: black;
|
||||
font-size: 10pt;
|
||||
}
|
||||
|
||||
A.nav {
|
||||
font-size: 10pt;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.nav {
|
||||
font-size: 10pt;
|
||||
font-weight: normal;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.navHead {
|
||||
font-size: 10pt;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.copy {
|
||||
font-size: 10pt;
|
||||
font-variant: small-caps;
|
||||
}
|
||||
|
||||
.modHead {
|
||||
font-size: 10pt;
|
||||
font-weight: bold;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.shellcode {
|
||||
font-size: 10pt;
|
||||
font-weight: normal;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.boldText {
|
||||
font-size: 10pt;
|
||||
color: black;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.moduleOutput {
|
||||
font-size: 10pt;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.moduleInfo {
|
||||
font-size: 10pt;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.textNormal {
|
||||
font-size: 10pt;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.textBold {
|
||||
font-size: 10pt;
|
||||
color: black;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.textBoldDark {
|
||||
font-size: 10pt;
|
||||
color: grey;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.textBoldBright {
|
||||
font-size: 10pt;
|
||||
color: black;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
|
||||
.textNormalColorA {
|
||||
background: #eeeeee;
|
||||
font-size: 10pt;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.textBoldColorA {
|
||||
background: #eeeeee;
|
||||
font-size: 10pt;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
|
||||
.textNormalColorB {
|
||||
background: #dddddd;
|
||||
font-size: 10pt;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.textBoldColorB {
|
||||
background: #dddddd;
|
||||
font-size: 10pt;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.tblOuter {
|
||||
background: black;
|
||||
}
|
||||
|
||||
.tblInner {
|
||||
background: white;
|
||||
}
|
||||
|
||||
|
||||
select {
|
||||
color: black;
|
||||
background: #eeeeee;
|
||||
font-weight: bold;
|
||||
padding: 2px 2px 2px 2px;
|
||||
}
|
||||
|
||||
input {
|
||||
font-weight: bold;
|
||||
color: black;
|
||||
background: #eeeeee;
|
||||
color: black;
|
||||
padding: 2px 10px 2px 10px;
|
||||
border: 1px solid grey;
|
||||
}
|
||||
|
||||
input.button {
|
||||
border-left: 1px solid grey;
|
||||
border-top: 1px solid grey;
|
||||
border-bottom: 2px solid black;
|
||||
border-right: 2px solid black;
|
||||
padding: 1px 5px 1px 5px;
|
||||
}
|
||||
|
||||
.iconset
|
||||
{
|
||||
background: white;
|
||||
padding: 2px 2px 2px 2px;
|
||||
border: 1px solid white;
|
||||
}
|
||||
|
||||
.moduleList
|
||||
{
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.moduleIcons
|
||||
{
|
||||
border-top: 1px solid #aaaaaa;
|
||||
border-left: 1em solid #aaaaaa;
|
||||
padding: 0.5em 0em 0em 0.25em;
|
||||
}
|
||||
|
||||
.moduleName
|
||||
{
|
||||
border-top: 1px solid #aaaaaa;
|
||||
padding: 0.5em 0.5em 0em 0em;
|
||||
}
|
||||
|
||||
.moduleSpacer
|
||||
{
|
||||
padding: 10px 0px 0px 0px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.CommandBar {
|
||||
|
||||
}
|
||||
|
||||
#CommandBarList {
|
||||
padding: 0 1px 1px;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
#CommandBarList li {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
display: inline;
|
||||
}
|
||||
|
||||
#CommandBarList li a {
|
||||
}
|
||||
|
||||
#CommandBarList li a:hover {
|
||||
border-bottom: 1px solid #black;
|
||||
}
|
|
@ -37,7 +37,8 @@ class Config < Hash
|
|||
'ModuleDirectory' => "modules",
|
||||
'LogDirectory' => "logs",
|
||||
'SessionLogDirectory' => "logs/sessions",
|
||||
'PluginDirectory' => "plugins"
|
||||
'PluginDirectory' => "plugins",
|
||||
'DataDirectory' => "data"
|
||||
}
|
||||
|
||||
##
|
||||
|
@ -94,6 +95,13 @@ class Config < Hash
|
|||
def self.user_module_directory
|
||||
self.new.user_module_directory
|
||||
end
|
||||
|
||||
#
|
||||
# Calls the instance method.
|
||||
#
|
||||
def self.data_directory
|
||||
self.new.data_directory
|
||||
end
|
||||
|
||||
#
|
||||
# Calls the instance method.
|
||||
|
@ -186,6 +194,13 @@ class Config < Hash
|
|||
config_directory + FileSep + "modules"
|
||||
end
|
||||
|
||||
#
|
||||
# Returns the data directory
|
||||
#
|
||||
def data_directory
|
||||
install_root + FileSep + self['DataDirectory']
|
||||
end
|
||||
|
||||
#
|
||||
# Initializes configuration, creating directories as necessary.
|
||||
#
|
||||
|
|
|
@ -83,6 +83,13 @@ class Framework
|
|||
return modules.recon
|
||||
end
|
||||
|
||||
#
|
||||
# Returns the framework version in Major.Minor format.
|
||||
#
|
||||
def version
|
||||
Version
|
||||
end
|
||||
|
||||
#
|
||||
# Event management interface for registering event handler subscribers and
|
||||
# for interacting with the correlation engine.
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
require 'rex/proto/http'
|
||||
require 'msf/core'
|
||||
require 'msf/base'
|
||||
require 'msf/ui'
|
||||
|
@ -20,6 +21,27 @@ class Driver < Msf::Ui::Driver
|
|||
ConfigCore = "framework/core"
|
||||
ConfigGroup = "framework/ui/web"
|
||||
|
||||
#
|
||||
# The msfweb resource handler that wrappers the default Erb handler.
|
||||
#
|
||||
class ResourceHandler < Rex::Proto::Http::Handler::Erb
|
||||
def initialize(server, root_path, framework, driver, opts = {})
|
||||
opts['ErbCallback'] = ::Proc.new { |erb, cli, request, response|
|
||||
query_string = request.qstring
|
||||
meta_vars = request.meta_vars
|
||||
erb.result(binding)
|
||||
}
|
||||
|
||||
super(server, root_path, opts)
|
||||
|
||||
self.framework = framework
|
||||
self.driver = driver
|
||||
end
|
||||
|
||||
attr_accessor :framework # :nodoc:
|
||||
attr_accessor :driver # :nodoc:
|
||||
end
|
||||
|
||||
#
|
||||
# The default port to listen for HTTP requests on.
|
||||
#
|
||||
|
@ -33,7 +55,17 @@ class Driver < Msf::Ui::Driver
|
|||
#
|
||||
# The default root directory for requests.
|
||||
#
|
||||
DefaultRoot = "/msfweb"
|
||||
DefaultRoot = "/"
|
||||
|
||||
#
|
||||
# The default local directory for msfweb.
|
||||
#
|
||||
DefaultLocalDirectory = Msf::Config.data_directory + File::SEPARATOR + "msfweb"
|
||||
|
||||
#
|
||||
# The default index script.
|
||||
#
|
||||
DefaultIndex = "index.rhtml"
|
||||
|
||||
#
|
||||
# Initializes a web driver instance and prepares it for listening to HTTP
|
||||
|
@ -67,12 +99,16 @@ class Driver < Msf::Ui::Driver
|
|||
|
||||
ilog("Web server started on #{host}:#{port}", LogSource)
|
||||
|
||||
service.add_resource(
|
||||
# Mount the server root directory on the web server instance. We pass
|
||||
# it a custom ErbCallback so that we can have it run in a context that
|
||||
# has the framework instance defined.
|
||||
service.mount(
|
||||
server_root,
|
||||
'Directory' => true,
|
||||
'Proc' => Proc.new { |cli, req|
|
||||
on_request(cli, req)
|
||||
})
|
||||
ResourceHandler,
|
||||
false,
|
||||
server_local_directory,
|
||||
framework,
|
||||
self)
|
||||
|
||||
# Wait for the termination event to be set.
|
||||
term_event.wait
|
||||
|
@ -93,12 +129,26 @@ class Driver < Msf::Ui::Driver
|
|||
end
|
||||
|
||||
#
|
||||
# Returns the root resource name, such as '/msfweb'
|
||||
# Returns the root resource name, such as '/msfweb'.
|
||||
#
|
||||
def server_root
|
||||
opts['ServerRoot'] || DefaultRoot
|
||||
end
|
||||
|
||||
#
|
||||
# Returns the server index, such as 'index.rhtml'.
|
||||
#
|
||||
def server_index
|
||||
opts['ServerIndex'] || DefaultIndex
|
||||
end
|
||||
|
||||
#
|
||||
# Returns the local directory that will hold the files to be serviced.
|
||||
#
|
||||
def server_local_directory
|
||||
opts['ServerLocalDirectory'] || DefaultLocalDirectory
|
||||
end
|
||||
|
||||
#
|
||||
# The framework instance associated with this driver.
|
||||
#
|
||||
|
|
|
@ -43,6 +43,9 @@ class Handler::Erb < Handler
|
|||
wlog("Erb::on_request: Dangerous request performed: #{resource}",
|
||||
LogSource)
|
||||
return
|
||||
# If the request is for the root directory, use the document index file.
|
||||
elsif (resource == '/')
|
||||
resource += opts['DocumentIndex'] || 'index.rhtml'
|
||||
end
|
||||
|
||||
begin
|
||||
|
@ -51,22 +54,28 @@ class Handler::Erb < Handler
|
|||
# Calculate the actual file path on disk.
|
||||
file_path = root_path + resource
|
||||
|
||||
puts "file path is #{file_path}"
|
||||
|
||||
# Serialize the contents of the file
|
||||
data = ::IO.readlines(file_path).join
|
||||
|
||||
# Evaluate the data and set the output as the response body.
|
||||
resp.body = evaluate(ERB.new(data), cli, req, resp)
|
||||
# Set the content-type to text/html by default. We do this before
|
||||
# evaluation so that the script can change it.
|
||||
resp['Content-Type'] = server.mime_type(resource)
|
||||
|
||||
# Set the content-type to text/html by default.
|
||||
resp['Content-Type'] = opts['MimeType']
|
||||
# If the requested file is a ruby html file, evaluate it.
|
||||
if (File.extname(file_path) == ".rhtml")
|
||||
# Evaluate the data and set the output as the response body.
|
||||
resp.body = evaluate(ERB.new(data), cli, req, resp)
|
||||
# Otherwise, just set the body to the data that was read.
|
||||
else
|
||||
resp.body = data
|
||||
end
|
||||
rescue
|
||||
elog("Erb::on_request: #{$!}\n\n#{$@.join("\n")}", LogSource)
|
||||
elog("Erb::on_request: #{$!}", LogSource)
|
||||
|
||||
puts "exception: #{$!} #{$@.join("\n")}"
|
||||
# Send a standard 404 message.
|
||||
server.send_e404(cli, req)
|
||||
|
||||
resp = Response::E404.new
|
||||
resp = nil
|
||||
end
|
||||
|
||||
# Send the response to the
|
||||
|
@ -83,8 +92,8 @@ class Handler::Erb < Handler
|
|||
def evaluate(erb, cli, request, response)
|
||||
# If the thing that created this handler wanted us to use a callback
|
||||
# instead of the default behavior, then let's do that.
|
||||
if (opts['Callback'])
|
||||
opts['Callback'].call(erb, cli, request, response)
|
||||
if (opts['ErbCallback'])
|
||||
opts['ErbCallback'].call(erb, cli, request, response)
|
||||
else
|
||||
Module.new.module_eval {
|
||||
query_string = request.qstring
|
||||
|
|
|
@ -69,8 +69,35 @@ class Server
|
|||
|
||||
include Proto
|
||||
|
||||
#
|
||||
# A hash that associated a file extension with a mime type for use as the
|
||||
# content type of responses.
|
||||
#
|
||||
ExtensionMimeTypes =
|
||||
{
|
||||
"rhtml" => "text/html",
|
||||
"html" => "text/html",
|
||||
"htm" => "text/htm",
|
||||
"jpg" => "image/jpeg",
|
||||
"jpeg" => "image/jpeg",
|
||||
"jpeg" => "image/jpeg",
|
||||
"gif" => "image/gif",
|
||||
"png" => "image/png",
|
||||
"bmp" => "image/bmp",
|
||||
"txt" => "text/plain",
|
||||
"css" => "text/css",
|
||||
}
|
||||
|
||||
#
|
||||
# The default server name that will be returned in the Server attribute of
|
||||
# a response.
|
||||
#
|
||||
DefaultServer = "Rex"
|
||||
|
||||
#
|
||||
# Initializes an HTTP server as listening on the provided port and
|
||||
# hostname.
|
||||
#
|
||||
def initialize(port = 80, listen_host = '0.0.0.0')
|
||||
self.listen_host = listen_host
|
||||
self.listen_port = port
|
||||
|
@ -170,6 +197,38 @@ class Server
|
|||
resp['Server'] = DefaultServer
|
||||
end
|
||||
|
||||
#
|
||||
# Returns the mime type associated with the supplied file. Right now the
|
||||
# set of mime types is fairly limited.
|
||||
#
|
||||
def mime_type(file)
|
||||
type = nil
|
||||
|
||||
if (file =~ /\.(.+?)$/)
|
||||
type = ExtensionMimeTypes[$1.downcase]
|
||||
end
|
||||
|
||||
type || "text/plain"
|
||||
end
|
||||
|
||||
#
|
||||
# Sends a 404 error to the client for a given request.
|
||||
#
|
||||
def send_e404(cli, request)
|
||||
resp = Response::E404.new
|
||||
|
||||
resp.body =
|
||||
"<html><head>" +
|
||||
"<title>404 Not Found</title" +
|
||||
"</head><body>" +
|
||||
"<h1>Not found</h1>" +
|
||||
"The requested URL #{request.resource} was not found on this server.<p><hr>" +
|
||||
"</body></html>"
|
||||
|
||||
# Send the response to the client like what
|
||||
cli.send_response(resp)
|
||||
end
|
||||
|
||||
attr_accessor :listen_port, :listen_host
|
||||
|
||||
protected
|
||||
|
@ -233,7 +292,6 @@ protected
|
|||
end
|
||||
}
|
||||
|
||||
begin
|
||||
if (p)
|
||||
# Create an instance of the handler for this resource
|
||||
handler = p[0].new(self, *p[2])
|
||||
|
@ -242,9 +300,10 @@ begin
|
|||
if (p[0].relative_resource_required?)
|
||||
# Substituted the mount point root in the request to make things
|
||||
# relative to the mount point.
|
||||
request.relative_resource = request.resource.gsub(root, '')
|
||||
request.relative_resource = request.resource.gsub(/^#{root}/, '')
|
||||
request.relative_resource = '/' + request.relative_resource if (request.relative_resource !~ /^\//)
|
||||
end
|
||||
|
||||
|
||||
# If we found the resource handler for this resource, call its
|
||||
# procedure.
|
||||
|
@ -266,27 +325,6 @@ begin
|
|||
if (cli.keepalive == false)
|
||||
close_client(cli)
|
||||
end
|
||||
rescue
|
||||
puts "bleh #{$!} #{$@.join("\n")}"
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Sends a 404 error to the client for a given request.
|
||||
#
|
||||
def send_e404(cli, request)
|
||||
resp = Response::E404.new
|
||||
|
||||
resp.body =
|
||||
"<html><head>" +
|
||||
"<title>404 Not Found</title" +
|
||||
"</head><body>" +
|
||||
"<h1>Not found</h1>" +
|
||||
"The requested URL #{request.resource} was not found on this server.<p><hr>" +
|
||||
"</body></html>"
|
||||
|
||||
# Send the response to the client like what
|
||||
cli.send_response(resp)
|
||||
end
|
||||
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue