Plesk - Decrypt FTP Passwords

I was working on a project where Plesk user details were being imported into a database and it would help to know the password. Since Plesk 11 the Plesk Client account is hashed which makes it unrecoverable, but other passwords are encrypted with 128 bit AES encryption and a salt.

If the FTP login name is the same as the client login there is a chance the customer was lazy and used the same details. To decrypt the passwords you will need the server secret key and the password string from the plesk database.


The server secret key can be retrieved with the following command on a linux server:

cat /etc/psa/private/secret_key | base64

Matching FTP logins (and their encrypted password) can be retrieved from the Plesk database with:

SELECT REPLACE(s.home, '/var/www/vhosts/', '') AS domain, c.login, a.password
FROM clients c
LEFT JOIN sys_users s ON s.login = c.login
LEFT JOIN accounts a on s.account_id = a.id;

The results will look like:

+----------------------+----------------+----------------------------------------------------------------+
| domain               | login          | password                                                       |
+----------------------+----------------+----------------------------------------------------------------+
| mydomain.com            | alogin        | $AES-128-CBC$VltRIEyCPAtFmC/6+da2rA==$0cgla4FhFk7zM4ptW1w+jw== |
| domain2.com | login2       | $AES-128-CBC$F5KxC5+08WokCkwIsYyD4g==$8r9jEgcPZR2bATIUzeqSxQ== |
| domain3.com | 3rdlogin | $AES-128-CBC$EqGObEecIrZQ4SFC7+tbMg==$bhhEi4Kh/45tCz5LQB537Q== |

+----------------------+----------------+----------------------------------------------------------------+


  1. The salt is the text between the first and second dollar symbols
    e.g. for mydomain.com it is "VltRIEyCPAtFmC/6+da2rA=="
  2. The password is the text between the second and third dollar symbols
    e.g. for mydomain.com it is "
    0cgla4FhFk7zM4ptW1w+jw=="


I found a very good explanation and working PHP code at Plesk 11 – Encrypted / Hashed password – authentication PHP on PSA database, but the article was no longer accessible the last time I tried. I made some minor modifications and the code I used was:


<?php

$key = "fdbwOaYGyXYZtAeWtdUs7Q==";

$hash = explode('$', '$AES-128-CBC$VltRIEyCPAtFmC/6+da2rA==$0cgla4FhFk7zM4ptW1w+jw==');

$iv = base64_decode($hash[2]);
$ct = base64_decode($hash[3]);

$pass = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $ct, MCRYPT_MODE_CBC, $iv);

echo("$pass\r\n");


I needed this to work in perl and the module needed a lot more information than the PHP version. Documentation for the Crypt::CBC module is here https://metacpan.org/pod/Crypt::CBC. After a lot of experimentation and reading, the working code I came up with was:

#!/usr/bin/perl

use strict;
use diagnostics;

use Crypt::CBC;
use MIME::Base64 qw( encode_base64 decode_base64 );



my $cipher  = Crypt::CBC->new(  -literal_key    => 1,
                                -cipher         => 'Rijndael',
                                -key            => decode_base64( 'fdbwOaYGyXYZtAeWtdUs7Q=='),
                                -keysize        => 16,
                                -blocksize      => 16,
                                -header         => 'none',
                                -padding        => 'null',
                                -iv             => decode_base64( 'VltRIEyCPAtFmC/6+da2rA==' )
                                );

my $decoded     = $cipher->decrypt(decode_base64("0cgla4FhFk7zM4ptW1w+jw=="));
print "Decoded: $decoded\n";



Comments

Popular posts from this blog

Linux: Permanent CIFS/SMB mount

IPTables: Clear all rules