'Matrix - create matrix from user input(rows)
i want to create matrix from user input like this:enter image description here
this is my code:
flag = True
while flag:
num = int(input('enter matrix dimension:'))
if num == 0:
print('Finish')
flag = False
else:
matrix = []
for row in range(num):
matrix.append([])
for column in range(1):
value = eval(input('Enter elements in row with commas:'))
matrix[row].append(value)
print (matrix)
for row in range(len(matrix)):
for column in range(len(matrix[row])):
print(matrix[row][column], end=" ")
print()
main()
the problem is that the type is tuple(i dont know why), and in the eval(input()) i cant put more arguments like num,row. how can i fix this?
Solution 1:[1]
As I played around a little with eval(), I want to elaborate on this a little more and explain to the OP and possible readers, why using eval() with user input is dangerous.
Eval let's you run expressions in form of strings, like "1+1" or code objects created with the builtin function compile().
Example:
>>> expression = "1+1"
>>> res = eval(expression)
>>> print(res)
2
>>> compiled_expression = compile(expression, "<string>", "eval")
>>> print(compiled_expression.co_code)
b'd\x00S\x00'
>>> res = eval(compiled_expression)
>>> print(res)
2
The expression can be everything, which has a return value.
>>> type(1+1)
<class 'int'>
>>> x = 42
>>> type(1 if x%2 == 0 else 1)
<class 'int'>
>>> type(print("Hi"))
Hi
<class 'NoneType'>
>>> type(import os)
File "<bpython-input-42>", line 1
type(import os)
^^^^^^
SyntaxError: invalid syntax
We're getting this syntax error, because the expression import os has no return value. This means, we cannot import modules, but we can use all existing variables, constants, methods, classes and imported modules to craft an expression and call this expression via eval(...).
From an attackers perspective, executing arbitrary code is kinda interesting. Consider of using the above code in a backend of a server, where user input from the frontend will be thrown into the builtin eval() method to fill a matrix, which is then returned to the frontend. Could be a valid scenario if one creates an online matrix calculator or stuff like that.
The code, if not open-sourced, is a blind spot for the attacker. If modules like os, requests or subprocess are already imported in your application, he's lucky. If not, there isn't much an attacker can do.
How to trick eval():
You may have mentioned, that we can indeed call methods which have no return value at first glance. print(...) does not only print text to your screen, but also it returns something of type <class 'NoneType'>.
Given that, we can also run another very interesting builtin method: exec().
Exec is a little like eval(), but kind of much more powerful and thus more dangerous. With exec(), we can as well run code in form of strings or compiled code objects like in the example above. But in contrast to eval(), we do not have to run a statement with a return value. With eval(), we can only run expressions which we can assign to some sort of variable.
With exec(), we can run any expression we want, independent of whether it has a return value or not. And moreover, the result of the expression stays permanent in the current process.
Example:
>>> print(x)
Traceback (most recent call last):
File "<input>", line 1, in <module>
print(x)
NameError: name 'x' is not defined
>>> exec("x = 1 + 1")
>>> print(x)
2
Let's do the check, if exec(...) is a valid expression, which has a return value or not and whether we can run it from eval().
>>> type(exec("x = 1 + 1"))
<class 'NoneType'>
Indeed, we can. With this little trick, we can now also run non-returning expressions from within eval(), like importing modules ...
Exploiting such arbitrary code execution vulnerabilities can have many impacts. The more or less harmless one is to simply crash the application because the input was not satisfied correctly. In terms of the mentioned matrix-calculator example, a row like posix.uname_result(sysname='Linux', nodename='redacted', release='5.10.105-1-MANJARO', version='#1 SMP PREEMPT Fri Mar 11 14:12:33 UTC 2022', machine='x86_64') would not make much sense.
Using requests, an attacker could also send data out before the script crashes. Or he could change files on the system, install a backdoor and so on.
Exploitation:
A successful exploitation could look like this:

(1) the attacker starts a listener on the attacking server.
(2) the attacker opens your online calculator (or in this case, the OP's script)
(3) the attacker inserts data
(4) when the attacker comes to the input, where eval() is used in the background, the code for spawning a reverse shell will be inserted like this: exec("""start_reverse_shell(ip=<attackers ip>, port=<attacker port>)""") (Note: start_reverse_shell() is not valid code, but I don't wanna post code for a reverse shell here ;) )
The script is now running the code, and as the provided statement has a return value, the current action is valid. The code for the reverse shell imports some modules and establishes a connection to the server of the attacker.
(5) The attacker has now access to the exploited server (as you can see from the output of "hostname" and "pwd").
PS Please do NOT misuse possible vulnerabilities like this. Go for responsible disclosure and be happy about being such a good human being :)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | ðá á |
