~ 2 min read

Decrypting Filezilla Passwords with PHP

One of the most frustrating things I find in managing a number of websites is that I’m always forgetting passwords. The version of Filezilla I’m running however makes it easy to remember them again through its use of weak XOR encryption and a the key being hard coded into the software. I’ve used a program previously called the Filezilla Password Recover, but it turns out that this is also extremely easy to extract them using a simple PHP script. The following code makes use of the nice XML parsing in PHP5 and a decryption function I found over here. I’ve added some comments to roughly describe what is going on.

Note: Apparently this encryption has been dropped from version 3 with absolutely no encryption featured at all, that’ll make my job easier now.

$filezilla_password_file = "FileZilla.xml";

$xml = file_get_contents($filezilla_password_file);

$simple_xml = simplexml_load_string($xml);

foreach($simple_xml->Sites->Site as $site)
{
	$attributes =  $site->attributes();

	print "Site: ".$attributes->Name."\n";
	print "User: ".$attributes->User."\n";
	print "Encrypted Pass: ".$attributes->Pass."\n";
	print "Unencrypted Pass:".decryptPass((string)$attributes->Pass)."\n\n";
}

function decryptPass($pass)
{
        // Encryption Key for FileZilla 2 Passwords
	$key = "FILEZILLA1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ";

	// Find the offset position in the key for this pass
	$pos=(strlen($pass)/3) % strlen($key);
	$decrypt = '';

	$t=0;

	//Loop through each 3rd of the password
	for($i=0;$i < strlen($pass) / 3;$i++) {

        //Get 3 characters, remove the 0 at the
	//front to get ASCII code to represent the character
	$num = substr($pass,$i * 3,3);

	if (substr($num,0,1) == 0) {
		$num = substr($num,1,2);
	}

	//Get the ascii code of the unencrypted character
	//by performing XOR against current ASCII and key
	//before converting back and adding to decrypted pass
		$t = $num ^ ord($key[($i + $pos) % strlen($pass)]);
		 $decrypt .= chr($t);

	}

	// Return the decrypted pass
       return $decrypt;
}