Security features for v0.3.0


#1

As part of the “security first” policy, we want to include the following changes for Lotus v0.3.0.

Markup escape

This involves three frameworks, Utils, View and Helpers.

Lotus::Utils::Escape

This is a module that offers markup escaping facilities like Escape.html.

It implements OWASP recommendations about escaping, and it’s based on their ESAPI implementation.
Technically speaking it differentiates between:

  • Content tag sanitization (eg. <div>sanitized content</div>)
  • Attribute tag sanitization (eg. <div title="sanitized content"></div>)
  • URL sanitization via scheme whitelisting (eg. <a href="sanitized url"></a>).

https://github.com/lotus/utils/pull/51

Lotus::Helpers

This is a new framework that will be released contextually with the next version of Lotus.

The first and only feature that it will have for now is HTML generator. The output will be automatically escaped, using the mentioned Utils facilities.

https://github.com/lotus/helpers/pull/7

It will also offer a helper to mixin in views that offers comfortable, and well known shortcuts for markup sanitization. I’m talking about:

  • #escape_html (aliased as #h)
  • #escape_html_attribute (aliased as #ha)
  • #escape_url (aliased as #u)

https://github.com/lotus/helpers/issues/8

Lotus::View

Until now, this framework didn’t escaped output. It demanded to the chosen template engine to do so. For instance, using erubis will do it for free.

The main goal of Lotus::View has always been to concentrate all the presentational logic in views and make the code independent from the current template engine of an application.

Automatic escape

We want to design Lotus::View to do automatic escaping of the output at the level of the view.

At the same time we want to leave the choice of send unescaped output via #raw.

class MyView
  include Lotus::View

  def username
    user.username
  end

  def greet
    raw "<script>alert('hello')</script>"
  end
end

template = Lotus::View::Template.new('path/to/template.erb')
user     = User.new(username: '<script>alert("xss!")</script>')
view     = MyView.new(template, user: user)

view.username
  # => "&lt;script&gt;alert(&quot;xss!&quot;)&lt;&#x2F;script&gt;"

view.greet
  # => "<script>alert('hello')</script>"

Enhance Lotus::Presenter

The proposal above can be useful but it can be verbose too.

Imagine to have the need of print a lot of informations for that given user. It would be unhandy to create concrete methods for all of them.

We want to introduce automatic markup escape for presenters.

class MyView
  include Lotus::View

  def user
    escape(super)
  end
end

template = Lotus::View::Template.new('path/to/template.erb')
user     = User.new({
             username: '<script>alert("xss!")</script>',
             name:     '<script>alert("hack!")</script>'
            })
view     = MyView.new(template, user: user)

u = view.user

u.username
# => "&lt;script&gt;alert(&quot;xss!&quot;)&lt;&#x2F;script&gt;"

u.name
# => "&lt;script&gt;alert(&quot;hack!&quot;)&lt;&#x2F;script&gt;"

Those two are breaking changes, we need to bump a minor release for Lotus::View (v0.4.0) and have an open discussion about those features.

Content-Security-Policy

Content-Security-Policy is a builtin XSS protection that all the modern browsers support. It allows only trusted assets and contents to be loaded and executed.

This is an ultimate protection that can save user’s data in markup escaping is not working as expected.

Because implementing CSP can be really hard at later stages of an application life, it’s better to plan it in advance. Lotus cares about code maintenance.

We want to be the first Ruby web framework to enable it by default.

Starting from Lotus 0.3.0 we want to generate the following setting in application’s configuration.

module Web
  class Application < Lotus::Application
    configure do
      # ...
      content_security_policy "connect-src 'self'; script-src 'self'; ..."
    end
  end
end

If present, that will be the content that the application will send as HTTP header in responses.

X-Frame-Options

Another important HTTP header for web security is X-Frame-Options. It helps to prevent Clickjacking attacks and to avoid web applications to be embedded by untrusted sources. Eg. evil.com cannot include myapp.com via <iframe> tag.

Again, we want to be the first Ruby web framework to enable it by default too.

Similarly, the idea is to generate a setting for it.

module Web
  class Application < Lotus::Application
    configure do
      # ...
      x_frame_options "DENY"
    end
  end
end

HttpOnly cookies

If all the above mechanisms would fail for some reason, browser or Lotus bug, developer mistake, we want to prevent attackers to steal cookies via JavaScript. Eg. alert(document.cookie) will fail.

Starting from Lotus::Controller 0.4.0, all the cookies will be HttpOnly by default.

Read more about this subject.

Conclusion

Those mechanisms will be enabled by default, to help companies to ship secure applications and keep their user’s data safe.

XSS is one of the most common vulnerabilities of the web as of today. Lotus wants to make developers aware of the risks and offer advanced protections for this threat.


#2

awesome job @jodosha :clap::clap::clap::clap::clap:


#3

I think you did an awesome jobs @jodosha.
However, there is one points that confused me, is about how you config security options in a context of application.
Writing like

module Web
  class Application < Lotus::Application
    configure do
      # ...
      content_security_policy "connect-src 'self'; script-src 'self'; ..."
    end
  end
end

Make a generic object like Application to aware of a header config seems to be a little bit complex for users. and the configure block will become longer and longer.
How about embed x-frame-options configure in the rack layer, Content-Security-Policy in the view layer?


#4

XFO: If moved in the Rack layer (where exactly?) how can developers access this setting and change it according to their needs?

CSP: This is an HTTP header, Lotus::View is out of scope. Again, to bury those settings makes hard to customize them. In my personal experience, CSP is changed often at the early stages of an application.


#5

@jodosha will it have more security options? maybe it’s a cool idea (or not) create a security block configuration:

configure do
   security do
      content_security_policy "connect-src 'self'; script-src 'self'; ..."
      x_frame_options "DENY"
   end
end

#6

Probably yes. Instead of a nested block, I’d go for security.content_security_policy, like we do for controller.* and view.* settings.


#7

Borrowing @AlfonsoUceda ideas above, I prefer the approach looks like (i don’t like security very much)

module Web
  class Application < Lotus::Application
    header do
      x_frame_options "DENY"
      content_security_policy "connect-src 'self'; script-src 'self'; ..."
    end
  end
end

P/S: just saw your reply above, so

module Web
  class Application < Lotus::Application
    configure do
      header.config.x_frame_options "DENY"
      header.config.content_security_policy "connect-src 'self'; script-src 'self'; ..."
    end
  end
end

looks better to me


#8

Hi @jodosha, sounds great. Looking forward to have this set of security features inside the framework. Still one question: maybe is miss something but what about CSRF Protection?


#9

Good question.
CSRF protection will be shipped when we will have form builders.
Once Lotus::Helpers will have them, we’ll ship this security mechanism.

We’re trying to build features + security for each release.


#10