Ruby on rails 如何硬化钢轨+;韦布里克+;Ruby 2.2上删除不安全密码的https
更新:首先,我的测试代码没有充分显示ruby 2.4看到了:SSLCiphers选项,而ruby 2.2没有。我对下面的示例代码进行了编辑,以明确这一点。 更新:由于我的问题未能获得社区的任何帮助,我继续前进,两天后找到了解决方案,我已将其包括在下面。 我在Ruby 2.2和Webrick上有一个小的Rails 3应用程序,它可以处理小负载,因此不需要像“真正的”web服务器那样复杂。它已经被修补,以支持安全登录的https连接,但在默认情况下,它接受许多旧的弱密码,这是我想要禁止的。虽然将ruby升级到2.4提供了新的强化选项来实现这一点,但我不能立即切换到较新的ruby。因此,我尝试对ruby 2.2的webrick/ssl.rb进行修补,以添加两个选项:SSLVersion和:SSLCiphers。我只取得了部分成功:虽然:SSLVersion似乎有效,但:SSLCiphers无效 首先,下面的示例显示了Ruby 2.4上的成功强化,基于这里的答案,但也包含了这里的一些建议:除了最初我们过于激进并排除AES128,只是为了显示:SSLCiphers选项有效(因为Ruby 2.4中的openssl版本默认情况下禁用了所有SHA1密码) 接下来,我将:SSLCiphers更改为我想要的实际字符串,因为我实际上对AES128很在行。我只想排除旧版openssl默认不排除的所有旧SHA1密码:Ruby on rails 如何硬化钢轨+;韦布里克+;Ruby 2.2上删除不安全密码的https,ruby-on-rails,ssl,rack,webrick,ruby-2.2,Ruby On Rails,Ssl,Rack,Webrick,Ruby 2.2,更新:首先,我的测试代码没有充分显示ruby 2.4看到了:SSLCiphers选项,而ruby 2.2没有。我对下面的示例代码进行了编辑,以明确这一点。 更新:由于我的问题未能获得社区的任何帮助,我继续前进,两天后找到了解决方案,我已将其包括在下面。 我在Ruby 2.2和Webrick上有一个小的Rails 3应用程序,它可以处理小负载,因此不需要像“真正的”web服务器那样复杂。它已经被修补,以支持安全登录的https连接,但在默认情况下,它接受许多旧的弱密码,这是我想要禁止的。虽然将ru
:SSLCiphers => 'TLSv1.2:!aNULL:!eNULL!SHA',
然后准备我的后端口,在上面显示的Rails::Server补丁之后插入。以下内容直接取自Ruby 2.2的webrick/ssl.rb,但添加了Ruby 2.4中的两个新选项,并通过webrick::GenericServer#setup_ssl_context()传递给Ruby openssl:
现在,虽然sslscan现在表示正在遵守SSLVersion(即不接受TLS 1.0或1.1),但SSLCiphers选项似乎没有任何作用,即SHA密码仍然被接受:
Supported Server Cipher(s):
Preferred TLSv1.2 256 bits DHE-RSA-AES256-GCM-SHA384 DHE 1024 bits
Accepted TLSv1.2 256 bits DHE-RSA-AES256-SHA256 DHE 1024 bits
Accepted TLSv1.2 256 bits DHE-RSA-AES256-SHA DHE 1024 bits
Accepted TLSv1.2 256 bits DHE-RSA-CAMELLIA256-SHA DHE 1024 bits
Accepted TLSv1.2 256 bits AES256-GCM-SHA384
Accepted TLSv1.2 256 bits AES256-SHA256
Accepted TLSv1.2 256 bits AES256-SHA
Accepted TLSv1.2 256 bits CAMELLIA256-SHA
Accepted TLSv1.2 128 bits DHE-RSA-AES128-GCM-SHA256 DHE 1024 bits
Accepted TLSv1.2 128 bits DHE-RSA-AES128-SHA256 DHE 1024 bits
Accepted TLSv1.2 128 bits DHE-RSA-AES128-SHA DHE 1024 bits
Accepted TLSv1.2 128 bits DHE-RSA-SEED-SHA DHE 1024 bits
Accepted TLSv1.2 128 bits DHE-RSA-CAMELLIA128-SHA DHE 1024 bits
Accepted TLSv1.2 128 bits AES128-GCM-SHA256
Accepted TLSv1.2 128 bits AES128-SHA256
Accepted TLSv1.2 128 bits AES128-SHA
Accepted TLSv1.2 128 bits SEED-SHA
Accepted TLSv1.2 128 bits CAMELLIA128-SHA
鉴于我预期:
Supported Server Cipher(s):
Preferred TLSv1.2 256 bits DHE-RSA-AES256-GCM-SHA384 DHE 1024 bits
Accepted TLSv1.2 256 bits DHE-RSA-AES256-SHA256 DHE 1024 bits
Accepted TLSv1.2 256 bits AES256-GCM-SHA384
Accepted TLSv1.2 256 bits AES256-SHA256
Accepted TLSv1.2 128 bits DHE-RSA-AES128-GCM-SHA256 DHE 1024 bits
Accepted TLSv1.2 128 bits DHE-RSA-AES128-SHA256 DHE 1024 bits
Accepted TLSv1.2 128 bits AES128-GCM-SHA256
Accepted TLSv1.2 128 bits AES128-SHA256
事实上,我更改什么并不重要:SSLCiphers为,任何有效或甚至无效的值。显然,仅仅更新ruby是不够的
我的后端口哪里出了问题?还有什么我可以尝试达到同样的结果吗?我似乎非常接近于一个解决方案,在我们的Ruby版本和webrick的约束下工作,这对我来说是很难摆脱的
解决方案:
我插入了debug print语句以查看SSLCiphers值“丢失”的位置。尽管我的测试表明WEBrick方面一切正常,但在OpenSSL类中,似乎在设置SSL侦听器时,传入了错误的密码列表(即默认值而不是覆盖)
在查看OpenSSL API以了解如何获取有关故障的更多信息时,我发现了一种方法,该方法将哈希作为参数,并将任何参数设置为SSLContext的新值。因此,我实验性地替换了我的猴子补丁WEBrick::GenericServer#setup_ssl_上下文来使用它并传递所有要更改的值的散列,而不是替换每个设置的ctx.=config:[:](直接从原始WEBrick代码中提取;即使在Ruby 2.4中,这也没有改变)
我的结果如何?成功!使用更改SSLContext对象的替代方法,我能够使:SSLCiphers覆盖值“stick”
if RUBY_VERSION < '2.4'
require 'webrick/ssl'
module WEBrick
module Config
svrsoft = General[:ServerSoftware]
osslv = ::OpenSSL::OPENSSL_VERSION.split[1]
SSL = {
:ServerSoftware => "#{svrsoft} OpenSSL/#{osslv}",
:SSLEnable => false,
:SSLCertificate => nil,
:SSLPrivateKey => nil,
:SSLClientCA => nil,
:SSLExtraChainCert => nil,
:SSLCACertificateFile => nil,
:SSLCACertificatePath => nil,
:SSLCertificateStore => nil,
:SSLTmpDhCallback => nil,
:SSLVerifyClient => ::OpenSSL::SSL::VERIFY_NONE,
:SSLVerifyDepth => nil,
:SSLVerifyCallback => nil, # custom verification
:SSLTimeout => nil,
:SSLOptions => nil,
:SSLCiphers => nil,
:SSLVersion => nil,
:SSLStartImmediately => true,
# Must specify if you use auto generated certificate.
:SSLCertName => nil,
:SSLCertComment => "Generated by Ruby/OpenSSL"
}
General.update(SSL)
end
class GenericServer
def setup_ssl_context(config) # :nodoc:
unless config[:SSLCertificate]
cn = config[:SSLCertName]
comment = config[:SSLCertComment]
cert, key = Utils::create_self_signed_cert(1024, cn, comment)
config[:SSLCertificate] = cert
config[:SSLPrivateKey] = key
end
ctx = OpenSSL::SSL::SSLContext.new
ctx.set_params({
key: config[:SSLPrivateKey],
cert: config[:SSLCertificate],
client_ca: config[:SSLClientCA],
extra_chain_cert: config[:SSLExtraChainCert],
ca_file: config[:SSLCACertificateFile],
ca_path: config[:SSLCACertificatePath],
cert_store: config[:SSLCertificateStore],
tmp_dh_callback: config[:SSLTmpDhCallback],
verify_mode: config[:SSLVerifyClient],
verify_depth: config[:SSLVerifyDepth],
verify_callback: config[:SSLVerifyCallback],
timeout: config[:SSLTimeout],
options: config[:SSLOptions],
ciphers: config[:SSLCiphers],
ssl_version: config[:SSLVersion],
})
ctx
end
end
end
end
如果RUBY_版本<'2.4'
需要“webrick/ssl”
模块WEBrick
模块配置
svrsoft=通用[:服务器软件]
osslv=::OpenSSL::OpenSSL_VERSION.split[1]
SSL={
:ServerSoftware=>“#{svrsoft}OpenSSL/#{osslv}”,
:SSLEnable=>false,
:SSLCertificate=>nil,
:SSLPrivateKey=>nil,
:SSLClientCA=>nil,
:SSLExtraChainCert=>nil,
:SSLCACertificateFile=>nil,
:SSLCACertificatePath=>nil,
:SSLCertificateStore=>nil,
:SSLTmpDhCallback=>nil,
:SSLVerifyClient=>::OpenSSL::SSL::VERIFY\u NONE,
:SSLVerifyDepth=>nil,
:SSLVerifyCallback=>nil,#自定义验证
:SSLTimeout=>nil,
:SSLOptions=>nil,
:SSLCiphers=>nil,
:SSLVersion=>nil,
:sslstartimely=>true,
#必须指定是否使用自动生成的证书。
:SSLCertName=>nil,
:SSLCertComment=>“由Ruby/OpenSSL生成”
}
一般更新(SSL)
结束
类GenericServer
def setup_ssl_context(config)#:nodoc:
除非配置[:SSLCertificate]
cn=config[:SSLCertName]
comment=config[:SSLCertComment]
证书,key=Utils::创建自签名证书(1024,cn,注释)
配置[:SSLCertificate]=证书
配置[:SSLPrivateKey]=键
结束
ctx=OpenSSL::SSL::SSLContext.new
ctx.set_参数({
key:config[:SSLPrivateKey],
证书:配置[:SSLCertificate],
客户端\u ca:config[:SSLClientCA],
额外链证书:配置[:SSLExtraChainCert],
ca_文件:配置[:SSLCACertificateFile],
ca_路径:配置[:SSLCACertificatePath],
证书存储:配置[:SSLCertificateStore],
tmp_dh_callback:config[:SSLTmpDhCallback],
验证\u模式:配置[:SSLVerifyClient],
验证深度:配置[:SSLVerifyDepth],
验证_回调:config[:SSLVerifyCallback],
超时:配置[:SSLTimeout],
选项:配置[:SSLOptions],
密码:config[:SSLCiphers],
ssl_版本:config[:SSLVersion],
})
ctx
结束
结束
结束
结束
有了这个补丁,sslscan输出与我的exp匹配
script/rails:47: warning: already initialized constant WEBrick::Config::SSL
C:/Ruby226/lib/ruby/2.2.0/webrick/ssl.rb:62: warning: previous definition of SSL was here
Supported Server Cipher(s):
Preferred TLSv1.2 256 bits DHE-RSA-AES256-GCM-SHA384 DHE 1024 bits
Accepted TLSv1.2 256 bits DHE-RSA-AES256-SHA256 DHE 1024 bits
Accepted TLSv1.2 256 bits DHE-RSA-AES256-SHA DHE 1024 bits
Accepted TLSv1.2 256 bits DHE-RSA-CAMELLIA256-SHA DHE 1024 bits
Accepted TLSv1.2 256 bits AES256-GCM-SHA384
Accepted TLSv1.2 256 bits AES256-SHA256
Accepted TLSv1.2 256 bits AES256-SHA
Accepted TLSv1.2 256 bits CAMELLIA256-SHA
Accepted TLSv1.2 128 bits DHE-RSA-AES128-GCM-SHA256 DHE 1024 bits
Accepted TLSv1.2 128 bits DHE-RSA-AES128-SHA256 DHE 1024 bits
Accepted TLSv1.2 128 bits DHE-RSA-AES128-SHA DHE 1024 bits
Accepted TLSv1.2 128 bits DHE-RSA-SEED-SHA DHE 1024 bits
Accepted TLSv1.2 128 bits DHE-RSA-CAMELLIA128-SHA DHE 1024 bits
Accepted TLSv1.2 128 bits AES128-GCM-SHA256
Accepted TLSv1.2 128 bits AES128-SHA256
Accepted TLSv1.2 128 bits AES128-SHA
Accepted TLSv1.2 128 bits SEED-SHA
Accepted TLSv1.2 128 bits CAMELLIA128-SHA
Supported Server Cipher(s):
Preferred TLSv1.2 256 bits DHE-RSA-AES256-GCM-SHA384 DHE 1024 bits
Accepted TLSv1.2 256 bits DHE-RSA-AES256-SHA256 DHE 1024 bits
Accepted TLSv1.2 256 bits AES256-GCM-SHA384
Accepted TLSv1.2 256 bits AES256-SHA256
Accepted TLSv1.2 128 bits DHE-RSA-AES128-GCM-SHA256 DHE 1024 bits
Accepted TLSv1.2 128 bits DHE-RSA-AES128-SHA256 DHE 1024 bits
Accepted TLSv1.2 128 bits AES128-GCM-SHA256
Accepted TLSv1.2 128 bits AES128-SHA256
if RUBY_VERSION < '2.4'
require 'webrick/ssl'
module WEBrick
module Config
svrsoft = General[:ServerSoftware]
osslv = ::OpenSSL::OPENSSL_VERSION.split[1]
SSL = {
:ServerSoftware => "#{svrsoft} OpenSSL/#{osslv}",
:SSLEnable => false,
:SSLCertificate => nil,
:SSLPrivateKey => nil,
:SSLClientCA => nil,
:SSLExtraChainCert => nil,
:SSLCACertificateFile => nil,
:SSLCACertificatePath => nil,
:SSLCertificateStore => nil,
:SSLTmpDhCallback => nil,
:SSLVerifyClient => ::OpenSSL::SSL::VERIFY_NONE,
:SSLVerifyDepth => nil,
:SSLVerifyCallback => nil, # custom verification
:SSLTimeout => nil,
:SSLOptions => nil,
:SSLCiphers => nil,
:SSLVersion => nil,
:SSLStartImmediately => true,
# Must specify if you use auto generated certificate.
:SSLCertName => nil,
:SSLCertComment => "Generated by Ruby/OpenSSL"
}
General.update(SSL)
end
class GenericServer
def setup_ssl_context(config) # :nodoc:
unless config[:SSLCertificate]
cn = config[:SSLCertName]
comment = config[:SSLCertComment]
cert, key = Utils::create_self_signed_cert(1024, cn, comment)
config[:SSLCertificate] = cert
config[:SSLPrivateKey] = key
end
ctx = OpenSSL::SSL::SSLContext.new
ctx.set_params({
key: config[:SSLPrivateKey],
cert: config[:SSLCertificate],
client_ca: config[:SSLClientCA],
extra_chain_cert: config[:SSLExtraChainCert],
ca_file: config[:SSLCACertificateFile],
ca_path: config[:SSLCACertificatePath],
cert_store: config[:SSLCertificateStore],
tmp_dh_callback: config[:SSLTmpDhCallback],
verify_mode: config[:SSLVerifyClient],
verify_depth: config[:SSLVerifyDepth],
verify_callback: config[:SSLVerifyCallback],
timeout: config[:SSLTimeout],
options: config[:SSLOptions],
ciphers: config[:SSLCiphers],
ssl_version: config[:SSLVersion],
})
ctx
end
end
end
end