File: 002-cve-2018-1000539.patch

package info (click to toggle)
ruby-json-jwt 1.6.2-1%2Bdeb9u1
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 292 kB
  • sloc: ruby: 2,120; makefile: 3
file content (99 lines) | stat: -rw-r--r-- 3,530 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
From 3393f394f271c87bd42ec23c300727b4437d1638 Mon Sep 17 00:00:00 2001
From: Bart de Water <bartdewater@gmail.com>
Date: Mon, 30 Apr 2018 10:57:16 -0400
Subject: [PATCH] Verify the GCM auth tag length

As described in https://github.com/ruby/openssl/issues/63 without this check, only a single byte needs to be supplied to make the authentication pass. This means that an attacker needs at most 256 attempts in order to forge a valid authentication tag.

The JWE spec example prescribes 128 bits (16 bytes) for the tag: https://tools.ietf.org/html/rfc7516#section-3.3
---
 lib/json/jwe.rb       |  2 ++
 spec/json/jwe_spec.rb | 24 ++++++++++++++++++++++++
 2 files changed, 26 insertions(+)

--- a/lib/json/jwe.rb
+++ b/lib/json/jwe.rb
@@ -259,6 +259,8 @@
       cipher.key = encryption_key
       cipher.iv = iv # NOTE: 'iv' has to be set after 'key' for GCM
       if gcm?
+        # https://github.com/ruby/openssl/issues/63
+        raise DecryptionFailed.new('Invalid authentication tag') if authentication_tag.length < 16
         cipher.auth_tag = authentication_tag
         cipher.auth_data = auth_data
       end
--- a/spec/json/jwe_spec.rb
+++ b/spec/json/jwe_spec.rb
@@ -162,6 +162,24 @@
       end
     end
 
+    shared_examples_for :verify_gcm_authentication_tag do
+      let(:jwe_string) do
+        _jwe_ = JSON::JWE.new plain_text
+        _jwe_.alg, _jwe_.enc = alg, enc
+        _jwe_.encrypt! key
+        header, key, iv, cipher_text, auth_tag = _jwe_.to_s.split('.')
+        truncated_auth_tag = Base64.urlsafe_decode64(auth_tag).slice(0..-2)
+        truncated_auth_tag = Base64.urlsafe_encode64(truncated_auth_tag, padding: false)
+        [header, key, iv, cipher_text, truncated_auth_tag].join('.')
+      end
+
+      it do
+        expect do
+          jwe.decrypt! key
+        end.to raise_error JSON::JWE::DecryptionFailed
+      end
+    end
+
     shared_examples_for :unexpected_algorithm_for_decryption do
       it do
         expect do
@@ -186,6 +204,7 @@
         let(:enc) { :A128GCM }
         if gcm_supported?
           it_behaves_like :decryptable
+          it_behaves_like :verify_gcm_authentication_tag
         else
           it_behaves_like :gcm_decryption_unsupported
         end
@@ -195,6 +214,7 @@
         let(:enc) { :A256GCM }
         if gcm_supported?
           it_behaves_like :decryptable
+          it_behaves_like :verify_gcm_authentication_tag
         else
           it_behaves_like :gcm_decryption_unsupported
         end
@@ -219,6 +239,7 @@
         let(:enc) { :A128GCM }
         if gcm_supported?
           it_behaves_like :decryptable
+          it_behaves_like :verify_gcm_authentication_tag
         else
           it_behaves_like :gcm_decryption_unsupported
         end
@@ -228,6 +249,7 @@
         let(:enc) { :A256GCM }
         if gcm_supported?
           it_behaves_like :decryptable
+          it_behaves_like :verify_gcm_authentication_tag
         else
           it_behaves_like :gcm_decryption_unsupported
         end
@@ -254,6 +276,7 @@
         let(:enc) { :A128GCM }
         if gcm_supported?
           it_behaves_like :decryptable
+          it_behaves_like :verify_gcm_authentication_tag
         else
           it_behaves_like :gcm_decryption_unsupported
         end
@@ -263,6 +286,7 @@
         let(:enc) { :A256GCM }
         if gcm_supported?
           it_behaves_like :decryptable
+          it_behaves_like :verify_gcm_authentication_tag
         else
           it_behaves_like :gcm_decryption_unsupported
         end