-
-
Notifications
You must be signed in to change notification settings - Fork 61
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Mitigate remote code execution attack vector #13
Comments
Ok taking a quick look at the code I see where the problem is: https://github.com/shakacode/cypress-on-rails/blob/master/lib/cypress_dev/command_executor.rb#L9 class CommandExecutor
def self.load(file,command_options = nil)
load_cypress_helper
file_data = File.read(file)
eval file_data
rescue => e
logger.error("fail to execute #{file}: #{e.message}")
logger.error(e.backtrace.join("\n"))
raise e
end If I am reading this right, this allows for any file on the machine to be used to execute ruby code. Adding a restrictions here to only allow loading files from As an attack, what I would do otherwise, would be to figure out where the users browser saves files on the system and make sure it caches my own malicious file and get this gem to try to execute this code. If I cannot do that, it will make the system much more secure. |
Looking at it even further and discussing with colleagues really quickly. Cypress.Commands.add('appCommands', function (body) {
cy.request({
method: 'POST',
url: "/__cypress__/command",
body: JSON.stringify(body),
log: true,
failOnStatusCode: true
})
}); This here means that if you have your CORS on rails enabled to be say |
Just to add some background on the notice. Kernel.eval(command_options) unless command_options.nil? and cypress function Cypress.Commands.add('appEval', function (code) {
cy.app('eval', code)
}); This allows you to write code like this, which can be useful for once of things: cy.appEval('UserService.disable_callbacks') which can easily be abused if someone can access your server. Doing eval's like this was supported in the first versions of cypress-on-rails, so i wanted to continue supporting it even though I deleted the file and function for all projects I work on. |
Limiting files to only be loaded from the configured |
We could also look at doing something like a api token that we can be generated on install and is added to cypress.env.json which cypress can access and is easy enough for the gem to read server side to confirm the token on any request. |
@grantspeelman thanks for the quick and thoughtful response and building the gem :).
Eliminating the need to do eval would really simplify things. There are other features of cypress-on-rails that can be used to accomplish the same thing like scenarios and helpers. We can deprecate it more slowly if you would like and turn it off by default on new installs. We can even allow the users to opt-in to using this feature at their own risk. Simply by leaving a comment in the code in config like: CypressDev.configure do |config|
# WARNING!!: cypress-on-rails can execute arbitrary ruby code if the code eval options is enabled. Please use with extra caution if starting your local server on 0.0.0.0, running the gem on a hosted server and with your CORS setup. For more details see: https://github.com/shakacode/cypress-on-rails/issues/13
# config.enable_code_eval
end A few years ago I had to secure a code eval for arbitrary business rules that code be added to an app. Think spreadsheet style, you add rules that effected your models. To accomplish that I used Distributed Ruby (drb). I started another ruby process with very restricted access (different user) to do the eval. I then sent the string to be evaluated to that less privileged process. It was a lot of work. Took like 6 weeks to get it all dialled in. Another idea is taking a look at other gems that have this problem. The top one would be Rails Web Console. They have a special permission for IPs that are used by the web console. class Application < Rails::Application
config.web_console.permissions = '192.168.0.100'
end https://github.com/rails/web-console#configweb_consolepermissions We can adopt the same idea for both CORS and IP. Looking at it a web console evaluator a little deeper it uses a unique id for every repel request: https://github.com/rails/web-console/blob/master/lib/web_console/session.rb#L45. That's to protect against reply attacks. It also means the path to execute the request changes everytime making it harder to guess it.
This would help a lot. We should also link from the warning to in the readme to this discussion here to let other contribute to it more easily. ====== My biggest question remains, can we drop the |
@grantspeelman can you add a license to the project? #12 Pretty please? :) I would like to try and use this gem, fork it and try spiking on some of the things we talked about above. I can't do that until we have a valid OSS license. Added PR #14 to do just that |
@yagudaev If you want a submit a pull request to tighten up the security, we'll get it reviewed ASAP. @grantspeelman and I feel that the gem should not be installed such that it's never used on production, like: |
I just read this issue to get caught up, but it's getting a little stale and I'm not sure where things stand. Is this still in consideration? I happily deleted Big thanks to everyone for working hard and caring! ❤️ |
The eval is required because the approach is to have files (in Something like: CypressOnRails.configure do |c|
c.execute_commands = lambda do |args|
case args.first
when "appFactory"
# load file, run method, whatever
end
end
end |
It would be really nice if we could limit the remote code execution attack when binding on 0.0.0.0.
This was a huge turn off to see this:
In the README, so much so that I opted to not use this gem and implemented some of the functionality myself in our app. But looking at this gem again, I like a lot of the things you have built and would love to help think about this more.
I'm especially cautious after seeing this article popup on hacker news https://news.ycombinator.com/item?id=20028108 the other day.
Combining those two things: remote code execution and accessing localhost:3000 from another website would make a killer way to deliver viruses and other malicious code.
Anyway, love to hear more details where that is in the code and brainstorm ideas how to get around the need for remote code execution. It should only allow execution of specific helper code and factories from cypress. Also maybe we need to fail or let the user set a flag to even be able to use this when binding on 0.0.0.0
The text was updated successfully, but these errors were encountered: