A.M. Hoornweg 144 Posted March 27, 2020 Hello all, I'd like to know if it is possible to activate the FastMM4 Option "AlwaysClearFreedMemory" temporarily/on demand in code? The reason being that some of my routines work with confidential passwords/hashes. Delphi often uses temporary "hidden" strings and interfaces (for example when concatenating strings) so there's the risk of legible stuff remaining in RAM when such a routine exits. Share this post Link to post
Fr0sT.Brutal 900 Posted March 27, 2020 (edited) Just control the copies carefully. Everything Delphi does with strings could be imitated with manually allocated buffers that are cleaned manually. Edited March 27, 2020 by Fr0sT.Brutal Share this post Link to post
David Heffernan 2353 Posted March 27, 2020 (edited) 1 hour ago, A.M. Hoornweg said: Hello all, I'd like to know if it is possible to activate the FastMM4 Option "AlwaysClearFreedMemory" temporarily/on demand in code? The reason being that some of my routines work with confidential passwords/hashes. Delphi often uses temporary "hidden" strings and interfaces (for example when concatenating strings) so there's the risk of legible stuff remaining in RAM when such a routine exits. That's surely not the right solution to the problem. The right solution is to implement the critical code following standard security practices. And to then get it audited by a security expert. Edited March 27, 2020 by David Heffernan 1 Share this post Link to post
Remy Lebeau 1436 Posted March 27, 2020 (edited) 3 hours ago, A.M. Hoornweg said: I'd like to know if it is possible to activate the FastMM4 Option "AlwaysClearFreedMemory" temporarily/on demand in code? No, it is not, because AlwaysClearFreedMemory is a compile-time {$define}, not a runtime variable (like ReportMemoryLeaksOnShutdown is, for instance). It is processed only when FastMM4.pas is being compiled. There was a feature request made 2 years ago asking for AlwaysClearFreedMemory to be configurable at runtime. It is still open: #51 Feature request regarding option "AlwaysClearFreedMemory" Quote The reason being that some of my routines work with confidential passwords/hashes. Delphi often uses temporary "hidden" strings and interfaces (for example when concatenating strings) so there's the risk of legible stuff remaining in RAM when such a routine exits. Then don't do such things on strings/interfaces containing sensitive data. And do use things like the CryptProtectMemory(), CryptUnprotectData(), and SecureZeroMemory() functions to secure the sensitive data in memory while you are not actively using it. Edited March 27, 2020 by Remy Lebeau Share this post Link to post
A.M. Hoornweg 144 Posted March 30, 2020 (edited) On 3/27/2020 at 7:02 PM, Remy Lebeau said: Then don't do such things on strings/interfaces containing sensitive data. And do use things like the CryptProtectMemory(), CryptUnprotectData(), and SecureZeroMemory() functions to secure the sensitive data in memory while you are not actively using it. My application needs to call sp_setapprole on MS SQL Server which requires a user name and password. So for a brief time I need these in cleartext form. They are currently stored in an AES encrypted file and I decrypt them on the fly when I need them, using Turbopower Lockbox 2.09. I have no way of knowing if its decryption engine leaves any decoded text in freed blocks on the heap so I thought it would be great if I could simply instruct the heap manager to wipe whatever memory is released. This would prevent the password from appearing in a memory dump. Edit: The actual SQL Query is executed using connection.execute(format('exec sp_setapprole ''%s'', {Encrypt N ''%s''}, ''odbc''', [Approle, Approlepassword])); so I cannot exclude the possibility that the "execute" and the "format" commands might put temporary stuff on the heap as well. [edit] the GitHub feature request you mentioned was mine... Edited March 30, 2020 by A.M. Hoornweg Share this post Link to post
Fr0sT.Brutal 900 Posted April 3, 2020 Just construct a full string preliminary connStr := format('... password ...'); then execute connection.execute(connStr) and then clear it ZeroMemory(connStr, Length(connStr)*SizeOf(Char)) if DB access components are not doing something hidden, the only copy of connection string will now be erased. Of course, you'll have to erase contents of Windows edit control as well. That's probably a harder task 🙂 Maybe overwriting .Text property with some random string will help. Share this post Link to post