初学 rails, 写了个 blog,然后上社区搜到了这个 @huacnlee 写的 gem 做为验证码,因为我是做安全的,所有习惯性测试了验证码是否可以被复用,首先 chrome 开 f12,然后评论一条,copy 出数据包如下
curl 'http://www.firebroo.com/categorys/20/articles/11/comments' -H 'Cookie: _blog_session=eTBGSkNhYTlUWmYrSDlEN2k2TEV5NEwvRjhmTUdIQTQ3WUdFQ08vaXFhbnhEdGp6RTJHNjVqVmVFL3haVEtnZ2xBaE51ZUR3cTFIcGY3SWIzd2p0WXIxdG1QQWhBemNIUkJYV3B5SGIySmhERmhqNWpoc2lqdEJTSDJTclBaRG51VXpGaWgwenFDcWIrY2JqWWUrZHpKcG1NcExWbVNxNzBYRUV2M01VL0Jibk15TjVqZXBYRktsbWlnM2M5eDNCbWZrOE5XQzhqaUxDUmttWHNETHovSWg5MmZ4V25reDErUVVuaC9MTkVxZ3YrQlk0aFJUcFZwM0dmcFRkajZFUkRDeVllNVhyN1BtQkxQNXYydCtuQURMQ3Bhc0plMXMwYUNRRVp2eUMwWUZxRW9vcFRDUTNhalMxVFAyZVQ3YjdXM3FQTXoxbU1HWGVBajNEc0NDd2VZdHJlUU96Q0N4QlY0YS9VN0RLL0JodEpJMjF1SnpibjBUMURFK2FXL1V6UTI3bkM3ZFFrOVFnR0ZkY0E4cUpiL2s1SHB2WmpvRHRzUWpFK1gxeUh0eXJ4WStQMUZUYVRpdXlWZ2diMjVOZkZyNUxzdGJjOFJrUmdUZnhlM3grV3BsTjN3M3h5SGNlVzRmMEp6bHl3M0E9LS1WQlpNbzgvNjNNb201OGRYTVdPTHhBPT0%3D--d72e796e819742de283b32395b295ee6503be124' -H 'Origin: http://www.firebroo.com' -H 'Accept-Encoding: gzip, deflate' -H 'Accept-Language: en-US,en;q=0.8,zh-CN;q=0.6,zh;q=0.4' -H 'Upgrade-Insecure-Requests: 1' -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.80 Safari/537.36' -H 'Content-Type: application/x-www-form-urlencoded' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8' -H 'Cache-Control: max-age=0' -H 'Referer: http://www.firebroo.com/categorys/20/articles/11.html' -H 'Connection: keep-alive' --data 'utf8=%E2%9C%93&authenticity_token=SLFcb%2FjeKgBJ2IyZ%2FgG5Itbcbv%2F9dftg8os6r1MZF9Msgk7imr7IcOev8b5Kdz0bOugb8NiQBhhVfH5vX%2F1MuA%3D%3D&comment%5Bcommenter%5D=firebroo&comment%5Bbody%5D=111&_rucaptcha=2d72&commit=%E6%8F%90%E4%BA%A4' --compressed
只要我多次不断执行这条命令,评论就会不断添加。达到绕过验证码实现重放攻击。 然后去 github 看了 verify_rucaptcha?函数,发现验证码设计流程应该是没问题的,无论验证码正确与否,都会被 session.delete 注销。
def verify_rucaptcha?(resource = nil)
rucaptcha_at = session[:_rucaptcha_at].to_i
captcha = (params[:_rucaptcha] || '').downcase.strip
# Captcha chars in Session expire in 2 minutes
valid = false
if (Time.now.to_i - rucaptcha_at) <= RuCaptcha.config.expires_in
valid = captcha.present? && captcha == session.delete(:_rucaptcha)
end
if resource && resource.respond_to?(:errors)
resource.errors.add(:base, t('rucaptcha.invalid')) unless valid
end
end
我打印过出重放请求时候的 session 的_rucaptcha, 发现和首次评论的验证码值一样,所以 session.delete 没有删除成功还是有啥缓存?