Closed dereks closed 6 years ago
This is a duplicate of #3032 and #3227. You already found #3267 which will fix the problem.
@emptynick
Thank you for your quick response.
With respect, I believe you are incorrect. This is a separate issue from the bugs you listed.
Both of those appear to be fixed by #3267, as you describe.
This bug report is new and is about the fact that any php artisan command can be run. This is a less severe version of #3032, as it restricts the user to php artisan commands only. But that is still dangerous, as some of those commands can be destructive and they are not all presented as options in the GUI (such as php artisan voyager:admin).
In short, the feature presents itself as allowing the user to run only certain php artisan commands. But in truth it allows an attacker to run any and all php artisan commands. The code should verify the command is one that is okay to run -- or else make it clear that the user can run any and all php artisan commands.
First the code blindly grabs the php artisan command name from the attacker's post:
$command = escapeshellcmd($request->command);
Then the code runs it, regardless of what it says:
$process = new Process('cd '.$path.' && php artisan ' . $command . $args);
Again, the user is limited to just php artisan commands (and not arbitrary shell commands), but that is still unsafe.
If this is intended behaviour, then I don't think it should show a GUI listing just a specific subset of commands. I assumed that only these particular artisan commands could be run, and I had to check the source code to see what it actually did...
I've been thinking through this feature today.
There are many php artisan commands that require filesystem write permissions, e.g. some to create .php files, and some to edit the .env file. These are things a public webserver (e.g. Apache) process should never be able to do, due to the inherent risk. It's a known attack vector with a proven history.
But for developers running a local server with php artisan serve, the webserver will be running under their own UID. That is very convenient for development because the same user can own and edit the .php source code files, including ones generated by php artisan commands, and easily work with it using git. For this, the one-click access to stub creators (like php artisan make:...) is very convenient. (The same is true for users of Laravel Homestead or Valet.)
However, there are some php artisan commands which should clearly be part of the admin panel on a Production webserver. Putting the application into (or out of) maintenance mode, flushing cache, and retrying queue jobs are all examples of things that should be an easy button click on the admin panel. These do not (?) need filesystem access beyond the ones installed for Laravel, and are things one would want to do on a production server.
So what if the php artisan commands are put into two groups:
The "Production" group. If you have Voyager admin privs, you can run these. These are commands an admin might need to run on a Production server. None of these commands require filesystem write access by the webserver (but they might modify the database using the DB_PASSWORD in .env, or modify Laravel's files under ./bootstrap/cache and ./storage).
The rest of the commands. These are suitable for development only, and might touch the filesystem. For these, we assume a development environment where the webserver runs under the UID of the developer.
As for user interface, I think the second group should be disabled (made grey) unless APP_DEBUG=true in the .env file. This way the commands are all still visible in Voyager (with the help text), even though the admin may need to log in remotely via SSH to execute them. This will prevent developers from trying to tell admins to click buttons that don't exist if an emergency comes up. Maybe there could be a button to copy the command to clipboard for easy paste into a shell terminal.
As a first draft, here are the php artisan commands I think should be in the Production group.
Laravel Framework 5.6.28
Usage:
command [options] [arguments]
...
Available commands:
down Put the application into maintenance mode
env Display the current framework environment
up Bring the application out of maintenance mode
migrate Run the database migrations
list Lists commands
help Displays help for a command
auth
auth:clear-resets Flush expired password reset tokens
cache
cache:clear Flush the application cache
cache:forget Remove an item from the cache
config
config:clear Remove the configuration cache file
config:cache Create a cache file for faster configuration loading
migrate
migrate:fresh Drop all tables and re-run all migrations
migrate:install Create the migration repository
migrate:refresh Reset and re-run all migrations
migrate:reset Rollback all database migrations
migrate:rollback Rollback the last database migration
migrate:status Show the status of each migration
queue
queue:failed List all of the failed queue jobs
queue:failed-table Create a migration for the failed queue jobs database table
queue:flush Flush all of the failed queue jobs
queue:forget Delete a failed queue job
queue:listen Listen to a given queue
queue:restart Restart queue worker daemons after their current job
queue:retry Retry a failed queue job
queue:table Create a migration for the queue jobs database table
queue:work Start processing jobs on the queue as a daemon
route
route:cache Create a route cache file for faster route registration
route:clear Remove the route cache file
route:list List all registered routes
schedule
schedule:run Run the scheduled commands
"any artisan command" is a subset of "any shell command". I don't see how this isn't a duplicate of #3032.
I would be open to a pull request where you can list which artisans are allowed in config.
As mentioned in one of your other issues. If you want to restrict access to commands, you can restrict write access to the filesystem by that user. The command will simply fail. Security is ALL of our responsibility, not just that of the package you're using.
This issue has been automatically locked since there has not been any recent activity after it was closed. If you have further questions please ask in our Slack group.
Version information
Description
Any artisan command can be run by the compass user (not just the ones listed in the compass GUI).
Steps To Reproduce
Under /admin/compass > commands.
The php artisan "command" string is pulled verbatim out of the POST request. This means a user can run ANY php artisan command, not just the ones listed in the GUI. All they need to do is hand-craft the POST request. For example, a user can run the "voyager:admin" command even though it is not listed in the GUI.
Expected behavior
To fix this, the code must vet the input data, to make sure the user-requested command is in the list of allowed "php artisan ..." commands. (NEVER trust user submitted data -- code like it is always an attack!)
Alternatively, the GUI must make is absolutely clear that this tool allows you to run any / every php artisan command, and give a box at the top that lets you type in whatever "php artisan ..." you want to run, including "voyager:admin" or anything else. That way there is no false sense of security.
Additional context
Bug #3267