Skip to content

Commit a93af63

Browse files
committed
Reduce resource cosumption of Net::FTP::TIME_PARSER
Reported by Alexandr Savca as a DoS vulnerability, but Net::FTP is a client library and the impact of the issue is low, so I have decided to fix it as a normal issue. Based on patch by nobu.
1 parent b0e2c34 commit a93af63

File tree

3 files changed

+29
-7
lines changed

3 files changed

+29
-7
lines changed

Gemfile.lock

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,25 @@
11
PATH
22
remote: .
33
specs:
4-
net-ftp (0.1.0)
4+
net-ftp (0.1.1)
5+
net-protocol
6+
time
57

68
GEM
79
remote: https://rubygems.org/
810
specs:
9-
power_assert (1.1.5)
10-
rake (13.0.1)
11-
test-unit (3.3.5)
11+
date (3.1.0)
12+
io-wait (0.1.0)
13+
net-protocol (0.1.0)
14+
io-wait
15+
timeout
16+
power_assert (2.0.0)
17+
rake (13.0.3)
18+
test-unit (3.4.1)
1219
power_assert
20+
time (0.1.0)
21+
date
22+
timeout (0.1.1)
1323

1424
PLATFORMS
1525
ruby
@@ -20,4 +30,4 @@ DEPENDENCIES
2030
test-unit
2131

2232
BUNDLED WITH
23-
2.1.4
33+
2.3.0.dev

lib/net/ftp.rb

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1054,10 +1054,11 @@ def writable?
10541054
TIME_PARSER = ->(value, local = false) {
10551055
unless /\A(?<year>\d{4})(?<month>\d{2})(?<day>\d{2})
10561056
(?<hour>\d{2})(?<min>\d{2})(?<sec>\d{2})
1057-
(?:\.(?<fractions>\d+))?/x =~ value
1057+
(?:\.(?<fractions>\d{1,17}))?/x =~ value
1058+
value = value[0, 97] + "..." if value.size > 100
10581059
raise FTPProtoError, "invalid time-val: #{value}"
10591060
end
1060-
usec = fractions.to_i * 10 ** (6 - fractions.to_s.size)
1061+
usec = ".#{fractions}".to_r * 1_000_000 if fractions
10611062
Time.public_send(local ? :local : :utc, year, month, day, hour, min, sec, usec)
10621063
}
10631064
FACT_PARSERS = Hash.new(CASE_DEPENDENT_PARSER)

test/net/ftp/test_ftp.rb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2509,6 +2509,17 @@ def test_puttextfile_command_injection
25092509
end
25102510
end
25112511

2512+
def test_time_parser
2513+
s = "20371231000000." + "9" * 999999999
2514+
assert_equal(Time.utc(2037, 12, 31, 0, 0, 0,
2515+
99999999999999999r / 100000000000),
2516+
Net::FTP::TIME_PARSER[s])
2517+
e = assert_raise(Net::FTPProtoError) {
2518+
Net::FTP::TIME_PARSER["x" * 999999999]
2519+
}
2520+
assert_equal("invalid time-val: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx...", e.message)
2521+
end
2522+
25122523
private
25132524

25142525
def create_ftp_server(sleep_time = nil)

0 commit comments

Comments
 (0)