Improper Input Validation in filebrowser/filebrowser

Valid

Reported on

Oct 1st 2021


Description

File Browser is a web-interface that allows you to manage and navigate through your files in a web browser.

One of its features is to allow a user to run specific shell commands in the server, these commands are specified by users with administrator privileges, with an allow list.

This feature is implemented on the frontend side with a web shell using web sockets and the enforcement of the allow list is made on the backend, by spliting the user input by spaces, to obtain the commands and arguments, and then checking the command (first substring) against the list of allowed commands.

The allowed commands are interpreted as a regex and matched against our first substring. This feature is not clearly stated in the documentation. Therefore, if a user follow your example (A space separated list with the available commands for this user. Example: git svn hg.), an attacker that sends something like aaaaagit, would pass the regex check, because it has the substring git.

After these checks, the original user input is splitted again inside the function runner.ParseCommand by calling the function caddy.SplitCommandAndArgs(Source). This last function uses a more complex way to divide commands and args, that considers in addition to spaces, more characters like tabsSource and a state machine that ignores comments. Finally, the parsed command is passed to exec.Command.

These two facts allow an attacker to have arbitrary command injection, if he has an account with the permission to run a specific command.

A payload to explore this vulnerability would be a command that uses tabs instead of spaces and has the allowed command inside a comment. This would pass the security checks, because in the first split, with strings.Split, the command is interpreted as a command without args that matches the regex, and then the caddy.SplitCommandAndArgs correctly parses the user input, identifying commands and arguments, and ignores the comment.

Proof of Concept

This PoC assumes that you have an user account that can only run the git command.

  1. Login with the user account
  2. Click on toggle shell
  3. Write the following command: whoami #git

Note that between the whoami and #git, there is a tab character and not a space.

Impact

A user can run unintended commands in the machine hosting the web server with the permissions of the web application. This can compromise the server and the users' files.

Mitigation

Instead of splitting the user input with strings.Split, use the function caddy.SplitCommandAndArgs to enforce that we are checking the allow list against the command that will be used in the exec.Command. And in addition to that, also evaluate whether interpreting the command as a regex is really necessary and, if yes, inform the user properly.

We have contacted a member of the filebrowser team and are waiting to hear back 2 months ago
We have contacted a member of the filebrowser team and are waiting to hear back 2 months ago
Oleg Lobanov validated this vulnerability a month ago
André Cirne has been awarded the disclosure bounty
The fix bounty is now up for grabs
Oleg Lobanov confirmed that a fix has been merged on 74b7cd a month ago
The fix bounty has been dropped
commands.go#L62 has been validated