python自動化處理審計

2021-10-19 03:36:10 字數 3565 閱讀 1658

摘要

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

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

主要是在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_id res = cur.execute(sql)

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

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

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

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

(二)語法樹的表示-函式

函式的作用就不用多說了,django的view層基本都是以函式為單位的。下面來看乙個函式的語法樹,如圖1

我們簡單分析一下這個結構,首先是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注入問題的原型。

注入判斷的核心就在於找到危險函式,並且判斷其引數是可控的,找到危險函式這個只需要維護乙個危險函式列表即可,當在語法樹中發現了函式呼叫並且其名稱在危險列表中就可以標記出該行**,接下來的難點就在於跟蹤該函式的引數,預設認為該危險函式的外層函式的引數是可控的,那就只需要分析這個外層函式引數的傳遞過程即可。首先分析哪些情況下,從乙個引數賦值給另外乙個引數其值還是可控的,下面列舉了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"))。

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

參考文獻

selenium python自動化處理時間控制項

嘗試編寫12306 查詢餘票資訊的自動化指令碼時,碰到日期選擇的問題,此處做一下記錄 最初打算直接定位,但發現2017 09 30這一天實在沒什麼特點,雖然也可以根據父元素的特徵屬性層層定位,然後選擇其下的第多少個child元素,但是感覺會有問題,過一天之後,這個child元素就不是30號了,與初衷...

語言包自動化處理 一

利用php,js等語言便捷的字串處理能力,在整理老專案語言包時候,可以使用指令碼程式讀取檔案每行,匹配中文,然後以自己想要的形式輸出.中文 正規表示式匹配 cn pattern x x u 待檢測 字尾 suffix php ignore file keywords suffix js dir pa...

python自動化測試 異常處理

在自動化測試過程中,我們會遇到 在執行過程中可能存在錯誤,為了能夠更好的對這些異常情況進行處理,我們一般會使用try.except的方式來處理這些錯誤資訊,所以我總結了幾種異常的處理方式,能夠給你的自動化測試 錦上添花。異常的處理機制 1 如果 在執行時發生錯誤,直譯器會查詢相應的處理語句。2 如果...