An git-annex repository with an autoenable=yes special remote can be used to exfiltrate data from another git-annex repository.
Advisory: cross repository data exfiltration via special remote
For example, suppose that ~/annex on my laptop is a git-annex repository that contains some annexed files whose content I only provide to some people. But I am not trying to hide that I have those files in that repository. So I push the git repository, without the annexed files, to a public server.
All an attacker needs to do is make a git-annex repository that contains an autoenabled special remote of type git:
git-annex initremote foo type=git location=/home/joey/annex autoenable=true
(They will first need to dummy up their own /home/joey/annex repository, with the same uuid as mine; that uuid is discoverable in what I pushed.)
In their repository, they can make some annexed files, with innocuous names, that use the keys of the annexed files I am keeping private. And make the git-annex branch record that those keys are located in the uuid of my repository.
Then they only need to coax me into cloning their repository and running git-annex sync. The foo remote is autoenabled and sync will get my private files from ~/annex. And, if the attacker's repository has preferred content configured, will send them on to origin.
This security hole is not limited to autoenabled git remotes. It could be an autoenabled S3 bucket, if I habitually keep S3 environment variables set. Or it could be an autoenabled rsync special remote with an rsyncurl that points into my server via ssh. Unlike the git special remote, some of those don't need the UUID to match either.
A harder to exploit variant of this security hole is when I have not published my ~/annex git repository. The attacker guesses that I am in possession of a file with a known hash, and guesses where I might be keeping it. They can try many locations with many autoenabled special remotes.
(It's almost possible to use this to exfiltrate arbitrary non-annexed files.
The attacker could make a directory or rsync special remote with
importtree=yes that autoenables. The only reason this doesn't work
is that remote.name.annex-tracking-branch needs to be set in order
to make git-annex sync use it. They could try to social engineer
me into running git-annex import, but that seems considerably harder.
Still, while this seems too hard to be a viable attack, it seems likely
that any fix to the main attack will also close off this one.)
--Joey
[fixed|done]]
The obvious fixes for this are to not autoenable anything, or to somehow prompt the user to verify autoenabled special remotes before use.
I know that autoenabled special remotes are broadly used in the datalad community, and losing them would probably break a great many repository workflows.
Prompting the user is difficult because autoenabling can happen on the first git-annex use, which could be expected to legitimately get files from the autoenabled special remote.
I'm struggling to think of other ways to fix this though.
A way to fix this while keeping autoenable could be to make git-annex refuse to push annexed files to remotes by default after autoenabling a special remote.
The UI for this could look something like:
What should verifyremote --unsafe do? At that point files can have already been gotten from it. Deleting the whole local repository might be a good move. It would need to advise the user about what to do.
Previous comment go me thinking, this security hole may not need an autoenabled special remote at all.
For example, if the attacker knows that I am storing annexed objects in a private S3 bucket, they can make a git-annex repository with a special remote for a S3 bucket that contains files they know I want. When I clone it, I can manually enable that special remote and use it. And then the attacker strikes, by updating the git-annex branch remote.log so that the special remote now points to my own private S3 bucket. Causing
git-annex syncto exfiltrate annex objects from it.This is really a separate security hole, but fixing it comprehensively across special remotes seems to be needed in order to fix the autoenable security hole.
One fix is for enabling a special remote to copy all security relevant parts of the remote config to git config settings, and have the special remote read those git config settings on use. Some special remotes already do that (eg rsync), but most don't, and there's no disciplined way to do it.
It should be possible to fix this without modifying all the special remotes to do that. git-annex could remember that a special remote was enabled with a particular special remote config, and supply that config to it, even after the git-annex branch was updated with a newer config.
To handle legitimate config changes, git-annex could notify the user about a config change and have them verify it before using it.
The attacker could also document that the user ought to
git-annex enableremotethe remote, and so avoid any autoenable specific security guardrails.That suggests that enableremote needs the same kind of security guardrails. That could be the same workflow with
git-annex verifyremoteneeded after enableremote. Or if could be built in to it, and rely on the user reading to review it for safety:The fixes proposed above are incomplete in that an attacker can still learn if I have a given key in given location.
git-annex syncwill get it from the autoenabled special remote, and update location tracking to say it's in my clone of the repository, and pushes the git-annex branch to origin, exposing that information to the attacker.To prevent this, two options:
The pre-push hook would need to be installed before autoenabling a special remote. (If there's an existing pre-push hook that the user has installed that doesn't call git-annex, the autoenabling would need to fail. This would be an uncommon special case, since usually autoenabling happens at first git-annex init, when the repository is young. Also use of pre-push hooks is probably rare.)
Avoiding commiting the journal to the git-annex branch would be easier to implement, but leaves the user with no indication why the git-annex branch is not getting sent to remotes as usual. The pre-push hook can display a useful message.
Exfiltration from an encrypted special remote needs the attacker to know the encryption cipher.
If I have an encrypted special remote, and I opt to publish the git repository, the attacker does have enough information for this attack.
They can reuse the cipher field of the config of my special remote in their special remote. With encryption=shared, that's not encrypted and it obviously works. With encryption=pubkey or encryption=hybrid, it is encrypted, but my gpg key will decrypt it and be able to access files on my encrypted special remote.
If I don't publish my git repository, my encrypted special remotes are safe from this attack.
How to handle upgrades?
The choices seem to be:
git-annex verifyremote.The big problem with #1 is that people have automated systems that are working. If upgrading git-annex requires a manual step to keep them working, and missing that causes existing data flows stop happening, it's entirely possible that it will lead to data loss. This makes me deeply uncomfortable with #1. A fairly low impact security hole should not lead to a high risk of data loss.
And if someone discovered this security hole already and has been exploiting it, then they will have probably already obtained all the annexed objects in the special remote. So #1 feels like locking the door after the cows are out.
If someone learns about this security hole from the advisory and starts trying to exploit it, it will be down to a race between them and when git-annex gets upgraded. But, if a user has just enabled a special remote and then learns about this security hole, they have an obvious thing to check.
So, I think #2 is the best choice.