Search code examples
pythonexecpython-2.xctf

Why there is a SytaxError when pushing an exec() function into an input()


There is a netcat CTF task where it is needed to get the flag via an RCE (the most simple and obvious variant for me is exec())

Python 2.7.18 (default, Apr 28 2021, 17:39:59)
[GCC 10.2.1 20210110] on linux2

>>> print input()
pow(2, 3) # No problems with functions
8

>>> print input()
None # Can print None values
None

>>> print input()
eval('1 + 1')
2

>>> print input()
eval('1 + 1') # eval() works
2

>>> x = 1
>>> print input()
eval('x + 1') # eval() with local variables involved also works
2

>>> print input()
exec('') # Even empty exec() causes an error
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1
    exec('') # Even empty exec() causes an error
       ^
SyntaxError: invalid syntax

>>> print input()
exec('import os') # exec() call causes an error
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1
    exec('import os') # exec() call causes an error
       ^
SyntaxError: invalid syntax

Is it possible to push an exec() with input() called in Python 2.7? (Switching the Python version or changing executable print input() cannot be done)

UPD

I need something like this:

>>> print input()
exec('import os\nprint os.name') # I need a similar RCE in this CTF task, so eval() is not suitable
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1
    exec('import os\nprint os.name') # I need a similar RCE in this CTF task, so eval() is not suitable
       ^
SyntaxError: invalid syntax

Solution

  • Instead of

    >>> print input()
    exec('1 + 1') 
    

    do

    >>> print input()
    eval('1 + 1') 
    

    and you will get the output 2 that you expect. exec() expects executable statements; eval() expects an expression, which is what 1+1 is. Though this is simpler and equivalent:

    >>> print input()
    1 + 1 
    

    I must admit I have no idea what a CTF task is, or why it needs to execute RTE code, whatever that is, but given that your real requirement is not to produce the result of 1 + 1 but rather the value of os.name, it might suit your purpose better to avoid futzing around the corner cases of the obsolete input() function and simply do, as a command line,

    python -c "import os;print(os.name)"
    

    which (on my system) produces the output

    nt
    

    and will work in every version of Python.

    The reason why the Python 2 input() function cannot be made to do what you want, is that in Python 2

    • exec is a statement, not a function.
    • input() is roughly equivalent to eval(raw_input()): it will accept expressions but not statements.