Kaynağa Gözat

fix: check sizelimit over full request, before attempting decoding

El RIDO 3 hafta önce
ebeveyn
işleme
272fcc45fc
4 değiştirilmiş dosya ile 32 ekleme ve 22 silme
  1. 5 4
      CHANGELOG.md
  2. 1 1
      cfg/conf.sample.php
  3. 4 14
      lib/Controller.php
  4. 22 3
      lib/Request.php

+ 5 - 4
CHANGELOG.md

@@ -1,16 +1,17 @@
 # PrivateBin version history
 # PrivateBin version history
 
 
 ## 2.1.1 (not yet released)
 ## 2.1.1 (not yet released)
+* CHANGED: Check `sizelimit` over full request, before attempting decoding
 
 
 ## 2.1.0 (2026-10-18)
 ## 2.1.0 (2026-10-18)
 * ADDED: Added `shortenviachhoto` endpoint with an `chhoto` configuration section
 * ADDED: Added `shortenviachhoto` endpoint with an `chhoto` configuration section
 * ADDED: Translation for Chinese (Traditional)
 * ADDED: Translation for Chinese (Traditional)
 * ADDED: Subject line to the "Email" share button's mailto link (#928)
 * ADDED: Subject line to the "Email" share button's mailto link (#928)
 * ADDED: Send the document with Ctrl+S, or Cmd+S on macOS (#739)
 * ADDED: Send the document with Ctrl+S, or Cmd+S on macOS (#739)
-* CHANGED: We removed jQuery in the Frontend and replaced it with vanilla JS.
-* CHANGED: Removed the unmaintained js-verify and replaced it with fast-check library.
-* CHANGED: Added a `jsconfig.json` in order to check the types of JavaScript.
-* CHANGED: Removed support for Bootstrap 3 as it requires jQuery.
+* CHANGED: We removed jQuery in the Frontend and replaced it with vanilla JS
+* CHANGED: Removed the unmaintained js-verify and replaced it with fast-check library
+* CHANGED: Added a `jsconfig.json` in order to check the types of JavaScript
+* CHANGED: Removed support for Bootstrap 3 as it requires jQuery
 * CHANGED: Encode documents with `TextEncoder` in `compress()`, instead of the `utf16To8()` percent-encoding round trip, which allocated ~20 times the payload
 * CHANGED: Encode documents with `TextEncoder` in `compress()`, instead of the `utf16To8()` percent-encoding round trip, which allocated ~20 times the payload
 * CHANGED: Upgrading libraries to: DOMpurify 3.4.17, ip-lib 1.22.1 & polyfill-php80 1.43.0
 * CHANGED: Upgrading libraries to: DOMpurify 3.4.17, ip-lib 1.22.1 & polyfill-php80 1.43.0
 * FIXED: Decode decompressed documents with `TextDecoder` instead of `utf8To16()`, which allocated ~3.4 GB for a 100 MB document and killed the tab (#2027)
 * FIXED: Decode decompressed documents with `TextDecoder` instead of `utf8To16()`, which allocated ~3.4 GB for a 100 MB document and killed the tab (#2027)

+ 1 - 1
cfg/conf.sample.php

@@ -40,7 +40,7 @@ defaultformatter = "plaintext"
 ; syntaxhighlightingtheme = "sons-of-obsidian"
 ; syntaxhighlightingtheme = "sons-of-obsidian"
 
 
 ; size limit per document or comment in bytes, defaults to 10 Megabytes
 ; size limit per document or comment in bytes, defaults to 10 Megabytes
-sizelimit = 10000000
+sizelimit = 10485760
 
 
 ; by default PrivateBin use "bootstrap5" template (tpl/bootstrap5.php).
 ; by default PrivateBin use "bootstrap5" template (tpl/bootstrap5.php).
 ; Optionally you can enable the template selection menu, which uses
 ; Optionally you can enable the template selection menu, which uses

+ 4 - 14
lib/Controller.php

@@ -92,7 +92,7 @@ class Controller
      * Factory of instance models
      * Factory of instance models
      *
      *
      * @access private
      * @access private
-     * @var    model
+     * @var    Model
      */
      */
     private $_model;
     private $_model;
 
 
@@ -100,7 +100,7 @@ class Controller
      * request
      * request
      *
      *
      * @access private
      * @access private
-     * @var    request
+     * @var    Request
      */
      */
     private $_request;
     private $_request;
 
 
@@ -280,14 +280,15 @@ class Controller
         ServerSalt::setStore($this->_model->getStore());
         ServerSalt::setStore($this->_model->getStore());
         TrafficLimiter::setConfiguration($this->_conf);
         TrafficLimiter::setConfiguration($this->_conf);
         TrafficLimiter::setStore($this->_model->getStore());
         TrafficLimiter::setStore($this->_model->getStore());
+        $data = [];
         try {
         try {
             TrafficLimiter::canPass();
             TrafficLimiter::canPass();
+            $data = $this->_request->getData($this->_conf->getKey('sizelimit'));
         } catch (TranslatedException $e) {
         } catch (TranslatedException $e) {
             $this->_json_error($e->getMessage());
             $this->_json_error($e->getMessage());
             return;
             return;
         }
         }
 
 
-        $data      = $this->_request->getData();
         $isComment = array_key_exists('pasteid', $data) &&
         $isComment = array_key_exists('pasteid', $data) &&
             !empty($data['pasteid']) &&
             !empty($data['pasteid']) &&
             array_key_exists('parentid', $data) &&
             array_key_exists('parentid', $data) &&
@@ -296,17 +297,6 @@ class Controller
             $this->_json_error(I18n::_('Invalid data.'));
             $this->_json_error(I18n::_('Invalid data.'));
             return;
             return;
         }
         }
-        $sizelimit = $this->_conf->getKey('sizelimit');
-        // Ensure content is not too big.
-        if (strlen($data['ct']) > $sizelimit) {
-            $this->_json_error(
-                I18n::_(
-                    'Document is limited to %s of encrypted data.',
-                    Filter::formatHumanReadableSize($sizelimit)
-                )
-            );
-            return;
-        }
 
 
         // The user posts a comment.
         // The user posts a comment.
         if ($isComment) {
         if ($isComment) {

+ 22 - 3
lib/Request.php

@@ -13,6 +13,7 @@ namespace PrivateBin;
 
 
 use JsonException;
 use JsonException;
 use PrivateBin\Model\Paste;
 use PrivateBin\Model\Paste;
+use PrivateBin\Exception\TranslatedException;
 
 
 /**
 /**
  * Request
  * Request
@@ -42,6 +43,14 @@ class Request
      */
      */
     const MIME_XHTML = 'application/xhtml+xml';
     const MIME_XHTML = 'application/xhtml+xml';
 
 
+    /**
+     * Input stream length for size checks
+     *
+     * @access private
+     * @var int
+     */
+    private $_bodyLength = 0;
+
     /**
     /**
      * Input stream to use for PUT parameter parsing
      * Input stream to use for PUT parameter parsing
      *
      *
@@ -111,8 +120,9 @@ class Request
                 // it might be a creation or a deletion, the latter is detected below
                 // it might be a creation or a deletion, the latter is detected below
                 $this->_operation = 'create';
                 $this->_operation = 'create';
                 try {
                 try {
-                    $data          = file_get_contents(self::$_inputStream);
-                    $this->_params = Json::decode($data);
+                    $data              = file_get_contents(self::$_inputStream);
+                    $this->_bodyLength = strlen($data);
+                    $this->_params     = Json::decode($data);
                     // a valid JSON scalar (number, bool or string) decodes
                     // a valid JSON scalar (number, bool or string) decodes
                     // without error, but is not a usable set of parameters
                     // without error, but is not a usable set of parameters
                     if (!is_array($this->_params)) {
                     if (!is_array($this->_params)) {
@@ -196,10 +206,19 @@ class Request
      * Get data of paste or comment
      * Get data of paste or comment
      *
      *
      * @access public
      * @access public
+     * @param  int $sizelimit
+     * @throws JsonException
+     * @throws TranslatedException
      * @return array
      * @return array
      */
      */
-    public function getData()
+    public function getData(int $sizelimit)
     {
     {
+        if ($this->_bodyLength > $sizelimit) {
+            throw new TranslatedException([
+                'Document is limited to %s of encrypted data.',
+                Filter::formatHumanReadableSize($sizelimit)
+            ]);
+        }
         $data = [
         $data = [
             'adata' => $this->getParam('adata'),
             'adata' => $this->getParam('adata'),
         ];
         ];