I have been dealing with FTP lately and I'm not sure about the security of the Indy component TIdFTP
. That is why I have created some tests which I want to share with you so you could give your opinion of best practices and how it is done.
First of all I just added the username and password in the component using the Object Inspector:
And created a simple connection which works well:
procedure TForm1.FormActivate(Sender: TObject);
begin
try
FTP.Connect();
ShowMessage ('Connection success');
except
ShowMessage ('Connection failure');
end;
end;
The problem with this method is that if you use a simple tool like Resource Hacker you can immediately see all that data:
Host = 'ivstefano.com'
Password = 'testpass'
Username = 'testuser'
Then I decided to be a little bit smarter by removing it from the OI and inserting it in the code as everybody else does:
FTP.Host:= 'ivstefano.com';
FTP.Username:= 'testuser';
FTP.Password:= 'testpass';
Still if somebody is smarter he can use with ease some tool like Hex editor and see what is in compiled in the exe:
So what I finally did was to make an encryption tool using OTP(One Time Pad Wiki) which you can download from here Sample OTP tool:
I used it to encrypt my password 'testpass' with the keyword 'lemon'. Then I took the OTP encrypted string (#25+#2+#3+#7+#117+#19+#31+#6
) and the key(#108+#101+#109+#111+#110
), both in ASCII sum of characters and used them in my main ftp connection program to decrypt them using OTP again:
function opt(text, key: String): String;
var i: Integer;
begin
SetLength(Result, length(text));
for i:= 1 to length(text) do
Result[i]:= Char(Byte(text[i]) xor (i + Byte(key[i mod length(key)])));
end;
procedure TFTPTester.FormActivate(Sender: TObject);
var decyptedPass: String;
begin
decyptedPass:= opt(#25+#2+#3+#7+#117+#19+#31+#6, #108+#101+#109+#111+#110);
FTP.Host:= 'ivstefano.com';
FTP.Username:= 'testuser';
FTP.Password:= decyptedPass;
try
FTP.Connect();
ShowMessage ('Connection success with pass: ' + decyptedPass);
except
ShowMessage ('Connection failure');
end;
end;
And as you can see it connects properly:
And if we look at the Hex again we can see that the keyphrase and the encrypted password are here but at least not the plain text password:
Conclusion: Still, the "hacker" can see the keyphrase and the encrypted pass but it is going to be harder to guess how to decrypt the pass using the key because he has to reverse engineer the code and see what kind of encryption I have used. Basically I can invent my own encryption and decryption so it is not necessary OTP but if somebody is more advanced he still could see the way I decrypt the encrypted password and access my FTP by applying it to the encrypted pass using the key.
ADDITIONAL THOUGHTS: Maybe obfuscating the Delphi code would be a much better choice?
QUESTION: What is a better way of protecting your password if any?
SOURCES: Here can find the source codes for the FTPTester and OTP generator: Link to both
It doesn't really matter how you store the password. Any kind of storage you use will be hackable with enough reverse engineering. Sooner or later, the plain text version has to be decrypted in memory before it is passed to TIdFTP, and there are tools (IDA, etc) that can view that memory after the decryption occurs. Just run the executable under a debugger and place a breakpoint in the Password
property setter or the Connect
method and view memory when hit.
To make matters worse, the FTP protocol transmits the password in plain text anyway, so even just a plain packet sniffer, such as Wireshark, will be able to see it without hacking the executable at all, unless you use SSL (which Indy 9 and earlier did not support for FTP - upgrade to Indy 10 for that).
I would use some protection tool for softwares, like asprotect to encrypt your exe file.
But anyway as Remy Lebeau said FTP sends the password as plain text, which is a big security hole...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With