Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 24f236e

Browse files
jasnowRubySec CI
authored and
RubySec CI
committedFeb 11, 2025·
Updated advisory posts against rubysec/ruby-advisory-db@44593ed
1 parent a03bda5 commit 24f236e

File tree

2 files changed

+165
-0
lines changed

2 files changed

+165
-0
lines changed
 

‎advisories/_posts/2024-09-19-CVE-2024-7254.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,4 +68,5 @@ advisory:
6868
- https://github.com/protocolbuffers/protobuf/commit/cc8b3483a5584b3301e3d43d17eb59704857ffaa
6969
- https://github.com/protocolbuffers/protobuf/commit/d6c82fc55a76481c676f541a255571e8950bb8c3
7070
- https://github.com/advisories/GHSA-735f-pc8j-v9w8
71+
...
7172
---
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
---
2+
layout: advisory
3+
title: 'CVE-2025-25186 (net-imap): Possible DoS by memory exhaustion in net-imap'
4+
comments: false
5+
categories:
6+
- net-imap
7+
advisory:
8+
gem: net-imap
9+
cve: 2025-25186
10+
ghsa: 7fc5-f82f-cx69
11+
url: https://github.com/ruby/net-imap/security/advisories/GHSA-7fc5-f82f-cx69
12+
title: Possible DoS by memory exhaustion in net-imap
13+
date: 2025-02-10
14+
description: |
15+
### Summary
16+
17+
There is a possibility for denial of service by memory exhaustion in
18+
`net-imap`'s response parser. At any time while the client is
19+
connected, a malicious server can send can send highly compressed
20+
`uid-set` data which is automatically read by the client's receiver
21+
thread. The response parser uses `Range#to_a` to convert the
22+
`uid-set` data into arrays of integers, with no limitation on the
23+
expanded size of the ranges.
24+
25+
### Details
26+
27+
IMAP's `uid-set` and `sequence-set` formats can compress ranges of
28+
numbers, for example: `"1,2,3,4,5"` and `"1:5"` both represent the
29+
same set. When `Net::IMAP::ResponseParser` receives `APPENDUID` or
30+
`COPYUID` response codes, it expands each `uid-set` into an array of
31+
integers. On a 64 bit system, these arrays will expand to 8 bytes
32+
for each number in the set. A malicious IMAP server may send
33+
specially crafted `APPENDUID` or `COPYUID` responses with very large
34+
`uid-set` ranges.
35+
36+
The `Net::IMAP` client parses each server response in a separate
37+
thread, as soon as each responses is received from the server.
38+
This attack works even when the client does not handle the
39+
`APPENDUID` or `COPYUID` responses.
40+
41+
Malicious inputs:
42+
43+
```ruby
44+
# 40 bytes expands to ~1.6GB:
45+
"* OK [COPYUID 1 1:99999999 1:99999999]\r\n"
46+
47+
# Worst *valid* input scenario (using uint32 max),
48+
# 44 bytes expands to 64GiB:
49+
"* OK [COPYUID 1 1:4294967295 1:4294967295]\r\n"
50+
51+
# Numbers must be non-zero uint32, but this isn't validated. Arrays
52+
# larger than UINT32_MAX can be created. For example, the following
53+
# would theoretically expand to almost 800 exabytes:
54+
"* OK [COPYUID 1 1:99999999999999999999 1:99999999999999999999]\r\n"
55+
```
56+
57+
Simple way to test this:
58+
```ruby
59+
require "net/imap"
60+
61+
def test(size)
62+
input = "A004 OK [COPYUID 1 1:#{size} 1:#{size}] too large?\n"
63+
parser = Net::IMAP::ResponseParser.new
64+
parser.parse input
65+
end
66+
67+
test(99_999_999)
68+
```
69+
70+
### Fixes
71+
72+
#### Preferred Fix, minor API changes
73+
74+
Upgrade to v0.4.19, v0.5.6, or higher, and configure:
75+
76+
```ruby
77+
# globally
78+
Net::IMAP.config.parser_use_deprecated_uidplus_data = false
79+
# per-client
80+
imap = Net::IMAP.new(hostname, ssl: true,
81+
parser_use_deprecated_uidplus_data: false)
82+
imap.config.parser_use_deprecated_uidplus_data = false
83+
```
84+
85+
This replaces `UIDPlusData` with `AppendUIDData` and `CopyUIDData`.
86+
These classes store their UIDs as `Net::IMAP::SequenceSet` objects
87+
(_not_ expanded into arrays of integers). Code that does not handle
88+
`APPENDUID` or `COPYUID` responses will not notice any difference.
89+
Code that does handle these responses _may_ need to be updated. See
90+
the documentation for
91+
[UIDPlusData](https://ruby.github.io/net-imap/Net/IMAP/UIDPlusData.html),
92+
[AppendUIDData](https://ruby.github.io/net-imap/Net/IMAP/AppendUIDData.html)
93+
and [CopyUIDData](https://ruby.github.io/net-imap/Net/IMAP/CopyUIDData.html).
94+
95+
For v0.3.8, this option is not available.
96+
For v0.4.19, the default value is `true`.
97+
For v0.5.6, the default value is `:up_to_max_size`.
98+
For v0.6.0, the only allowed value will be `false` _(`UIDPlusData`
99+
will be removed from v0.6)_.
100+
101+
#### Mitigation, backward compatible API
102+
103+
Upgrade to v0.3.8, v0.4.19, v0.5.6, or higher.
104+
105+
For backward compatibility, `uid-set` can still be expanded
106+
into an array, but a maximum limit will be applied.
107+
108+
Assign `config.parser_max_deprecated_uidplus_data_size` to set the
109+
maximum `UIDPlusData` UID set size. When
110+
`config.parser_use_deprecated_uidplus_data == true`, larger sets will crash.
111+
When `config.parser_use_deprecated_uidplus_data == :up_to_max_size`,
112+
larger sets will use `AppendUIDData` or `CopyUIDData`.
113+
114+
For v0.3,8, this limit is _hard-coded_ to 10,000, and larger sets
115+
will always raise `Net::IMAP::ResponseParseError`.
116+
For v0.4.19, the limit defaults to 1000.
117+
For v0.5.6, the limit defaults to 100.
118+
For v0.6.0, the limit will be ignored _(`UIDPlusData` will be
119+
removed from v0.6)_.
120+
121+
#### Please Note: unhandled responses
122+
123+
If the client does not add response handlers to prune unhandled
124+
responses, a malicious server can still eventually exhaust all
125+
126+
client memory, by repeatedly sending malicious responses. However,
127+
`net-imap` has always retained unhandled responses, and it has always
128+
been necessary for long-lived connections to prune these responses.
129+
_This is not significantly different from connecting to a trusted
130+
server with a long-lived connection._ To limit the maximum number
131+
of retained responses, a simple handler might look something like
132+
the following:
133+
134+
```ruby
135+
limit = 1000
136+
imap.add_response_handler do |resp|
137+
next unless resp.respond_to?(:name) && resp.respond_to?(:data)
138+
name = resp.name
139+
code = resp.data.code&.name if resp.data.respond_to?(:code)
140+
if Net::IMAP::VERSION > "0.4.0"
141+
imap.responses(name) { _1.slice!(0...-limit) }
142+
imap.responses(code) { _1.slice!(0...-limit) }
143+
else
144+
imap.responses(name).slice!(0...-limit)
145+
imap.responses(code).slice!(0...-limit)
146+
end
147+
end
148+
```
149+
cvss_v3: 6.5
150+
unaffected_versions:
151+
- "< 0.3.2"
152+
patched_versions:
153+
- "~> 0.3.8"
154+
- "~> 0.4.19"
155+
- ">= 0.5.6"
156+
related:
157+
url:
158+
- https://nvd.nist.gov/vuln/detail/CVE-2025-25186
159+
- https://github.com/ruby/net-imap/security/advisories/GHSA-7fc5-f82f-cx69
160+
- https://github.com/ruby/net-imap/commit/70e3ddd071a94e450b3238570af482c296380b35
161+
- https://github.com/ruby/net-imap/commit/c8c5a643739d2669f0c9a6bb9770d0c045fd74a3
162+
- https://github.com/ruby/net-imap/commit/cb92191b1ddce2d978d01b56a0883b6ecf0b1022
163+
- https://github.com/advisories/GHSA-7fc5-f82f-cx69
164+
---

0 commit comments

Comments
 (0)
Please sign in to comment.