summaryrefslogtreecommitdiffstats
path: root/meta/recipes-devtools/ruby/ruby/CVE-2021-33621.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-devtools/ruby/ruby/CVE-2021-33621.patch')
-rw-r--r--meta/recipes-devtools/ruby/ruby/CVE-2021-33621.patch139
1 files changed, 139 insertions, 0 deletions
diff --git a/meta/recipes-devtools/ruby/ruby/CVE-2021-33621.patch b/meta/recipes-devtools/ruby/ruby/CVE-2021-33621.patch
new file mode 100644
index 0000000000..cc2f9853db
--- /dev/null
+++ b/meta/recipes-devtools/ruby/ruby/CVE-2021-33621.patch
@@ -0,0 +1,139 @@
1From 64c5045c0a6b84fdb938a8465a0890e5f7162708 Mon Sep 17 00:00:00 2001
2From: Yusuke Endoh <mame@ruby-lang.org>
3Date: Tue, 22 Nov 2022 10:49:27 +0900
4Subject: [PATCH] Prevent CRLF injection
5
6Throw a RuntimeError if the HTTP response header contains CR or LF to
7prevent HTTP response splitting.
8
9https://hackerone.com/reports/1204695
10
11Upstream-Status: Backport [https://github.com/ruby/cgi/commit/64c5045c0a6b84fdb938a8465a0890e5f7162708]
12CVE: CVE-2021-33621
13Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
14---
15 lib/cgi/core.rb | 45 +++++++++++++++++++++++--------------
16 test/cgi/test_cgi_header.rb | 8 +++++++
17 2 files changed, 36 insertions(+), 17 deletions(-)
18
19diff --git a/lib/cgi/core.rb b/lib/cgi/core.rb
20index bec76e0..62e6068 100644
21--- a/lib/cgi/core.rb
22+++ b/lib/cgi/core.rb
23@@ -188,17 +188,28 @@ class CGI
24 # Using #header with the HTML5 tag maker will create a <header> element.
25 alias :header :http_header
26
27+ def _no_crlf_check(str)
28+ if str
29+ str = str.to_s
30+ raise "A HTTP status or header field must not include CR and LF" if str =~ /[\r\n]/
31+ str
32+ else
33+ nil
34+ end
35+ end
36+ private :_no_crlf_check
37+
38 def _header_for_string(content_type) #:nodoc:
39 buf = ''.dup
40 if nph?()
41- buf << "#{$CGI_ENV['SERVER_PROTOCOL'] || 'HTTP/1.0'} 200 OK#{EOL}"
42+ buf << "#{_no_crlf_check($CGI_ENV['SERVER_PROTOCOL']) || 'HTTP/1.0'} 200 OK#{EOL}"
43 buf << "Date: #{CGI.rfc1123_date(Time.now)}#{EOL}"
44- buf << "Server: #{$CGI_ENV['SERVER_SOFTWARE']}#{EOL}"
45+ buf << "Server: #{_no_crlf_check($CGI_ENV['SERVER_SOFTWARE'])}#{EOL}"
46 buf << "Connection: close#{EOL}"
47 end
48- buf << "Content-Type: #{content_type}#{EOL}"
49+ buf << "Content-Type: #{_no_crlf_check(content_type)}#{EOL}"
50 if @output_cookies
51- @output_cookies.each {|cookie| buf << "Set-Cookie: #{cookie}#{EOL}" }
52+ @output_cookies.each {|cookie| buf << "Set-Cookie: #{_no_crlf_check(cookie)}#{EOL}" }
53 end
54 return buf
55 end # _header_for_string
56@@ -213,9 +224,9 @@ class CGI
57 ## NPH
58 options.delete('nph') if defined?(MOD_RUBY)
59 if options.delete('nph') || nph?()
60- protocol = $CGI_ENV['SERVER_PROTOCOL'] || 'HTTP/1.0'
61+ protocol = _no_crlf_check($CGI_ENV['SERVER_PROTOCOL']) || 'HTTP/1.0'
62 status = options.delete('status')
63- status = HTTP_STATUS[status] || status || '200 OK'
64+ status = HTTP_STATUS[status] || _no_crlf_check(status) || '200 OK'
65 buf << "#{protocol} #{status}#{EOL}"
66 buf << "Date: #{CGI.rfc1123_date(Time.now)}#{EOL}"
67 options['server'] ||= $CGI_ENV['SERVER_SOFTWARE'] || ''
68@@ -223,38 +234,38 @@ class CGI
69 end
70 ## common headers
71 status = options.delete('status')
72- buf << "Status: #{HTTP_STATUS[status] || status}#{EOL}" if status
73+ buf << "Status: #{HTTP_STATUS[status] || _no_crlf_check(status)}#{EOL}" if status
74 server = options.delete('server')
75- buf << "Server: #{server}#{EOL}" if server
76+ buf << "Server: #{_no_crlf_check(server)}#{EOL}" if server
77 connection = options.delete('connection')
78- buf << "Connection: #{connection}#{EOL}" if connection
79+ buf << "Connection: #{_no_crlf_check(connection)}#{EOL}" if connection
80 type = options.delete('type')
81- buf << "Content-Type: #{type}#{EOL}" #if type
82+ buf << "Content-Type: #{_no_crlf_check(type)}#{EOL}" #if type
83 length = options.delete('length')
84- buf << "Content-Length: #{length}#{EOL}" if length
85+ buf << "Content-Length: #{_no_crlf_check(length)}#{EOL}" if length
86 language = options.delete('language')
87- buf << "Content-Language: #{language}#{EOL}" if language
88+ buf << "Content-Language: #{_no_crlf_check(language)}#{EOL}" if language
89 expires = options.delete('expires')
90 buf << "Expires: #{CGI.rfc1123_date(expires)}#{EOL}" if expires
91 ## cookie
92 if cookie = options.delete('cookie')
93 case cookie
94 when String, Cookie
95- buf << "Set-Cookie: #{cookie}#{EOL}"
96+ buf << "Set-Cookie: #{_no_crlf_check(cookie)}#{EOL}"
97 when Array
98 arr = cookie
99- arr.each {|c| buf << "Set-Cookie: #{c}#{EOL}" }
100+ arr.each {|c| buf << "Set-Cookie: #{_no_crlf_check(c)}#{EOL}" }
101 when Hash
102 hash = cookie
103- hash.each_value {|c| buf << "Set-Cookie: #{c}#{EOL}" }
104+ hash.each_value {|c| buf << "Set-Cookie: #{_no_crlf_check(c)}#{EOL}" }
105 end
106 end
107 if @output_cookies
108- @output_cookies.each {|c| buf << "Set-Cookie: #{c}#{EOL}" }
109+ @output_cookies.each {|c| buf << "Set-Cookie: #{_no_crlf_check(c)}#{EOL}" }
110 end
111 ## other headers
112 options.each do |key, value|
113- buf << "#{key}: #{value}#{EOL}"
114+ buf << "#{_no_crlf_check(key)}: #{_no_crlf_check(value)}#{EOL}"
115 end
116 return buf
117 end # _header_for_hash
118diff --git a/test/cgi/test_cgi_header.rb b/test/cgi/test_cgi_header.rb
119index bab2d03..ec2f4de 100644
120--- a/test/cgi/test_cgi_header.rb
121+++ b/test/cgi/test_cgi_header.rb
122@@ -176,6 +176,14 @@ class CGIHeaderTest < Test::Unit::TestCase
123 end
124
125
126+ def test_cgi_http_header_crlf_injection
127+ cgi = CGI.new
128+ assert_raise(RuntimeError) { cgi.http_header("text/xhtml\r\nBOO") }
129+ assert_raise(RuntimeError) { cgi.http_header("type" => "text/xhtml\r\nBOO") }
130+ assert_raise(RuntimeError) { cgi.http_header("status" => "200 OK\r\nBOO") }
131+ assert_raise(RuntimeError) { cgi.http_header("location" => "text/xhtml\r\nBOO") }
132+ end
133+
134
135 instance_methods.each do |method|
136 private method if method =~ /^test_(.*)/ && $1 != ENV['TEST']
137--
1382.25.1
139