puma 5.6.6 → 5.6.8

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cb3429770d4660d6e96743e79b1a56d90e3d4d9f72678ad37b2b945cadcb1a31
4
- data.tar.gz: d935f257b8d0b2f5d9530305aaffcdc0d0ab1e748b70ce8477f56c16225850f4
3
+ metadata.gz: cc34dc2b7094b86d3eec5100455de02cdcfb14a2e382059565e06e512d5c40ac
4
+ data.tar.gz: 10080424606d3a4613f1b27b33199a048711da57e4b45a55f7e997346c64c419
5
5
  SHA512:
6
- metadata.gz: 2bf1646d4905dff9eaf3176067ae76e7c484dfd15cfa3dbe53953f487cbd57b60ad1b7191993060a6edf7e1fb66247ea9b1486f2aef5fa691ad6d7a4450876bc
7
- data.tar.gz: fc72f4158ed6ff95429b83c725ba33fbdd4e26e780377d8d1c8a0421c5da301dd5919fd2d8404d690e723a4259da078bfc0aa79aa6574e6ed220fe9659de1a52
6
+ metadata.gz: 18da16eff3311151ff29f868f07762d509541b1302dd6ff80bf323bb6fdd73da9d8bc32983a37b71e439faf4753e8110bdafb8f444df205b62f742376c980147
7
+ data.tar.gz: 89968813be0e066fc4de68dc439827d621d2d1803c58c64ee2df78f4d9baa4785fc7865d655990564ff52d9cd64ebc8d9dbc4be048334e0f8db954d83efaeef1
data/History.md CHANGED
@@ -1,3 +1,13 @@
1
+ ## 5.6.8 / 2023-01-08
2
+
3
+ * Security
4
+ * Limit the size of chunk extensions. Without this limit, an attacker could cause unbounded resource (CPU, network bandwidth) consumption. ([GHSA-c2f4-cvqm-65w2](https://github.com/puma/puma/security/advisories/GHSA-c2f4-cvqm-65w2))
5
+
6
+ ## 5.6.7 / 2023-08-18
7
+
8
+ * Security
9
+ * Address HTTP request smuggling vulnerabilities with zero-length Content Length header and trailer fields ([GHSA-68xg-gqqm-vgj8](https://github.com/puma/puma/security/advisories/GHSA-68xg-gqqm-vgj8))
10
+
1
11
  ## 5.6.6 / 2023-06-21
2
12
 
3
13
  * Bugfix
data/lib/puma/client.rb CHANGED
@@ -45,7 +45,16 @@ module Puma
45
45
 
46
46
  # chunked body validation
47
47
  CHUNK_SIZE_INVALID = /[^\h]/.freeze
48
- CHUNK_VALID_ENDING = "\r\n".freeze
48
+ CHUNK_VALID_ENDING = Const::LINE_END
49
+ CHUNK_VALID_ENDING_SIZE = CHUNK_VALID_ENDING.bytesize
50
+
51
+ # The maximum number of bytes we'll buffer looking for a valid
52
+ # chunk header.
53
+ MAX_CHUNK_HEADER_SIZE = 4096
54
+
55
+ # The maximum amount of excess data the client sends
56
+ # using chunk size extensions before we abort the connection.
57
+ MAX_CHUNK_EXCESS = 16 * 1024
49
58
 
50
59
  # Content-Length header value validation
51
60
  CONTENT_LENGTH_VALUE_INVALID = /[^\d]/.freeze
@@ -347,8 +356,8 @@ module Puma
347
356
  cl = @env[CONTENT_LENGTH]
348
357
 
349
358
  if cl
350
- # cannot contain characters that are not \d
351
- if cl =~ CONTENT_LENGTH_VALUE_INVALID
359
+ # cannot contain characters that are not \d, or be empty
360
+ if cl =~ CONTENT_LENGTH_VALUE_INVALID || cl.empty?
352
361
  raise HttpParserError, "Invalid Content-Length: #{cl.inspect}"
353
362
  end
354
363
  else
@@ -459,6 +468,7 @@ module Puma
459
468
  @chunked_body = true
460
469
  @partial_part_left = 0
461
470
  @prev_chunk = ""
471
+ @excess_cr = 0
462
472
 
463
473
  @body = Tempfile.new(Const::PUMA_TMP_BASE)
464
474
  @body.unlink
@@ -509,7 +519,7 @@ module Puma
509
519
 
510
520
  while !io.eof?
511
521
  line = io.gets
512
- if line.end_with?("\r\n")
522
+ if line.end_with?(CHUNK_VALID_ENDING)
513
523
  # Puma doesn't process chunk extensions, but should parse if they're
514
524
  # present, which is the reason for the semicolon regex
515
525
  chunk_hex = line.strip[/\A[^;]+/]
@@ -521,19 +531,39 @@ module Puma
521
531
  @in_last_chunk = true
522
532
  @body.rewind
523
533
  rest = io.read
524
- last_crlf_size = "\r\n".bytesize
525
- if rest.bytesize < last_crlf_size
534
+ if rest.bytesize < CHUNK_VALID_ENDING_SIZE
526
535
  @buffer = nil
527
- @partial_part_left = last_crlf_size - rest.bytesize
536
+ @partial_part_left = CHUNK_VALID_ENDING_SIZE - rest.bytesize
528
537
  return false
529
538
  else
530
- @buffer = rest[last_crlf_size..-1]
539
+ # if the next character is a CRLF, set buffer to everything after that CRLF
540
+ start_of_rest = if rest.start_with?(CHUNK_VALID_ENDING)
541
+ CHUNK_VALID_ENDING_SIZE
542
+ else # we have started a trailer section, which we do not support. skip it!
543
+ rest.index(CHUNK_VALID_ENDING*2) + CHUNK_VALID_ENDING_SIZE*2
544
+ end
545
+
546
+ @buffer = rest[start_of_rest..-1]
531
547
  @buffer = nil if @buffer.empty?
532
548
  set_ready
533
549
  return true
534
550
  end
535
551
  end
536
552
 
553
+ # Track the excess as a function of the size of the
554
+ # header vs the size of the actual data. Excess can
555
+ # go negative (and is expected to) when the body is
556
+ # significant.
557
+ # The additional of chunk_hex.size and 2 compensates
558
+ # for a client sending 1 byte in a chunked body over
559
+ # a long period of time, making sure that that client
560
+ # isn't accidentally eventually punished.
561
+ @excess_cr += (line.size - len - chunk_hex.size - 2)
562
+
563
+ if @excess_cr >= MAX_CHUNK_EXCESS
564
+ raise HttpParserError, "Maximum chunk excess detected"
565
+ end
566
+
537
567
  len += 2
538
568
 
539
569
  part = io.read(len)
@@ -561,6 +591,10 @@ module Puma
561
591
  @partial_part_left = len - part.size
562
592
  end
563
593
  else
594
+ if @prev_chunk.size + chunk.size >= MAX_CHUNK_HEADER_SIZE
595
+ raise HttpParserError, "maximum size of chunk header exceeded"
596
+ end
597
+
564
598
  @prev_chunk = line
565
599
  return false
566
600
  end
data/lib/puma/const.rb CHANGED
@@ -100,7 +100,7 @@ module Puma
100
100
  # too taxing on performance.
101
101
  module Const
102
102
 
103
- PUMA_VERSION = VERSION = "5.6.6".freeze
103
+ PUMA_VERSION = VERSION = "5.6.8".freeze
104
104
  CODE_NAME = "Birdie's Version".freeze
105
105
 
106
106
  PUMA_SERVER_STRING = ['puma', PUMA_VERSION, CODE_NAME].join(' ').freeze
data/lib/puma/null_io.rb CHANGED
File without changes
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: puma
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.6.6
4
+ version: 5.6.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Evan Phoenix
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 1980-01-01 00:00:00.000000000 Z
11
+ date: 2024-01-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nio4r
@@ -141,7 +141,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
141
141
  - !ruby/object:Gem::Version
142
142
  version: '0'
143
143
  requirements: []
144
- rubygems_version: 3.4.12
144
+ rubygems_version: 3.5.3
145
145
  signing_key:
146
146
  specification_version: 4
147
147
  summary: Puma is a simple, fast, threaded, and highly parallel HTTP 1.1 server for