繁体   English   中英

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

[英]Matrix - create matrix from user input(rows)

我想像这样从用户输入创建矩阵:在此处输入图像描述

这是我的代码:

    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()

问题是类型是元组(我不知道为什么),并且在 eval(input()) 中我不能放更多的参数,比如 num,row。 我怎样才能解决这个问题?

当我玩了一下eval()时,我想再详细说明一下,并向 OP 和可能的读者解释为什么使用eval()和用户输入是危险的。


Eval 让您以字符串的形式运行表达式,例如“1+1”或使用内置函数compile()创建的代码对象。

例子:

>>> 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

表达式可以是所有有返回值的东西。

>>> 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

我们得到这个语法错误,因为表达式import os没有返回值。 这意味着,我们不能导入模块,但我们可以使用所有现有的变量、常量、方法、类和导入的模块来制作一个表达式并通过eval(...)调用这个表达式。

从攻击者的角度来看,执行任意代码有点意思。 考虑在服务器的后端使用上面的代码,来自前端的用户输入将被扔到内置的eval()方法中以填充矩阵,然后将其返回到前端。 如果创建一个在线矩阵计算器或类似的东西,这可能是一个有效的场景。

代码如果不开源,就会成为攻击者的盲点。 如果您的应用程序中已经导入了osrequestssubprocess等模块,那么他很幸运。 否则,攻击者无能为力。

如何欺骗eval()

您可能已经提到,我们确实可以调用乍一看没有返回值的方法。 print(...)不仅会在屏幕上打印文本,还会返回<class 'NoneType'>类型的内容。 鉴于此,我们还可以运行另一个非常有趣的内置方法: exec()

Exec 有点像eval() ,但功能更强大,因此更危险。 使用exec() ,我们也可以像上面的示例一样以字符串或编译代码对象的形式运行代码。 但与eval()相比,我们不必运行带有返回值的语句。 使用eval() ,我们只能运行可以分配给某种变量的表达式。 使用exec() ,我们可以运行任何我们想要的表达式,不管它是否有返回值。 此外,表达式的结果在当前进程中保持不变。

示例

>>> 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

让我们检查一下,如果exec(...)是一个有效的表达式,它是否有返回值,以及我们是否可以从eval()运行它。

>>> type(exec("x = 1 + 1"))
<class 'NoneType'>

确实,我们可以。 有了这个小技巧,我们现在还可以在eval()中运行非返回表达式,比如导入模块......

利用此类任意代码执行漏洞可能会产生许多影响。 或多或少无害的一种方法是简单地使应用程序崩溃,因为输入未正确满足。 就提到的矩阵计算器示例而言,像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')没有多大意义。

使用requests ,攻击者还可以在脚本崩溃之前发送数据。 或者他可以更改系统上的文件,安装后门等等。

开发

成功的利用可能如下所示: 使用 exec() 开发 eval()

(1) 攻击者在攻击服务器上启动一个监听器。

(2) 攻击者打开你的在线计算器(或者在这种情况下是 OP 的脚本)

(3) 攻击者插入数据

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

(5) 攻击者现在可以访问被利用的服务器(从“hostname”和“pwd”的输出中可以看到)。

PS请不要滥用这样的可能的漏洞。 进行负责任的披露,并为成为这样一个好人而感到高兴:)

暂无
暂无

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

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