Thijs
Thijs

Reputation: 717

Is it safe to put information from an untrusted source as python exception message?

Is there any way that the following is dangerous? As in, can code get executed if someone prints this exception to stdout?

def somefunc(val_from_untrusted_source):
    if val_from_untrusted_source == 'something_we_except':
        # do something useful
        pass
    else:
        raise RuntimeException('unknown input: {}'.format(val_from_untrusted_source))

Upvotes: 0

Views: 70

Answers (2)

Serge Ballesta
Serge Ballesta

Reputation: 148965

Never to that!

Log messages are meant to inform about processing and should be securely delivered to allow to find evidences of what happened in case of problems. Here no control is done so here are some possible problems:

  • str(val_from_untrusted_source) could itself raise an exception, among which UnicodeEncodeError for unicode strings containing non ASCII characters in Python 2, or UnicodeDecodeError for byte strings containing non ASCII characters in Python 3. This also includes object specially crafted with an exception raising __str__ method
  • str(val_from_untrusted_source) could be a looooong string. It includes long byte or unicode string, but also tiny objects specialy crafted:

    class DONT:
        def __init__(self, size, pattern):
            self.pattern = pattern
            self.size = size
        def __str__(self):
            return self.pattern * self.size
    

    They could cause the log file to exhaust to disk space

  • An object can be specially crafted with a never ending __str__ method, or one that tries to exhaust memory. Just imagine a slight variation of above DONT...

All that is what could happen in the worse use case where code in uncontrolled. In a more real use scenario, val_from_untrusted_source will probably be a string. In that case, it is enough to limit its size and handle UnicodeError exception:

if val_from_untrusted_source == 'something_we_except':
    # do something useful
    pass
else:
    try:
        txt = str(val_from_untrusted_source)
    except UnicodeEncodeError:                # unicode string on Python 2
        txt = val_from_untrusted_source.encode(error = 'replace')
    except UnicodeDecodeError:                # byte string on Python 3
        txt = val_from_untrusted_source.decode(error = 'replace')
    except Exception:                         # quite weird but once we are there...
        txt = "object non convertible to string"
    if len(text) > 47):     # limit length to 50
        txt = txt[:47] + '...'
    raise RuntimeException('unknown input: {}'.format(txt))

Upvotes: 2

Eugene Primako
Eugene Primako

Reputation: 2817

As far as I know, nothing dangerous can't happen. The most unpleasant consequences:

  1. (if Python 2 is assumed) If val_from_untrusted_source is not ASCII, UnicodeEncodeError will occur when trying to raise RuntimeException
  2. If val_from_untrusted_source contains '\r' and someone writes this exception to log - the beginning of the current log line may be overwrited

Upvotes: 1

Related Questions