Python自動化審計及實現

來源:互聯網
上載者:User

標籤:

Python語言由於其簡單,快速,庫豐富的特點在國內使用的越來越廣泛,但是一些不好的用法卻帶來了嚴重的安全問題,本文從Python源碼入手,分析其文法樹,跟蹤資料流來判斷是否存在注入點。

0x01 引言

Python注入問題是說使用者可以控制輸入,導致系統執行一些危險的操作。它是Python中比較常見的安全問題,特別是把python作為web應用程式層的時候這個問題就更加突出,它包括代碼注入,OS命令注入,sql注入,任意檔案下載等。

0x02 注入的情境

主要是在web應用情境中,使用者可直接控制輸入參數,並且程式未做任何參數判斷或者處理,直接就進入了危險函數中,導致執行一些危險的操作。主要的注入類型有:

(一)OS命令注入

主要是程式中通過Python的OS介面執行系統命令,常見的危險函數有

os.system,os.popen,commands.getoutput,commands.getstatusoutput,subprocess

等一些介面。例如:def myserve(request,fullname):os.system(’sudo rm -f %s’%fullname),fullname是使用者可控的,惡意使用者只需利用shell的拼接符;就可以完成一次很好的攻擊。

(二)代碼注入

是說在注入點可以執行一段代碼,這個一般是由python的序列話函數eval導致的,例如:def eval_test(request,login):login = eval(login),如果惡意使用者從外界傳入import(’os’).system(’rm /tmp -fr’)就可以清空tmp目錄。

(三)Sql注入

在一般的Python web架構中都對sql注入做了防護,但是千萬別認為就沒有注入風險,使用不當也會導致sql注入。例如:

def getUsers(user_id):sql = ‘select * from auth_user where id =%s’%user_idres = cur.execute(sql)

(四)任意檔案下載

程式員編寫了一個下載報表或者任務的功能,如果沒有控制好參數就會導致任意檔案下載,例如:def export_task(request,filename):return HttpResponse(fullname)

0x03 判斷原理

從以上四種情況來看,都有一個共同點,那就是危險函數中使用了可控參數,如system函數中使用到的(’sudo rm -f %s’%fullname),如eval中使用到的login參數,如execute函數中使用到的user_id參數,如HttpResponse中使用到的fullname參數,這些參數直接從函數中傳進來,或者經過簡單的編碼,截斷等處理直接進入危險函數,導致了以上危險行為。如果在執行危險函數前對這些可控參數進行一定判斷,如必須是數字,路徑必須存在,去掉某些特殊符號等則避免了注入問題。 有了這個基礎理論,這個參數資料在傳遞的過程中到底有沒有改變?怎麼順利的跟蹤可控參數呢?接下來分析Python的文法樹。

0x04 Python文法樹

很顯然,在參數不停傳遞過程中,普通的Regex已經無能為力了。這個時候就可以體現Python庫豐富的特點。Python官方庫中就提供了強大的Python文法分析模組ast。我們可以利用根據ast最佳化後的PySonar模組,PySonar相對於ast模組而言有效能上的提升,另外是以Python的dict來表示的。

(一)文法樹的表示-檔案

一個檔案中可以有函數,類,它是模組的組成單位。大體結構如下:{"body":[{},{}],"filename":"test.py","type":"module"},這是檔案test.py得到的文法樹結構,body裡麵包含兩個dict,實際裡面會存放函數,類,全域變數或者匯入等,它是遞迴嵌套的,type欄位表明類型,在這裡是模組,filename則是它的檔案名稱。

(二)文法樹的表示-函數

函數的作用就不用多說了,django的view層基本都是以函數為單位的。下面來看一個函數的文法樹,

我們簡單分析一下這個結構,首先是type,這裡是FunctionDef,說明這個結構體是一個函數,_fields中的name,args,body,decorator_list等是函數的基本組成單位。name是函數名稱,上述函數名為is_this_subdomain;args是函數的參數,它包含普通參數args,預設參數kwarg;lineno是標明該語句所在的檔案的行數;decorator_list則是函數的修飾器,上述為空白。

(三)文法樹的表示-類

在類的文法樹中,包含body,decorator_list,lineno,name,base等欄位type是ClassDef,表明該結構為class,body中則包含著函數的結構體,base則是繼承的父類。

(四)文法樹的表示-樣本

接下來我們將以一個if結構片段代碼作為樣本,來解釋Python源碼到其文法樹的對應關係。片段代碼:if type not in ["RSAS", "BVS"]:return HttpResponse("2"),得到的文法樹2:

在這個文法樹結構中,body裡包含著if結構中的語句return HttpResponse("2"),type為Compare表示該結構體為判斷語句,left表示左值即源碼中的type,test結構體中則是用來進行if判斷,test中的ops對應著源碼中的not in,表示比較判斷,comparators則是被比較的元素。這樣源碼就和Python文法樹一一對應起來,有了這些一一對應的基礎,就有了判斷Python注入問題的原型。

0x05 注入判斷的實現

注入判斷的核心就在於找到危險函數,並且判斷其參數是可控的,找到危險函數這個只需要維護一個危險函數列表即可,當在文法樹中發現了函數調用並且其名稱在危險列表中就可以標記出該行代碼,接下來的痛點就在於跟蹤該函數的參數,預設認為該危險函數的外層函數的參數是可控的,那就只需要分析這個外層函數參數的傳遞過程即可。首先分析哪些情況下,從一個參數賦值給另外一個參數其值還是可控的,下面列舉了5中基本情況:

(1)屬性取值:對一個變數取屬性,比如request的GET,POST,FILES屬性,屬性的屬性還是可控的,但是request的其他欄位如META,user,session,url則得排查開外。 (2)字串拼接:被拼接的字串中包含可控參數,則認為賦值後的值也是可控的,需要考慮好各種拼接情況,如使用+,%等進行拼接。 (3)分區符取值:一般認為分區後的值也是可控的。 (4)列表解析式,如果列表解析式基於某個可控因子進行迭代,則認為賦值後的列表也是可控的。 (5)簡單的函數處理:a,處理函數是字串操作函數(str,unicode,strip,encode等);b,簡單的未過濾函數,也就是說這個函數的返回參數是可控的。

對外層函數中的所有程式碼進行分析,判斷是否是賦實值型別,如果賦實值型別的操作屬於以上五種情況中任意一種,則將該賦值後的值放入可變參數列表中,具體的流程3:

另外在分析的過程中還得排除下列情況,提前結束分析。第一種情況是 if語句中有os.path.exitst,isdigit帶可控參數並且含有return語句,如(if not os.path.isdir(parentPath):return None);第二種情況是將可控參數鎖定在某個定值範圍並直接返回的,如(if type not in ["R", "B"]:return HttpResponse("2"))。

0x06 結束語

對Python源碼實現注入問題的自動審查,大大降低了人為的不可控性,使代碼暴露出來的漏洞更少。當然目前來說這個模組還是有一定局限性,對類的處理不夠充分,沒有分析匯入的函數對屬性的取值也不夠細分等問題。

 

 

來源:51CTO

Python自動化審計及實現

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.