競爭條件漏洞

思安網路安全工作室(SecAn_labs)

「競爭條件」發生在多個線程同時訪問同一個共享代碼、變數、文件等沒有進行鎖操作或者同步操作的場景中。

案例:

並發抽獎、提現、在上傳文件和安全檢查的間隙,攻擊者不斷的發起訪問請求訪問該文件,該文件一旦被執行,就會在伺服器上生成一個惡意的shell文件。

anquan.us/static/bugs/w 烏雲案例

上傳:

(代碼來源合天網安實驗室:http://www.hetianlab.com)

簡單解釋一下,將文件上傳到伺服器,然後檢測文件後綴名,如果不符合條件,就刪掉!

雖然php代碼在執行的時候是線性執行代碼的,但是執行的時候可以有多個線程,如果我們上傳一個php文件

內容如下:

(代碼來源合天網安實驗室:http://www.hetianlab.com)

在執行完move_uploaded_file之後,執行unlink之前,此時這個php文件是已經保存到了web伺服器上的,並且我們能夠訪問,所以只要我們在刪除該文件之前,訪問上傳的文件,就可以獲得一次執行php代碼的機會,如果上傳的php的功能是寫一句話到一個php文件,這樣我們在刪除之前訪問該文件,就會生成一個一句話木馬,就可以得到webshell。 所以我們使用多線程並發的訪問上傳的文件,總會有一次在上傳文件到刪除文件這個時間段內訪問到上傳的php文件,一旦我們成功訪問到了上傳的文件,那麼它就會向伺服器寫一個shell。

當然我們還要了解以下:

線程安全:當多個線程同時訪問時,保證實現沒有競爭條件。

條件安全:不同的線程可以同時訪問不同的對象,並且可以保護對共享數據的訪問免受競爭條件的影響。

不是線程安全的:不應該由不同的線程同時訪問代碼。

線程安全保證通常還包括設計步驟,以防止或限制不同形式的死鎖的風險,以及優化並發性能最大化的優化。但是,無法始終給出無死鎖保證,因為死鎖可能是由回調和違反獨立於庫本身的架構分層引起的。

下面我們討論兩種避免競爭條件來實現線程安全的方法。

第一類方法側重於避免共享狀態,包括:

重入

以這樣的方式編寫代碼,使其可以由線程部分執行,由同一線程重新執行或由另一個線程同時執行,並仍然正確地完成原始執行。這需要將狀態信息保存在每個執行的本地變數中,通常在堆棧上,而不是靜態或全局變數或其他非本地狀態。必須通過原子操作訪問所有非本地狀態,並且數據結構也必須是可重入的。

線程本地存儲

變數已本地化,因此每個線程都有自己的私有副本。這些變數在子常式和其他代碼邊界中保留其值,並且是線程安全的,因為它們對於每個線程是本地的,即使訪問它們的代碼可能由另一個線程同時執行。

不可變的物體

施工後無法更改物體的狀態。這意味著只共享只讀數據並獲得固有的線程安全性。然後可以以這樣的方式實現可變(非常量)操作,即它們創建新對象而不是修改現有對象。這種方法是函數式編程的特徵,也可用於Java,C#和Python中的字元串實現。[7]

第二類方法與同步相關,用於無法避免共享狀態的情況:

相互排斥

對共享數據的訪問序列化使用機制,確保只有一個線程讀取或隨時寫入到共享的數據。合併互斥需要經過深思熟慮,因為不當使用會導致諸如死鎖,活鎖和資源匱乏等副作用。

原子操作

通過使用不能被其他線程中斷的原子操作來訪問共享數據。這通常需要使用特殊的機器語言指令,這些指令可能在運行時庫中可用。由於操作是原子操作,因此無論其他線程如何訪問它,共享數據始終保持有效狀態。原子操作構成了許多線程鎖定機制的基礎,並用於實現互斥原語。

參考文章:en.wikipedia.org/wiki/T hetianlab.com


推薦閱讀:
查看原文 >>
相关文章