parser.add_argument("-r", "--restore", action='store_true',
help="Restore a backup.")
parser.add_argument("-R", "--recover", action='store_true',
- help="Recover a potentially damaged backup with an index file.")
+ help="Recover a potentially damaged backup with an index "
+ "file. **Caution**: recovery mode is insecure; it ignores "
+ "data integrity checks on encrypted backup sets which may "
+ "allow unauthorized decryption of confidential information.")
parser.add_argument("-f", "--full", action='store_true',
help="Create a full backup.")
parser.add_argument("-d", "--diff", action='store_true',
"""
Walk the index, extracting objects in disaster mode. Bad files are
reported along with a reason.
+
+ *Security considerations*: In *recovery mode* the headers of encrypted
+ objects are assumed damaged and GCM tags are not validated so
+ modification of cryptographically relevant parts of the header (more
+ specifically, the initalization vectors) can no longer be detected. If
+ an attacker can manipulate the encrypted backup set and has access to
+ the plaintext of some of the contents, they may be able to obtain the
+ plaintext of other encrypted objects by injecting initialization
+ vectors. For this reason *recovery mode* should only be used to
+ emergency situations and the contents of the resulting files should be
+ validated manually if possible and not be disclosed to untrusted
+ parties.
"""
return self.restore_backup(target_path,
backup_indexes_paths=backup_indexes_paths,
More aggressive “unfsck” mode: do not rely on the index data as the
files may be corrupt; skim files for header-like information and
attempt to retrieve the data.
+
+ *Security considerations*: As with *recovery mode*, in *rescue mode*
+ the headers of encrypted objects are assumed damaged and GCM tags are
+ not validated so modification of cryptographically relevant parts of
+ the header (more specifically, the initalization vectors) can no longer
+ be detected. If an attacker can manipulate the encrypted backup set and
+ has access to the plaintext of some of the contents, they may be able
+ to obtain the plaintext of other encrypted objects by injecting
+ initialization vectors. For this reason *rescue mode* should only be
+ used to emergency situations and the contents of the resulting files
+ should be validated manually if possible and not be disclosed to
+ untrusted parties.
"""
def gen_volume_name (nvol):
return os.path.join (os.path.dirname (backup_tar_path),
Needless to say, care must be taken to inspect the files reported damaged.
+Security considerations
+-------------------------------------------------------------------------------
+
+With encrypted backup sets, recovery mode omits the GCM authentication tag on
+ciphertext. This introduces a severe flaw in that bad initalization vectors
+will no longer cause decryption to fail. An attacker controlling the backup
+sets (e. g. after subverting the file server) can exploit this to recover
+plaintext from encrypted objects. Thus recovery mode should only ever be used
+as the last resort when dealing with known corrupted files. The decrypted
+result must be conscientiously inspected for manipulation attempts.
+