Rails Rails 把 Cookie 加密之后为什么还要加一个 Signature?

lmorenbit · 2014年06月11日 · 最后由 y0unge 回复于 2023年11月01日 · 4835 次阅读

本来就用 aes-256-cbc 加密然后用 Base64 编码,为什么还要加上个 Signature? 谁能解释一下不?

服务器根据签名来判断 cookie 中的内容是否被伪造

http://mednoter.com/rails-session-2.html

解决的是不同的问题,加密是将内容变成密文;签名是防篡改

@xiaoronglv @sunday35034 谢谢,文章很赞

这里面的 salt 是随机的,即使有 cookie,有 secret_key_base,我也想不出还有什么办法可以解出来。签名是防篡改,但是如果改了之后 cookie 完全没用,为什么要防呢?

# This can be used in situations similar to the <tt>MessageVerifier</tt>, but
# where you don't want users to be able to determine the value of the payload.
#
#   salt  = SecureRandom.random_bytes(64)
#   key   = ActiveSupport::KeyGenerator.new('password').generate_key(salt) # => "\x89\xE0\x156\xAC..."
#   crypt = ActiveSupport::MessageEncryptor.new(key)                       # => #<ActiveSupport::MessageEncryptor ...>
#   encrypted_data = crypt.encrypt_and_sign('my secret data')              # => "NlFBTTMwOUV5UlA1QlNEN2xkY2d6eThYWWh..."
#   crypt.decrypt_and_verify(encrypted_data)                               # => "my secret data"

签名应该可以验证 cookie 完整性

文章里有一段不是有解释嘛

正文只是简单的编码,并未加密的。如果用户(userid = 13134)篡改了正文(userid = 2),就有访问其他用户信息的风险。
为了防止cookie被篡改,每一个session字符串的尾巴上都带着一个服务器生成的digest。
若用户的content与digest不匹配,服务器就知道这个cookie是伪造的。

#5 楼 @sunday35034 是这样的,Rails 4.1 本身已经对 cookie 加密了(而且有 salt)不是只用 Base64 编码

@xiaoronglv 请问你的 Rails 版本多少?或者文中的正文是怎么得到的?

我从 cookie 里拿到的 session 是

Q3NpYk8veW15aXQ1dWgxZGhldCtPU3ZYRTh2SWxacnlGcExWYTJtUXFvRkI3QzZodVl1MW5ZY2VSalI2OVZiSEdOSUcyYXQ4NDNQSGt3djByd0NxZWtZVTA2eUZpc090blJwNE1td0ZiNnMvdzQ3OTRUczd1Q1M5dG5LdlZvbjVrWUlScEtwNEdqd2xJaCt1RGJKa3pCK3FEak0wYXFJS21HTmtiYXdFR3R6V0NhdERZU0dFSlE0ejhqMDN3TVM5bGRhQzdjU3lwb1NseXVGMXJUK1pJc0pKMkI3a0ZiTkYwbW9oMjZndDY2WVlVTGhMa1RiSkNQMEduY1pLYytBZWMwZmFjRDFRU0lXTWZTMnkzdWVMUThoOHFyL3B5OFcyaFJnRytOOVhKZTRoQ1Y4MVgvSjJ6NEJCVWF2bkZkT3otLWdkT3VnaUpnKytjQWlkYUswL123456PQ==--63f0c6963b5adfe7b947d8ef750ddc284650860c

Base64 解码后

CsibO/ymyit5uh1dhet+OSvXE8vIlZryFpLVa2mQqoFB7C6huYu1nYceRjR69VbHGNIG2at843PHkwv0rwCqekYU06yFisOtnRp4MmwFb6s/w4794Ts7uCS9tnKvVon5kYIRpKp4GjwlIh+uDbJkzB+qDjM0aqIKmGNkbawEGtzWCatDYSGEJQ4z8j03wMS9ldaC7cSypoSlyuF1rT+ZIsJJ2B7kFbNF0moh26gt66YYULhLkTbJCP0GncZKc+Aec0facD1QSIWMfS2y3ueLQ8h8qr/py8W2hRgG+N9XJe4hCV81X/J2z4BBUavnFdOz--gdOugiJg++cAidaK012345==

另外 salt 是怎么保存的?

不要用上面的 Cookie 直接解码,我改过几个字符

个人觉得这个事情不用太深究,因为安全这个毕竟是一个相对的事情,每个环节都可能出现安全问题,你不能先建立“加了密就是绝对安全”这个假命题的基础上讨论这个问题。假如别人通过渠道拿到了你的 salt,也知道你的加密算法,但是不知道你的签名算法,这时候签名就有用了。

反过来,既然 Rails 4.1 都给 cookies 加密了,为什么 ruby-china 还要用 ssl 呢?

不过还是很欣赏 LZ 打破砂锅问到底的钻研精神

#7 楼 @sunday35034 解决的是不同问题

cookie 加密并不能解决登录过程中用户名和密码被劫持的问题

#8 楼 @kingwkb 对,密文一样可以被劫持。照样能冒充你

@sunday35034 你说得对

Cookie 的加密方法: http://dev.housetrip.com/2014/01/14/session-store-and-security/

我上面提到的 salt,大家都是一样的(如果你没改过): "encrypted cookie",但是 rails 还会进一步编码之后才用。具体看文章

这个代码我分析过,当前的 cookie 加密方式用的是 aes cbc,如果不加签名对于一般人也伪造不了,因为 sk 不可知。但是,这个加密算法在这里使用是存在的漏洞,具体可以搜索 padding oracle,在不知道 key 的情况下,可以还原出明文,且可以伪造出一个合法的 cookie。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号