Ugarit
Documentation
Login

Security model

I have designed and implemented Ugarit to be able to handle cases where the actual vault storage is not entirely trusted.

However, security involves tradeoffs, and Ugarit is configurable in ways that affect its resistance to different kinds of attacks. Here I will list different kinds of attack and explain how Ugarit can deal with them, and how you need to configure it to gain that protection.

Vault snoopers

This might be somebody who can intercept Ugarit's communication with the vault at any point, or who can read the vault itself at their leisure.

Ugarit's splitlog backend creates files with "rw-------" permissions out of the box to try and prevent this. This is a pain for people who want to share vaults between UIDs, but we can add a configuration option to override this if that becomes a problem.

Reading your data

If you enable encryption, then all the blocks sent to the vault are encrypted using a secret key stored in your Ugarit configuration file. As long as that configuration file is kept safe, and the AES algorithm is secure, then attackers who can snoop the vault cannot decode your data blocks. Enabling compression will also help, as the blocks are compressed before encrypting, which is thought to make cryptographic analysis harder.

Recommendations: Use compression and encryption when there is a risk of vault snooping. Keep your Ugarit configuration file safe using UNIX file permissions (make it readable only by root), and maybe store it on a removable device that's only plugged in when required. Alternatively, use the "prompt" passphrase option, and be prompted for a passphrase every time you run Ugarit, so it isn't stored on disk anywhere.

Looking for known hashes

A block is identified by the hash of its content (before compression and encryption). If an attacker was trying to find people who own a particular file (perhaps a piece of subversive literature), they could search Ugarit vaults for its hash.

However, Ugarit has the option to "key" the hash with a "salt" stored in the Ugarit configuration file. This means that the hashes used are actually a hash of the block's contents *and* the salt you supply. If you do this with a random salt that you keep secret, then attackers can't check your vault for known content just by comparing the hashes.

Recommendations: Provide a secret string to your hash function in your Ugarit configuration file. Keep the Ugarit configuration file safe, as per the advice in the previous point.

Vault modifiers

These folks can modify Ugarit's writes into the vault, its reads back from the vault, or can modify the vault itself at their leisure.

Modifying an encrypted block without knowing the encryption key can at worst be a denial of service, corrupting the block in an unknown way. An attacker who knows the encryption key could replace a block with valid-seeming but incorrect content. In the worst case, this could exploit a bug in the decompression engine, causing a crash or even an exploit of the Ugarit process itself (thereby gaining the powers of a process inspector, as documented below). We can but hope that the decompression engine is robust. Exploits of the decryption engine, or other parts of Ugarit, are less likely due to the nature of the operations performed upon them.

However, if a block is modified, then when Ugarit reads it back, the hash will no longer match the hash Ugarit requested, which will be detected and an error reported. The hash is checked after decryption and decompression, so this check does not protect us against exploits of the decompression engine.

This protection is only afforded when the hash Ugarit asks for is not tampered with. Most hashes are obtained from within other blocks, which are therefore safe unless that block has been tampered with; the nature of the hash tree conveys the trust in the hashes up to the root. The root hashes are stored in the vault as "tags", which an vault modifier could alter at will. Therefore, the tags cannot be trusted if somebody might modify the vault. This is why Ugarit prints out the snapshot hash and the root directory hash after performing a snapshot, so you can record them securely outside of the vault.

The most likely threat posed by vault modifiers is that they could simply corrupt or delete all of your vault, without needing to know any encryption keys.

Recommendations: Secure your vaults against modifiers, by whatever means possible. If vault modifiers are still a potential threat, write down a log of your root directory hashes from each snapshot, and keep it safe. When extracting your backups, use the ls -ll command in the interface to check the "contents" hash of your snapshots, and check they match the root directory hash you expect.

Process inspectors

These folks can attach debuggers or similar tools to running processes, such as Ugarit itself.

Ugarit backend processes only see encrypted data, so people who can attach to that process gain the powers of vault snoopers and modifiers, and the same conditions apply.

People who can attach to the Ugarit process itself, however, will see the original unencrypted content of your filesystem, and will have full access to the encryption keys and hashing keys stored in your Ugarit configuration. When Ugarit is running with sufficient permissions to restore backups, they will be able to intercept and modify the data as it comes out, and probably gain total write access to your entire filesystem in the process.

Recommendations: Ensure that Ugarit does not run under the same user ID as untrusted software. In many cases it will need to run as root in order to gain unfettered access to read the filesystems it is backing up, or to restore the ownership of files. However, when all the files it backs up are world-readable, it could run as an untrusted user for backups, and where file ownership is trivially reconstructible, it can do restores as a limited user, too.

Attackers in the source filesystem

These folks create files that Ugarit will back up one day. By having write access to your filesystem, they already have some level of power, and standard Unix security practices such as storage quotas should be used to control them. They may be people with logins on your box, or more subtly, people who can cause servers to writes files; somebody who sends an email to your mailserver will probably cause that message to be written to queue files, as will people who can upload files via any means.

Such attackers might use up your available storage by creating large files. This creates a problem in the actual filesystem, but that problem can be fixed by deleting the files. If those files get stored into Ugarit, then they are a part of that snapshot. If you are using a backend that supports deletion, then (when I implement snapshot deletion in the user interface) you could delete that entire snapshot to recover the wasted space, but that is a rather serious operation.

More insidiously, such attackers might attempt to abuse a hash collision in order to fool the vault. If they have a way of creating a file that, for instance, has the same hash as your shadow password file, then Ugarit will think that it already has that file when it attempts to snapshot it, and store a reference to the existing file. If that snapshot is restored, then they will receive a copy of your shadow password file. Similarly, if they can predict a future hash of your shadow password file, and create a shadow password file of their own (perhaps one giving them a root account with a known password) with that hash, they can then wait for the real shadow password file to have that hash. If the system is later restored from that snapshot, then their chosen content will appear in the shadow password file. However, doing this requires a very fundamental break of the hash function being used.

Recommendations: Think carefully about who has write access to your filesystems, directly or indirectly via a network service that stores received data to disk. Enforce quotas where appropriate, and consider not backing up "queue directories" where untrusted content might appear; migrate incoming content that passes acceptance tests to an area that is backed up. If necessary, the queue might be backed up to a non-snapshotting system, such as rsyncing to another server, so that any excessive files that appear in there are removed from the backup in due course, while still affording protection.