NFS Backups and Xen Orchestra
I want to confirm a couple things about Xen Orchestra and NFS backups.
- Running Mount from XOA
When I go to Settings -> Remotes and try to add an NFS remote, it looks like Xen Orchestra wants to run
mounton the XOA VM to mount it. That implies that the web server is running as
rootor the web server has the ability to invoke commands as root, because only root can mount filesystems. That seems decidedly suboptimal from a security point of view. If I run xo-web as root and there's an input validation error, then I not only have command injection, but I have commands injected that are running as root.
Imagine someone types
ver=3; echo blah | tee -a /etc/shadow; :or similar as their options on the NFS remote. That potentially executes as root and does something nasty (where
blahis a correctly formatted /etc/shadow entry).
I could potentially create a rule in my
/etc/sudoersfile to allow the unprivileged
wwwuser to invoke
/bin/mountas root with no password, but I'm still not sure how exposed I would be to command injection. The risk is limited to that one command, but it's still sorta there. We'd have to change the mount command that is executed to be
sudo mount, instead of
If I follow the flow, the hypervisor will transmit the VM's data for backup to my XOA VM, who in turn writes it out to the NFS volume. If my XOA instance is not on the same network or host, that's a bad idea, right? I mean: it would be better for the host to do the NFS mount from the hypervisor and write the data out to the NFS share directly, wouldn't it? Even if my XOA VM is on the same host, the data is transmitted into the VM and back out again. Do I understand this correctly?
- Ping @julien-f about this
- That's correct and there's a good reason to that. When we ask XenServer/XCP-ng to export a VM disk, it doesn't push data. It only expose an HTTP handler so we can pull data. Remember that we are doing everything through XAPI and there's 0 SSH calls. So there's no way to ask a host to push data to a NFS host. However, this limitation is solved by using XO proxies, which are available in XOA since last release See https://xen-orchestra.com/docs/proxy.html
I don't believe command injection is possible because
mountis called directly, no shell is used to parse the command line.
@julien-f Yeah, I have just found the
useSudooption in the docs. I swear things change fast enough on xen orchestra that "upgrading" almost doesn't make sense. I rebuild it like every 3-6 months and so much changes that it's almost easier to start over. If I had started over and pretended I didn't know anything, I would have read the documentation and seen the useSudo option. That's not a complaint. Fast development and adding features is awesome.
NodeJS is not my best language. But it looks
_mount.jsuses the execa library to wrap around standard child-process stuff.
I did a little bit of code reading and it looks like, ultimately, execa and child-process-promise end up invoking child_process.spawn(), and it seems like spawn() is just an asynchronous wrapper around
child_process.exec(). This leads me to believe that the input ultimately ends up on a shell command line.
According to the docs I found:
child_process.exec(): spawns a shell and runs a command within that shell, passing the stdout and stderr to a callback function when complete
Now, both execa and the child-process-promise library do a lot of parsing of arguments. I can't tell to what extent that parsing and marshalling of command line arguments actually defeats injection attacks. I've done a lot of code review in my day, and sometimes I miss the line that does the work of defeating injection attacks because it is terse and effective. I might have looked right at it and misunderstood its importance.
Like I said, NodeJS and all the modules that are getting loaded in here to make this happen is difficult for me to follow. It's not my strong suit. Sorry if I'm wasting your time because I can't follow the code flow. It looks to me like it all boils down to exec(), and exec() by definition invokes the shell. But maybe we're protected by one of the argument marshalling functions in the call chain.
shelloption is used, no shell interpreter (Bash,
cmd.exe, etc.) is used, so shell features such as variables substitution (
echo $PATH) are not allowed.
spawnwhich does not do any arguments parsing, those are passed verbatim to the underlying command (probably via a call to
If we would have used the
shelloption, this command would indeed run a shell which would have parsed the command line and therefore be susceptible to injection, but we are not using this
@olivierlambert The proxy page has a pretty decent diagram for what things look like when there is no proxy. But it doesn't have a diagram for what things look like if there IS a proxy. I'm trying to understand it. Does this diagram capture the two situations?
If you're running 2 sites using a single instance of Xen Orchestra, is this what happens?
Indeed, it's on the blog post but not in the doc. It's:
As visible here: https://xen-orchestra.com/blog/backup-proxies/
I'm updating the doc right now.
Doc now updated with 2 pictures here: https://xen-orchestra.com/docs/proxy.html#architecture