brunofacca/zen-rails-security-checklist

Additional notes

Closed this issue ยท 17 comments

I would like to add the following remarks:

Please do, that would be great. Except for "Use a Strong Session-Secret" and "Create a new session after logging in (if you don't use a gem) to prevent session fixation attacks." which IMO are already covered by the following checklist items

Use a secret_key_base with over 30 random characters. The rake secret command generates such strong keys. Strengthens cookie encryption, mitigating multiple cookie/session related attacks.

Expire the session at log out and expire old sessions at every successful login. Devise does that by default.

Your suggestions are highly important, especially when building authentication from scratch. The checklist only had a Devise-specific authentication section. I have changed that so your suggestions (and future recommendations on how to implement security measures on other authentication gems) will fit better.

Oh. My fault. I did miss this part.

What's about

Do not commit sensitive data such as ...

Maybe it's a good idea to mention best practices recommended by https://12factor.net/

Furthor more on checking password strength. https://github.com/dropbox/zxcvbn
is a good tool for checking password strength, if you don't do it this way http://gavinmiller.io/2016/a-tale-of-security-gone-wrong/

Maybe the hole zen topic is worth a github page instead of a readme.

Edit: As tool I would also mention rubocop. It's not a security tool, but it can find coding issues like "=" instead of "==" inside if statements. As far as I know.

I like the twelve-factor methodology. What specific practices do you think we should include in the checklist?

About zxcvbn, i believe it's worth mentioning. We already mention devise_zxcvbn but it is Devise-specific.
If you wish, you can include a recommendation to https://github.com/envato/zxcvbn-ruby in the following checklist item, which contains authentication-agnostic recommendations:

The password_strength and StrongPassword gems or a regex validation (code sample) should work with most authentication setups.

Regarding Rubocop, that's a great tool, and it does some important security-related checks. However, before recommending it in the checklist, it would be nice to find out if the same security-related checks performed by Rubocop are not performed by Brakeman. In other words, are there relevant advantages in using both tools together (leaving aside other Rubocop benefits and thinking only about security)? Anyone watching the project has the answer to this question?

About the Zen topic, it certainly is worth a GitHub page. Unfortunately, I have nowhere near the knowledge/wisdom to write it ๐Ÿ˜…

What specific practices do you think we should include in the checklist?

Point II. may help that you use your wanted gem's and a insecure old one. But in my point of view this can be extented. You should carefuly choose your dependencies and keep it to a minium. You have to keep an eye on every dependency, because they may have bugs, maybe only when you use it together with another gem.

Point III. Store config in environment variables. It prefents that you check in secrets into your source code system. dotenv helps you to make this task easier.

In other words, are there relevant advantages in using both tools together (leaving aside other Rubocop benefits and thinking only about security)?

Sadly I don't know. I didn't have a look into this. And more disappointing, I'm out of ruby bussiness for a year now.

Unfortunately, I have nowhere near the knowledge/wisdom to write it

I think a simple page is pretty straigt forward. github pages support jekyll. With jekyll you can use markdown. It's now more then your readme ;)

http://programminghistorian.org/lessons/building-static-sites-with-jekyll-github-pages

I believe that checking dependencies (gem) for vulnerabilities is already covered on:

Point II. may help that you use your wanted gem's and a insecure old one. But in my point of view this can be extented. You should carefuly choose your dependencies and keep it to a minium. You have to keep an eye on every dependency, because they may have bugs, maybe only when you use it together with another gem.

If you are referring to bugs that only manifest when using a specific combination of gems, could you please provide an example?

Point III. Store config in environment variables. It prefents that you check in secrets into your source code system. dotenv helps you to make this task easier.

There is already an item recommending that secrets are stored in environment variables. Maybe we can create two subitems (bullets below that item), one recommending dotenv for the development environment and the other suggesting to use the web dashboard or CLI to set environment variables in Heroku and Amazon EBS for the production environment. What do you think?

Sadly I don't know. I didn't have a look into this. And more disappointing, I'm out of ruby bussiness for a year now.

No problem, but in that case I suggest we postpone the Rubocop recommendation until we find out.

About the Zen topic deserving a GitHub Page, I thought you were referring to the Zen philosophy (as in Zen Buddhism) hahah

I believe that checking dependencies (gem) for vulnerabilities is already covered on:

What do you mean? Brakeman? Brakeman can only check gem's on your local environment or CI/Build server. On your production server another version of a gem your using
from system gems can be installed. So it's important to nail down all gem's and don't rely on system gems. That's what point II of 12factor says.

If you are referring to bugs that only manifest when using a specific combination of gems, could you please provide an example?

There is no real example, only an inderect one. Consider the serialization bug. Instantiating an arbitrary object is not that bad. The bad thing happened as they found an class which does bad things at creation time with carefully choosen instance variable settings. In this particular example
serialisation was from activesupport and the bad class was found within ruby core. But consider if this bad class has been in a second gem this bug has only been exploidable because you used a particular combination of gems.

and the other suggesting to use the web dashboard or CLI to set environment variables in Heroku and Amazon EBS for the production environment

In my point of view it's to specific. There are other hosters too. You have to know your hosting environment. You can program a secure application but you can destroy all the security when you deploy it on an unsafe environment. I thinks it's important to know your target environment.

What do you mean? Brakeman? Brakeman can only check gem's on your local environment or CI/Build server. On your production server another version of a gem your using
from system gems can be installed. So it's important to nail down all gem's and don't rely on system gems. That's what point II of 12factor says.

Sorry, I have quoted the wrong text in my previous comment. I meant to say that checking dependencies (gems) for vulnerabilities is already covered on the following item:

  • Watch out for security vulnerabilities in your gems. Run bundler-audit frequently or use a service like Snyk, Gemnasium (both free for open-source development) or Appcanary.

But like you said, if we perform the check in the development environment and use different gem versions in the production environment, it will do us no good. What exactly do you suggest to mitigate this? We could recommend developers to check Gemfile.lock into version control.

There is no real example, only an inderect one. Consider the serialization bug. Instantiating an arbitrary object is not that bad. The bad thing happened as they found an class which does bad things at creation time with carefully choosen instance variable settings. In this particular example
serialisation was from activesupport and the bad class was found within ruby core. But consider if this bad class has been in a second gem this bug has only been exploidable because you used a particular combination of gems.

I understand, but I can't think of an effective way to mitigate this. I believe that "keeping dependencies to a minimum" has its pros and cons. Using too many gems may generate performance issues, security vulnerabilities and so on. However, one of the great things about Ruby and Rails is that we have gems for mostly anything. IMO it makes development faster and more satisfactory, as we don't have to continually "reinvent the wheel" (write boilerplate code).

In my point of view it's to specific. There are other hosters too. You have to know your hosting environment. You can program a secure application but you can destroy all the security when you deploy it on an unsafe environment. I thinks it's important to know your target environment.

Yes, there are a lot of other hosting environments and developers should get to know the chosen environment very well before deploying an application. However, IMO PaaS like Heroku and Amazon EB are amongst the most popular, and their popularity will probably keep increasing in the near future. Hence, it may be useful to provide specific advice for these platforms. That does not mean we can't also provide generic (platform-agnostic) recommendations. That is the same approach used in the "Authentication" section of the checklist: we make general (authentication-agnostic) recommendations but also provide specific instructions on how to implement them on Devise, as that is the most popular authentication gem.

What exactly do you suggest to mitigate this? We could recommend developers to check Gemfile.lock into version control.

I would stick with the suggestion from 12factor. "Define all dependencies completely and exactly"
This also requires checking in Gemfile.lock

IMO it makes development faster and more satisfactory, as we don't have to continually "reinvent the wheel"

It's difficult.

With every gem you include you'r extenting your trust. You do not only trust this specific gem, you also trust all gem's depending on this gem. This trust starts by "is the code secure?" and goes to "Does the author secure its keys for github?", "Does the author keep its rubygems password save?" , "Does the author review PR's thoroughly, or can a malicious persons inject bad code via a PR? " and so on.

Furthor more if you include a gem its also like you own it. It's possible that no one will port the gem to the next ruby or Rails version. In this case you have to maintain the gem. Maybe it's so deeply integrated into your code that you can't switch to the next Rails or ruby version. If your are unable to maintain the gem and your out of luck, you have to stick with an insecure Rails or ruby version just because a gem is incompatible with a new version of ruby or Rails.

In my point of view it's better to copy some line of codes from a small gem or skip a feature where you need a larger gem.

If you realy need a gem, look at the issue lists. Does sombody care about the issues? When was the lattest release? Is it a one man show? ... and so on. When you include a gem look for ways with your design to make it easy to replace it.

I would stick with the suggestion from 12factor. "Define all dependencies completely and exactly"
This also requires checking in Gemfile.lock

That's good. I suggest translating "Define all dependencies completely and exactly" into an actionable list of recommendations (checklist items), including checking in Gemfile.lock.

About the trade-offs between using gems or writing our own code, I agree with everything you said. It's a very delicate balance between security and long-term maintainability vs. time and cost of development.

Such design decisions may also depend on whether the application is a personal or open-source project or we are getting paid to deliver the project within a tight deadline (e.g., for our employer or customer). Businesspersons may be more concerned about the bottom-line (minimize development time/cost, get the application up and running quickly) than security or long-term maintainability.

There are a lot of factors to consider, such as:

  • What is the required level of security for the application? (think online banking platform vs. an application which only stores public-domain data).
  • Can our team of developers effectively replicate the behavior of a large and complex gem? Will the resulting code be safer and easier to maintain? In some cases, it may be easier to take on the gem maintenance if it's eventually abandoned by the current maintainers.
  • Is it worth the time/cost? Usually, it is the client who will decide that, and we may not necessarily agree.

In conclusion, you make some excellent points. I believe the next step might be to translate our discussion into succinct and actionable checklist items.

It's a very delicate balance between security and long-term maintainability vs. time and cost of development.
...
There are a lot of factors to consider

Yes, indeed. I would like to add.

  • What will happen when some one hacks the site you did create?
  • Will your server became a drone?
  • Will illegal data be stored on your server?
  • Will customers be infected with a virus?
  • Will customers and visotors loose important data?
  • Will you have to pay some ransom?
  • What will happen with the reputation of your client?
  • What will happen with your reputation as a developer?

I think it's like beeing a truck driver knowing that your brakes need a repair, or bad things will happen. Will you follow the orders of your manager? In one way or another your responsible for the code you develop. Also you should follow the boy scout rule "Always leave the campground cleaner than you found it" or "Try and leave this world a little better than you found it."

In short you should always do a little risk analysis. You'r customers and managers seldom know the risks they are taking. Also you have to make sure they understand that software and servers need maintenance. There are always updates which have to be integrated.

I believe the next step might be to translate our discussion into succinct and actionable checklist items.

Oh, yes ๐Ÿ‘

I will be away for one week. Will let you know as soon as I get back. If you wish, feel free to create your suggestions for checklist items in the meantime. Have a nice week.

I'm back.

Although I understand your truck driver analogy, in many scenarios design decisions are out of our hands and it may be necessary to convince the client/project manager that a bit of extra development time spent in security is a worthy investment. Maybe we should add a section in the checklist about raising security consciousness in the product owner (client or project manager) and include your list of potential consequences of being hacked.

I appreciate your contribution. This discussion will certainly result in many new and important checklist items. Looking forward to your PRs :)

It's off topic, but whats about turning this project into a github page? It would be easier to edit single pages instead of one readme.

I understand it would be easier to edit, but I think it may loose the "quick reference/checklist" feel. For instance, a developer can fork the repo and go through the entire checklist at once, marking the items that are already implemented in his application.

I don't know if security can be covered by a quick reference or checklist. In my point of view it gives the impression "make a check behind every box and your done & secure".

You have constantly to keep in mind all the points in this readme, understand what it means and heed the advices during your development process and reviews. For instance "validate user input", you have to do this with every new parameter you accept from the client. You can't do it only once. Other points are also on going tasks. Security is nothing you can implement later. It has to be part of your day to day development process.

All the hints in this readme are a starting point and you have to lookup details when you hit a case named in this readme.

Furthor more you have to keep track of new developments and vulnerabilities.

I absolutely agree with everything you said. However, this document is not meant to provide detailed explanations (to teach how each vulnerability works). It is intended to be a checklist, to help prevent developers from overlooking or forgetting to implement important security measures. In my understanding, a "quick reference" is not the same as a "quick fix". We may eventually convert it into a GitHub Page, but I'd like the entire checklist to remain on a single page.

We could create separate pages to provide further details about each vulnerability, while still keeping the checklist on a single page (e.g., each checklist item could link to a separate page about the vulnerability). However, I believe there are existing resources that already cover that, such as the Ruby on Rails Security Guide and chapter 15 of The Rails 4 Way by Obie Fernandez. I'm not sure we can do better than that, and I don't have enough free time to write such large texts.

Closing due to inactivity. Feel free to reopen if you want to contribute.