0x00 前言
eval是Python用于執行python表達式的一個內置函數,使用eval,可以很方便的將字符串動態執行。比如下列代碼:
>>> eval("1+2")>>> eval("[x for x in range(10)]")[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]當內存中的內置模塊含有os的話,eval同樣可以做到命令執行:
>>> import os>>> eval("os.system('whoami')")win-20140812chj/administrator當然,eval只能執行Python的表達式類型的代碼,不能直接用它進行import操作,但exec可以。如果非要使用eval進行import,則使用 __import__ :
>>> exec('import os')>>> eval('import os')Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<string>", line 1 import os ^SyntaxError: invalid syntax>>> eval("__import__('os').system('whoami')")win-20140812chj/administrator在實際的代碼中,往往有使用客戶端數據帶入eval中執行的需求。比如動態模塊的引入,舉個栗子,一個在線爬蟲平臺上爬蟲可能有多個并且位于不同的模塊中,服務器端但往往只需要調用用戶在客戶端選擇的爬蟲類型,并通過后端的exec或者eval進行動態調用,后端編碼實現非常方便。但如果對用戶的請求處理不恰當,就會造成嚴重的安全漏洞。
0x01 “安全”使用eval
現在提倡最多的就是使用eval的后兩個參數來設置函數的白名單:
Eval函數的聲明為 eval(expression[, globals[, locals]])
其中,第二三個參數分別指定能夠在eval中使用的函數等,如果不指定,默認為globals()和locals()函數中 包含的模塊和函數。
>>> import os>>> 'os' in globals()True>>> eval('os.system(/'whoami/')')win-20140812chj/administrator>>> eval('os.system(/'whoami/')',{},{})Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<string>", line 1, in <module>NameError: name 'os' is not defined如果指定只允許調用abs函數,可以使用下面的寫法:
>>> eval('abs(-20)',{'abs':abs},{'abs':abs})>>> eval('os.system(/'whoami/')',{'abs':abs},{'abs':abs})Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<string>", line 1, in <module>NameError: name 'os' is not defined>>> eval('os.system(/'whoami/')')win-20140812chj/administrator使用這種方法來防護,確實可以起到一定的作用,但是, 這種處理方法可能會被繞過 ,從而造成其他問題!
0x02 繞過執行代碼1
被繞過的情景如下,小明知道了eval會帶來一定的安全風險,所以使用如下的手段去防止eval執行任意代碼:
新聞熱點
疑難解答