Python之漢諾塔問題
今天學習了一下漢諾塔問題,像了許久啊!!腦袋不太OK!記得上次看到漢諾塔是我在看電影的時候,電影場景裏給大猩猩測試智商的。。。。
這裏使用的是Python3編寫的代碼,畢竟大家都知道2020年的1月1日Python2已經正式退休了。下面是Python3的時代了。
發現規律後就會意識到這個就是一個遞歸函數,挺明顯的。
代碼如下:
'''
下面是漢諾塔問題不同的圓盤個數實現任務的次數規律:
n=1 a=1 f(x) = 1
n=2 a=3 f(2) = 2*f(1)+1
n=3 a=7 f(3) = 2*f(2)+1
n=4 a=15 f(4) = 2*f(3)+1
... ... f(n) = 2*f(n-1)+1
'''
def Move(n,a,b,c):
if n == 1:
print (a,'--->',c) #如果只有一個圓盤就直接把它從A拿到C,並且結束程序。
return 0
else: #不是一個圓盤那麼就要對n-1個圓盤從A移到B
Move(n-1,a,c,b)
print (a,'--->',c) #把最底下的那個從A移動到C
Move(n-1,b,a,c) #最後把在B的n-1個圓盤移動到C
number = input('請輸入圓盤的個數(整數數字):')
Move(eval(number),'A','B','C')
運行效果如下:
思考
說起Python,這也是一門解釋型語言所以它肯定會存在一些注入漏洞,之前在看SQL注入的時候就一直在想Python注入會是什麼樣的。今天就試一試,因爲剛好我在編寫代碼的時候使用到了eval()
函數,這個函數可以把字符串轉換爲Python可以理解的語句,這樣就產生了了一個命令執行漏洞。就不具體講了,所以我發現它是可以被利用於注入的。
所以我就設置了一個flag進行簡單是實驗:
'''
下面是漢諾塔問題不同的圓盤個數實現任務的次數規律:
n=1 a=1 f(x) = 1
n=2 a=3 f(2) = 2*f(1)+1
n=3 a=7 f(3) = 2*f(2)+1
n=4 a=15 f(4) = 2*f(3)+1
... ... f(n) = 2*f(n-1)+1
'''
flag='A1andNS{sfji_341bghsdf_6ygsfuh}'
def Move(n,a,b,c):
if n == 1:
print (a,'--->',c) #如果只有一個圓盤就直接把它從A拿到C,並且結束程序。
return 0
else: #不是一個圓盤那麼就要對n-1個圓盤從A移到B
Move(n-1,a,c,b)
print (a,'--->',c) #把最底下的那個從A移動到C
Move(n-1,b,a,c) #最後把在B的n-1個圓盤移動到C
number = input('請輸入圓盤的個數(整數數字):')
Move(eval(number),'A','B','C')
代碼如上,然後運行一下:
照常請求輸入數字,但是我會輸入print(flag)
語句:
運行一下結果如下:
我要的Flag被直接顯示出來了,當然由於eval(‘print flag’)被執行,所以python報錯了,Move()函數就傳參異常了。
防範
那麼要怎麼樣來防止被惡意執行命令呢?
可以從eval()函數自身開始看,利用eval()的兩個設置 限制條件的位來設置白名單,從而避免被執行。
'''
n=1 a=1 f(x) = 1
n=2 a=3 f(2) = 2*f(1)+1
n=3 a=7 f(3) = 2*f(2)+1
n=4 a=15 f(4) = 2*f(3)+1
... ... f(n) = 2*f(n-1)+1
'''
flag='A1andNS{sfji_341bghsdf_6ygsfuh}'
def Move(n,a,b,c):
if n == 1:
print (a,'--->',c)
return 0
else:
Move(n-1,a,c,b)
print (a,'--->',c)
Move(n-1,b,a,c)
number = input('請輸入圓盤的個數(整數數字):')
Move(eval(number,{'input':input},{'input':input}),'A','B','C')
比如我把eval函數加了限制後再去執行print(flag),就不起作用了。
當然這只是一個簡單的實驗,證實了eval函數在帶來便利的同時也會帶來一些風險,這些風險需要被重視,並且安全的使用eval函數。否則就會造成一些不必要的損失。