CVE-2021-3758 (PHP, published 2021-09-02T12:15Z)
Description: value: bookstack is vulnerable to Server-Side Request Forgery (SSRF)
Severity: MEDIUM (CVSS v3 base score: 6.5)
Weakness: CWE-918 \u2014 Server-Side Request Forgery (SSRF)
The web server receives a URL or similar request from an upstream component and retrieves the contents of this URL, but it does not sufficiently ensure that the request is being sent to the expected destination.
Repository: https://github.com/bookstackapp/bookstack
Files changed:
.env.example.complete
app/Config/app.php
app/Config/dompdf.php
app/Entities/Tools/ExportFormatter.php
phpunit.xml
tests/Entity/ExportTest.php
tests/Unit/ConfigTest.php
Commit message: Added untrusted server fetching control

WKHTMLtoPDF provides limited control for external fetching
so that will now be disabled by default unless
ALLOW_UNTRUSTED_SERVER_FETCHING=true is specifically set.
This new option will also control DOMPDF fetching.


Vulnerable code:
        'DOMPDF_FONT_DIR' => storage_path('fonts/'),  // advised by dompdf (https://github.com/dompdf/dompdf/pull/782)
        'DOMPDF_FONT_CACHE' => storage_path('fonts/'),
        'DOMPDF_TEMP_DIR' => sys_get_temp_dir(),
        'DOMPDF_CHROOT' => realpath(base_path()),
        'DOMPDF_UNICODE_ENABLED' => true,
        'DOMPDF_ENABLE_FONTSUBSETTING' => false,
        'DOMPDF_PDF_BACKEND' => 'CPDF',
        'DOMPDF_DEFAULT_MEDIA_TYPE' => 'print',
        'DOMPDF_DEFAULT_PAPER_SIZE' => 'a4',
        'DOMPDF_DEFAULT_FONT' => 'dejavu sans',
        'DOMPDF_DPI' => 96,
        'DOMPDF_ENABLE_PHP' => false,
        'DOMPDF_ENABLE_JAVASCRIPT' => false,
        'DOMPDF_ENABLE_REMOTE' => true,
        'DOMPDF_FONT_HEIGHT_RATIO' => 1.1,
        'DOMPDF_ENABLE_CSS_FLOAT' => true,
        'DOMPDF_ENABLE_HTML5PARSER' => true,
        $useWKHTML = config('snappy.pdf.binary') !== false;

Fixed code:
# Allow server-side fetches to be performed to potentially unknown
# and user-provided locations. Primarily used in exports when loading
# in externally referenced assets.
# Can be 'true' or 'false'.
ALLOW_UNTRUSTED_SERVER_FETCHING=false

    # Allow server-side fetches to be performed to potentially unknown
    # and user-provided locations. Primarily used in exports when loading
    # in externally referenced assets.
    'allow_untrusted_server_fetching' => env('ALLOW_UNTRUSTED_SERVER_FETCHING', false),

        'font_dir' => storage_path('fonts/'),  // advised by dompdf (https://github.com/dompdf/dompdf/pull/782)
        'font_cache' => storage_path('fonts/'),
        'temp_dir' => sys_get_temp_dir(),
        'chroot' => realpath(base_path()),
        'unicode_enabled' => true,
        'enable_fontsubsetting' => false,
        'pdf_backend' => 'CPDF',
        'default_media_type' => 'print',
        'default_paper_size' => 'a4',
        'default_font' => 'dejavu sans',
        'dpi' => 96,
        'enable_php' => false,
        'enable_javascript' => false,
        'enable_remote' => env('ALLOW_UNTRUSTED_SERVER_FETCHING', false),
        'font_height_ratio' => 1.1,
        'enable_css_float' => true,
        'enable_html5parser' => true,
        $useWKHTML = config('snappy.pdf.binary') !== false && config('app.allow_untrusted_server_fetching') === true;
    <server name="ALLOW_UNTRUSTED_SERVER_FETCHING" value="false"/>

    public function test_wkhtmltopdf_only_used_when_allow_untrusted_is_true()
    {
        /** @var Page $page */
        $page = Page::query()->first();

        config()->set('snappy.pdf.binary', '/abc123');
        config()->set('app.allow_untrusted_server_fetching', false);

        $resp = $this->asEditor()->get($page->getUrl('/export/pdf'));
        $resp->assertStatus(200); // Sucessful response with invalid snappy binary indicates dompdf usage.

        config()->set('app.allow_untrusted_server_fetching', true);
        $resp = $this->get($page->getUrl('/export/pdf'));
        $resp->assertStatus(500); // Bad response indicates wkhtml usage
    }
    public function test_dompdf_remote_fetching_controlled_by_allow_untrusted_server_fetching_false()
    {
        $this->checkEnvConfigResult('ALLOW_UNTRUSTED_SERVER_FETCHING', 'false', 'dompdf.defines.enable_remote', false);
        $this->checkEnvConfigResult('ALLOW_UNTRUSTED_SERVER_FETCHING', 'true', 'dompdf.defines.enable_remote', true);
    }