2011-03-18 49 views
4

如果攻擊者可以控制值attacker_controlled_nasty_variable,這段代碼是否易受攻擊?這是一個安全使用python eval()嗎?

dic={"one":1, 
     "nasty":attacker_controlled_nasty_variable, 
    } 
store=str(dict) 
... 
dic=eval(store) 
+0

由於攻擊者可以編輯你的Python源代碼,這個問題很愚蠢,不是嗎? – 2011-03-18 11:10:34

+1

誰說攻擊者在他的本地機器上運行代碼? – 2011-03-18 11:11:26

+0

@Tim Pietzcker:如果攻擊者沒有在本地機器上運行這個惡意變量,它是如何設置的? – 2011-03-18 11:15:12

回答

11

使用ast.literal_eval()而不是eval()

+0

+1這是非常好的 – rook 2011-03-18 12:16:25

6

是的。它可以用具有__repr__()方法的對象替換,該方法要麼有一個有效載荷本身,要麼返回一個字符串,當傳遞到eval()時可能不安全。

概念證明:

class MyClass(object): 
    def __repr__(self): 
    return 'os.system("format c:")' 

bad = [MyClass()] 
print str(bad) 
+1

你能舉個例子嗎?我試圖想象在他的例子中攻擊如何通過str()操作。 – payne 2011-03-18 11:13:01

+4

'class bad_repr(object): def __repr __(self): return'evil''(他不能這樣做,如果他的變量只能是一個字符串雖然)該類字符串字典將看起來像'{'討厭' :邪惡,'一':1}' - 所以'邪惡'沒有被引用,可能幾乎是任何Python代碼。 – ThiefMaster 2011-03-18 11:15:05

+0

很好的例子,謝謝。 – payne 2011-03-18 11:54:05

3

它是安全的,只要你可以肯定的是attacker_controlled_nasty_variable是從來沒有的對象,其中的攻擊者可以控制__repr__(或__str__),因爲他本來注入Python代碼。

但是,最好使用repr(dic)而不是str(dic),因爲只有repr預計會返回有效的python代碼。

另外 - 由@payne提到 - 使用更安全的替代ast.literal_eval()eval()

1

讓我們試一下:

>>> attacker_controlled_nasty_variable="`cat /etc/passwd`" 
>>> dic={"one":1, 
...  "nasty":attacker_controlled_nasty_variable, 
... } 
>>> store = repr(dic) 
>>> store 
"{'nasty': '`cat /etc/passwd`', 'one': 1}" 
>>> dic=eval(store) 
>>> dic 
{'nasty': '`cat /etc/passwd`', 'one': 1} 

>>> attacker_controlled_nasty_variable="'hello',}" 
>>> dic={"one":1, 
...  "nasty":attacker_controlled_nasty_variable, 
... } 
>>> repr(dic) 
'{\'nasty\': "\'hello\',}", \'one\': 1}' 
>>> eval(repr(dic)) 
{'nasty': "'hello',}", 'one': 1} 

你可能想嘗試更多案件,但根據經驗,它看起來像__repr__被正確引用內容。

+2

怎麼樣:類壞:def __repr __(self):os.system(「做壞東西)\ attacker_controlled_nasty_variable =壞()? – James 2011-03-18 11:20:58

+0

啊,你確實嘗試了額外的案例! – 2011-03-18 11:56:21