Recent

Author Topic: Burning strings  (Read 1858 times)

JohnnieK

  • New Member
  • *
  • Posts: 31
Burning strings
« on: November 16, 2020, 03:01:07 pm »
Hi

I am busy developing a TOTP app and in order to keep people from dumping the application memory and getting to the TOTP values, I need to burn all strings when I don't use them anymore. This is done by just overwriting the strings with random characters before disposing of the varialble. Unfortunately the LCL keeps the input values for inputbox in a string somewhere so it stays visible in the memory dump. I was wondering if there is a single place in the source code of the underlying objects that I can add the burn code to, so that all strings will be securely disposed of.

Thanx


marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12984
  • FPC developer.
Re: Burning strings
« Reply #1 on: November 16, 2020, 04:00:25 pm »

*UNTESTED* My guess would be to go to rtl/inc/astrings.inc and make the last part of fpc_ansistr_decr_ref look a little bit something like this:

Code: Pascal  [Select][+][-]
  1.  If declocked(p^.ref) then
  2.   begin
  3.       if p^.len>0 then
  4.         fillchar(s[1],p^.len,#0);
  5.       FreeMem(p);
  6.   end;
  7.  

and possibly something similar for wide/unicdestrings.  Shortstring will be impossible, since as they are static arrays, there is no finalization for them. There is some minor internal RTL use, but not that much, so that might not be a problem. And then recompile everything (FPC and lazarus) since this is unit system and everything depends on that.

There of course will be a performance penalty, but for non performance apps not too bad I hope.

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 12641
  • Debugger - SynEdit - and more
    • wiki
Re: Burning strings
« Reply #2 on: November 16, 2020, 06:33:25 pm »
Write your own MemMananger? Like Heaptrc.
(Actually you can probably forward most calls to an existing mem manager)

Any mem get freed (incl any string) and you can overwrite it.

This  should also allow to catch mem-realloc => in case the string grows.

---
Note: The OS may allocate memory and hold data belonging to TEdit. => that memory will not be cleared. If you want to be sure of that too, then use a custom-drawn input.

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12984
  • FPC developer.
Re: Burning strings
« Reply #3 on: November 16, 2020, 06:39:04 pm »
Write your own MemMananger? Like Heaptrc.

That would NIL all allocations, not just strings. More performance impact, but also more secure since possible buffers are also nilled.

But any zeroing strategy relies on that no unnecessary strings (or buffers containing them) are kept alive, e.g. setting fields that are no longer needed to '' etc, zeroing static buffers, and setlength()ing old buffers.

Quote
This  should also allow to catch mem-realloc => in case the string grows.

If reallocing a string allocates a new string, decref is called on the old one. astrings.inc:808 in trunk

Quote
Note: The OS may allocate memory and hold data belonging to TEdit. => that memory will not be cleared. If you want to be sure of that too, then use a custom-drawn input.

Yes, strings might exist in OS/widget structures too.

P.s. I'm not really a programmer with security aspirations or experience. This is just what I can think of quickly
« Last Edit: November 16, 2020, 06:41:12 pm by marcov »

ASerge

  • Hero Member
  • *****
  • Posts: 2514
Re: Burning strings
« Reply #4 on: November 16, 2020, 07:17:59 pm »
Write your own MemMananger?
This may not help.
Made an example (under Windows). Exe without debugging information, runs without a debugger. However, the dump contains the string.

Code: Pascal  [Select][+][-]
  1. unit uBurnMemManager;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. implementation
  8.  
  9. var
  10.   OldMM: TMemoryManager;
  11.  
  12. function BurnFreeMem(P: Pointer): PtrUInt;
  13. begin
  14.   if Assigned(P) then
  15.     FillChar(P^, OldMM.MemSize(P), 0);
  16.   Result := OldMM.Freemem(P);
  17. end;
  18.  
  19. procedure InitBurnMemManager;
  20. var
  21.   NewMM: TMemoryManager;
  22. begin
  23.   GetMemoryManager(OldMM);
  24.   NewMM := OldMM;
  25.   NewMM.Freemem := @BurnFreeMem;
  26.   SetMemoryManager(NewMM);
  27. end;
  28.  
  29. initialization
  30.   InitBurnMemManager;
  31. end.


Code: Pascal  [Select][+][-]
  1. {$MODE OBJFPC}
  2. {$LONGSTRINGS ON}
  3. {$APPTYPE CONSOLE}
  4.  
  5. uses uBurnMemManager;
  6.  
  7. procedure Test;
  8. var
  9.   S: string;
  10. begin
  11.   S := StringOfChar('~', 40);
  12.   Writeln(S);
  13. end;
  14.  
  15. begin
  16.   Writeln('Make program dump and search multiple ~ chars');
  17.   Test;
  18.   Readln;
  19. end.

In this case, the answer is obvious - the Writeln procedure contains its own buffer. In a complex program, there may be other "helpers" that store a copy of the string.

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12984
  • FPC developer.
Re: Burning strings
« Reply #5 on: November 16, 2020, 08:36:00 pm »
In this case, the answer is obvious - the Writeln procedure contains its own buffer. In a complex program, there may be other "helpers" that store a copy of the string.

This is normal. A temp in the mainprogram  is essentially a global and thus alive for possibly the whole program.

But in most lazarus gui programs, the main program is minimal, so I think this is an exception

 

TinyPortal © 2005-2018