0

We need to protect customer data and using FirebirdSQL 2.5(.8) with Delphi 7.
Also it is essential to do regular backups on "secondary" PC, or pen-drives if the "master" fails.

For that we used this method, calling Gbak.exe and 7z.exe with stdin/out.
Realized that was a bad idea because it's very easy to see the parameters (passwords) added to command line during the process, even with a simple Task-manager.

Is there a more secure way to do it?
(Using standard Interbase componenst OR UIB)

Mark Rotteveel
  • 82,132
  • 136
  • 114
  • 158
SzakiLaci
  • 185
  • 9
  • Stackoverflow is for [programming questions](https://stackoverflow.com/help/on-topic). Questions about **general computing hardware and software** are off-topic for Stack Overflow unless they directly involve tools used primarily for programming. You may be able to get help on [Super User](https://superuser.com/about). – President James K. Polk Mar 25 '18 at 15:54
  • @James, I don't believe that you can start a process that won't be visible e.g. by Process Explorer. The question is how to eliminate entering password for the 7-zip tool. Possible workaround might be sending standard output to your application and encrypt by yourself there (as it seems that 7-zip tool doesn't allow you to enter e.g. hashed password). – Victoria Mar 25 '18 at 15:57
  • @Victoria: Agreed, but you can specify a file name or some other resource name that points to the sensitive information, rather than having the sensitive information directly on the command-line. In any event Super User is the correct place for such questions. – President James K. Polk Mar 25 '18 at 16:01
  • 1
    @James, I don't agree. Maybe to Database Administrators, but still. The question is more or less, how to eliminate inserting password in plain text on command line, ergo how to eliminate that 7-zip tool. Maybe even IBX or UIB components provide the way to backup to a stream (which would be the real solution). I'll check that later. – Victoria Mar 25 '18 at 16:17
  • I believe you can do it in IBX and UIB if you read their sources on how they use FB Services API for backup/restore and then modify the libraries to include your custom transformation of data streams. However one global hardcoded password might get relatively easily extracted form the application, so the added security would not really be much. Also, what about making usual GBK then compressing/encrypting it, then wiping the GBK file before deleting ? – Arioch 'The Mar 27 '18 at 10:48
  • @JamesKPolk I've searched everywhere and the answer was always the same: it is impossible to hide the parameters. So Victoria is right, the only possible solution is somehow stream the data and compress/encrypt with Delphi code. The question is how to do that? – SzakiLaci Mar 27 '18 at 17:04
  • Okay, I read IB6 API Guide, seems Services API only provide for server-local operations, which indeed would require server-side files for output. However, since you can make local GBAK.EXE output the stream into STDOUT what you seemingly have to do is to make your program read GBAK's output and encrypt/compress it inside itself. There are a number of 7zip DLL API wrappers, such as JEDI CodeLib and others, if you want to have the same output as before. Or you can use any of many Delphi encryption libs, is compression is not that important – Arioch 'The Mar 28 '18 at 09:41
  • Look how Delphi is used to read output from spawned console programs, that do it with the first half of your current method to read GBAK's output – Arioch 'The Mar 28 '18 at 09:42
  • 1
    @Arioch, that's just what I said in my answer below. – Victoria Mar 29 '18 at 15:01
  • @Arioch'The Yes, as Victoria already wrote below, this is a great idea, but only HALF solution, because it would still reveal GBAK.exe parameters: [secret location and name of the database] + [Username] + [DB-password] during the whole (loooong) backup and restore process. – SzakiLaci Mar 30 '18 at 11:12
  • "secret location and name of the database" - not a secret at all, SysInternals Process Monitor would show it at once. "[Username] + [DB-password]" again, any more or less savvy user i bet would sniff them out using something like WireShark. However, if you are so wary about it - do not put them in command line but into Environment Variables instead. This would take you supplying modified EnvVars block to CreateProcess API, and tools like SysInternals Process Explorer I believe can show them, but now Windows 7 Task Manager – Arioch 'The Mar 30 '18 at 15:03

2 Answers2

1

Upgrade to Firebird 3 which added Database Encryption capability. If you don't want or cannot, I believe you might run the GBAK tool from your application with the STDOUT option but instead of using 7-zip for compression you would read that output in your application, and encrypt such input by some encryption library on the fly.

I believe you may find many examples how to run an application and read its standard output over here (here is something related to start with), so the rest might be about finding a way of an on the fly stream encryption. Or just capturing STDOUT in one stream and encypting in another.

Victoria
  • 7,477
  • 2
  • 18
  • 40
  • Services API provide the GBK stream which can be transformed (like encrypted, compressed or anything) before being written to disk. One has to look into UIB/IBX sources into backup/restore components to see how they are doing it. – Arioch 'The Mar 27 '18 at 10:45
  • @Arioch, which API function are we talking about? Services API use service tasks that can backup at most to a file. – Victoria Mar 27 '18 at 15:49
  • @Victoria Yes, at first sight this seems to be the ideal solution. But also gives the biggest riddle... how to automate update from FB2.5 to FB3.0/4.0 with the help of a single .EXE? The devs did not implement backward compatibility, so the 3.0 engine already installed can not backup a 2.5 database. – SzakiLaci Mar 27 '18 at 16:54
  • @Victoria About the basic idea: replacing 7z.exe with my own exe to compress the stream: this is a fantastic idea! I started to look into it how a Delphi app can accept an input stream. – SzakiLaci Mar 27 '18 at 17:35
  • It is not ideal. Ideal might be modifying existing GBAK tool in your case (in C++). Services API (for FB 2.5) allows backup only to files, not streams, so you're quite out of luck there. My suggested way is pretty hacky though might work in Delphi with FB 2.5. – Victoria Mar 27 '18 at 23:14
  • @Victoria it seems that starting with 2.5.2. Services API can send out the FBK stream, though it is scarcely documented and is incompatible with verbose diagnostics – Arioch 'The Apr 17 '18 at 13:39
1

Firebird guys on SQL.ru forum say, that actually it is possible to use Services API to get backup stream remotely. That does not mean that IBX or UIB or any other library readily support it though. Maybe it does, maybe not.

They suggested to read Release Notes for Firebird 2.5.2 or Part 4 of doc\README.services_extension.txt files of Firebird 2.5.2+ installation.

Below is a small excerpt from the latter:

The simplest way to use this feature is fbsvcmgr. To backup database run approximately the following:

fbsvcmgr remotehost:service_mgr -user sysdba -password XXX action_backup -dbname some.fdb -bkp_file stdout >some.fbk

and to restore it:

fbsvcmgr remotehost:service_mgr -user sysdba -password XXX action_restore -dbname some.fdb -bkp_file stdin <some.fbk

Please notice - you can't use "verbose" switch when performing backup because data channel from server to client is used to deliver blocks of fbk files. You will get appropriate error message if you try to do it. When restoring database verbose mode may be used without limitations.

If you want to perform backup/restore from your own program, you should use services API for it. Backup is very simple - just pass "stdout" as backup file name to server and use isc_info_svc_to_eof in isc_service_query() call. Data, returned by repeating calls to isc_service_query() (certainly with isc_info_svc_to_eof tag) is a stream, representing image of backup file.

Restore is a bit more tricky. Client sends new spb parameter isc_info_svc_stdin to server in isc_service_query(). If service needs some data in stdin, it returns isc_info_svc_stdin in query results, followed by 4-bytes value - number of bytes server is ready to accept from client. (0 value means no more data is needed right now.) The main trick is that client should NOT send more data than requested by server - this causes an error "Size of data is more than requested". The data is sent in next isc_service_query() call in the send_items block, using isc_info_svc_line tag in traditional form: isc_info_svc_line, 2 bytes length, data. When the server needs next portion, it once more returns non-zero isc_info_svc_stdin value from isc_service_query().

A sample of how services API should be used for remote backup and restore can be found in source code of fbsvcmgr.

Arioch 'The
  • 15,005
  • 31
  • 59
  • @Victoria no. Here "stdout" is just a magic string literal to transfer FBK stream by network into the program's memory. It does not take launching external executable (gbak.exe) nor tweaking that executable input/output pipes. You just use the same Service API based backup components and have the backup stream all within your application. Just were the verbose text log was being received by those libraries, binary FBK data would get received instead. Maybe libs modifications would be needed. Then the TS can utilize any libs like Spring4D or LockBox to encrypt the stream. – Arioch 'The Apr 17 '18 at 14:10
  • I know the meaning of that switch. Hence I've suggested capturing STDOUT in your own application. Whether you use GBAK tool or the service directly is not so important. In the end, there is no API function that could backup to a stream, only to STDOUT (that you can capture after). – Victoria Apr 17 '18 at 14:21
  • "I know the meaning of that switch." - skip the short demo part, read the longer API part. There is no "switches" there are "magic string constants" to be put into SPB structure. "there is no API function that could backup to a stream" - the quoted documentation contradicts it, it explicitly names the API functions to be called to get FBK stream into your application. "only to STDOUT (that you can capture after)." - Services API can not work with your application stdin/stdout/stderr. If you want to forward Services API messages to stdout - you have to explicitly code proxy for it. – Arioch 'The Apr 17 '18 at 14:35
  • Aha, I see now. Sorry, then. Will try this. – Victoria Apr 17 '18 at 17:15