# Move語言中的整數溢出漏洞分析## 前言在對Aptos Moveevm進行深入研究後,我們發現了一個新的整數溢出漏洞。這個漏洞的觸發過程相對更加有趣,下面我們將對這個漏洞進行深入分析,並介紹一些Move語言的背景知識。通過本文的講解,相信你會對Move語言有更深入的理解。Move語言在執行字節碼之前會驗證代碼單元。驗證過程分爲4個步驟,而這個漏洞出現在reference_safety步驟中。## Move中的引用安全Move語言支持兩種類型的引用:不可變引用(&)和可變引用(&mut)。不可變引用用於從結構中讀取數據,而可變引用用於修改數據。使用適當的引用類型有助於維護安全性並識別讀取模塊。在Move的引用安全模塊中,會以函數爲單位,掃描函數中基本塊的字節碼指令,以驗證所有引用操作是否合法。驗證引用安全性的主要流程包括執行基本塊、生成後置狀態、合並前後狀態等步驟。## 漏洞分析漏洞出現在引用安全模塊的join_函數中。當函數參數長度和局部變量長度之和大於256時,由於使用u8類型表示local變量,會導致整數溢出。雖然Move有校驗locals個數的過程,但在check bounds模塊中只校驗了locals,並未包括參數長度。開發人員似乎意識到需要檢查參數和本地值的總和,但代碼中只校驗了本地變量的個數。## 從整數溢出到DoS攻擊利用這個整數溢出漏洞,攻擊者可以制造一個循環代碼塊,改變塊的狀態。當再次執行execute_block函數時,如果指令需要訪問的索引在新的AbstractState locals map中不存在,將導致DoS攻擊。在reference safety模塊中,MoveLoc/CopyLoc/FreeRef等操作碼可能會觸發這種情況。例如,在copy_loc函數中,如果LocalIndex不存在會導致panic,進而導致整個節點崩潰。## 漏洞復現可以通過以下PoC代碼在git中重現這個漏洞:movepublic fun test(a: u64, b: u64, c: u64, d: u64) { let x = 0; loop { if (x == 1) { break }; x = x + 1; }}觸發DoS的步驟如下:1. 第一次執行execute_block函數,設置parameters和locals均爲SignatureIndex(0),導致num_locals爲264。執行join_函數後,新的locals map長度變爲8。2. 第二次執行execute_block函數時,執行move代碼第一條指令copyloc(57)。由於此時locals只有長度8,offset 57不存在,導致get(57).unwrap()函數返回None,最終引發panic。## 總結這個漏洞表明沒有絕對安全的代碼。雖然Move語言在代碼執行前進行了靜態校驗,但仍可能被溢出漏洞繞過。這再次強調了代碼審計的重要性。對於Move語言,我們建議在運行時增加更多的檢查代碼,以防止意外情況發生。目前Move主要在verify階段進行安全檢查,但一旦驗證被繞過,運行階段缺乏足夠的安全加固可能導致更嚴重的問題。作爲Move語言安全研究的領導者,我們將繼續深入研究Move的安全問題,並在後續分享更多發現。
Move語言整數溢出漏洞分析:從引用安全到DoS攻擊
Move語言中的整數溢出漏洞分析
前言
在對Aptos Moveevm進行深入研究後,我們發現了一個新的整數溢出漏洞。這個漏洞的觸發過程相對更加有趣,下面我們將對這個漏洞進行深入分析,並介紹一些Move語言的背景知識。通過本文的講解,相信你會對Move語言有更深入的理解。
Move語言在執行字節碼之前會驗證代碼單元。驗證過程分爲4個步驟,而這個漏洞出現在reference_safety步驟中。
Move中的引用安全
Move語言支持兩種類型的引用:不可變引用(&)和可變引用(&mut)。不可變引用用於從結構中讀取數據,而可變引用用於修改數據。使用適當的引用類型有助於維護安全性並識別讀取模塊。
在Move的引用安全模塊中,會以函數爲單位,掃描函數中基本塊的字節碼指令,以驗證所有引用操作是否合法。驗證引用安全性的主要流程包括執行基本塊、生成後置狀態、合並前後狀態等步驟。
漏洞分析
漏洞出現在引用安全模塊的join_函數中。當函數參數長度和局部變量長度之和大於256時,由於使用u8類型表示local變量,會導致整數溢出。
雖然Move有校驗locals個數的過程,但在check bounds模塊中只校驗了locals,並未包括參數長度。開發人員似乎意識到需要檢查參數和本地值的總和,但代碼中只校驗了本地變量的個數。
從整數溢出到DoS攻擊
利用這個整數溢出漏洞,攻擊者可以制造一個循環代碼塊,改變塊的狀態。當再次執行execute_block函數時,如果指令需要訪問的索引在新的AbstractState locals map中不存在,將導致DoS攻擊。
在reference safety模塊中,MoveLoc/CopyLoc/FreeRef等操作碼可能會觸發這種情況。例如,在copy_loc函數中,如果LocalIndex不存在會導致panic,進而導致整個節點崩潰。
漏洞復現
可以通過以下PoC代碼在git中重現這個漏洞:
move public fun test(a: u64, b: u64, c: u64, d: u64) { let x = 0; loop { if (x == 1) { break }; x = x + 1; } }
觸發DoS的步驟如下:
第一次執行execute_block函數,設置parameters和locals均爲SignatureIndex(0),導致num_locals爲264。執行join_函數後,新的locals map長度變爲8。
第二次執行execute_block函數時,執行move代碼第一條指令copyloc(57)。由於此時locals只有長度8,offset 57不存在,導致get(57).unwrap()函數返回None,最終引發panic。
總結
這個漏洞表明沒有絕對安全的代碼。雖然Move語言在代碼執行前進行了靜態校驗,但仍可能被溢出漏洞繞過。這再次強調了代碼審計的重要性。
對於Move語言,我們建議在運行時增加更多的檢查代碼,以防止意外情況發生。目前Move主要在verify階段進行安全檢查,但一旦驗證被繞過,運行階段缺乏足夠的安全加固可能導致更嚴重的問題。
作爲Move語言安全研究的領導者,我們將繼續深入研究Move的安全問題,並在後續分享更多發現。