0

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
martineau
  • 119,623
  • 25
  • 170
  • 301
Genken
  • 23
  • 5
  • Stack Overflow is not intended to replace existing documentation and tutorials. Why do you think that `1 + 1` or an empty line is a legal statement in the command shell you invoke with `exec`? – Prune Jul 07 '21 at 20:25
  • @Prune Well, I found nothing about this in the docs. I mean the problem is not in the starement inside `exec()` itself (look in the UPD - without print input() it executes with no errors (as I wrote, the executed “print input()” at the beginning cannot be overridden) – Genken Jul 07 '21 at 20:35
  • [The doc](https://docs.python.org/3/library/functions.html#exec) clearly says that you must supply an executable statement. Neither `1 + 1` nor the empty string is an executable statement. – Prune Jul 07 '21 at 20:41
  • @Prune You are right about `1 + 1` and empty input, I will edit the question. But `exec(‘import os\nprint os.name’)` is a valid executable statement, so question stays unanswered. – Genken Jul 07 '21 at 20:45
  • I have extended the answer to explain why `'exec "import os;print os.name"'` is not acceptable to `input()` and to suggest an alternative approach that avoids both `input()` and `exec`. – BoarGules Jul 08 '21 at 10:03

1 Answers1

0

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.
BoarGules
  • 16,440
  • 2
  • 27
  • 44
  • Can `eval` somehow execute a single-string script (I should mention again that it is a CTF task and I need to access the `os` module with a single line that should contain RCE code) like this: `exec('import os\nprint os.name')`? – Genken Jul 07 '21 at 19:54
  • Perhaps use multi-statement syntax instead? Replace the newline with a semicolon. This is working for me under Python 3.8. (Please note that 2.7 was deprecated 18 months ago.) – Prune Jul 07 '21 at 21:04