Skip to content

Commit e2ac25d

Browse files
shugonagachika
authored andcommitted
Fix StartTLS stripping vulnerability
This fixes CVE-2021-32066. Reported by Alexandr Savca in <https://hackerone.com/reports/1178562>.
1 parent fc71da2 commit e2ac25d

2 files changed

Lines changed: 38 additions & 1 deletion

File tree

lib/net/imap.rb

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1218,12 +1218,14 @@ def get_tagged_response(tag, cmd)
12181218
end
12191219
resp = @tagged_responses.delete(tag)
12201220
case resp.name
1221+
when /\A(?:OK)\z/ni
1222+
return resp
12211223
when /\A(?:NO)\z/ni
12221224
raise NoResponseError, resp
12231225
when /\A(?:BAD)\z/ni
12241226
raise BadResponseError, resp
12251227
else
1226-
return resp
1228+
raise UnknownResponseError, resp
12271229
end
12281230
end
12291231

@@ -3719,6 +3721,10 @@ class BadResponseError < ResponseError
37193721
class ByeResponseError < ResponseError
37203722
end
37213723

3724+
# Error raised upon an unknown response from the server.
3725+
class UnknownResponseError < ResponseError
3726+
end
3727+
37223728
RESPONSE_ERRORS = Hash.new(ResponseError)
37233729
RESPONSE_ERRORS["NO"] = NoResponseError
37243730
RESPONSE_ERRORS["BAD"] = BadResponseError

test/net/imap/test_imap.rb

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,16 @@ def test_starttls
127127
imap.disconnect
128128
end
129129
end
130+
131+
def test_starttls_stripping
132+
starttls_stripping_test do |port|
133+
imap = Net::IMAP.new("localhost", :port => port)
134+
assert_raise(Net::IMAP::UnknownResponseError) do
135+
imap.starttls(:ca_file => CA_FILE)
136+
end
137+
imap
138+
end
139+
end
130140
end
131141

132142
def start_server
@@ -834,6 +844,27 @@ def starttls_test
834844
end
835845
end
836846

847+
def starttls_stripping_test
848+
server = create_tcp_server
849+
port = server.addr[1]
850+
start_server do
851+
sock = server.accept
852+
begin
853+
sock.print("* OK test server\r\n")
854+
sock.gets
855+
sock.print("RUBY0001 BUG unhandled command\r\n")
856+
ensure
857+
sock.close
858+
server.close
859+
end
860+
end
861+
begin
862+
imap = yield(port)
863+
ensure
864+
imap.disconnect if imap && !imap.disconnected?
865+
end
866+
end
867+
837868
def create_tcp_server
838869
return TCPServer.new(server_addr, 0)
839870
end

0 commit comments

Comments
 (0)