抵抗MCU故障注入攻擊的軟體防護措施

作者 : 張紋碩,新唐科技(Nuvoton)微控制器產品系統設計二部經理

對於微控制器產品而言,「故障注入」(Fault Injection)是一個簡單、有效又低成本的攻擊,只是攻擊仍然必須能夠精確的定位安全設定、密鑰載入、加密運算的關鍵時序。本文介紹常見的故障注入攻擊方式及其原理,並提出在不增加硬體成本下,如何以最具效益的軟體防護方法來抵擋這類攻擊。

微控制器產品在設計之初,就會設定相應的產品規格以規範產品的執行條件,確保產品可以完成預設的任務。然而,若執行條件可不完全依照產品規格的情況下,就有可能會讓系統無法如預期的方式運作,這樣的特性經常被惡意攻擊者用以做為尋找系統漏洞的工具,藉此繞過預設的安全機制或取得受保護的資料,即所謂的故障注入(Fault Injection)攻擊

這方法之所以被攻擊者經常使用,其根本原因不外乎相關攻擊設備簡單、容易取得且成本低廉,並且其攻擊具有一定的效果。本篇文章將介紹常見的故障注入攻擊方式及其原理,並提出在不增加硬體成本下,以最具效益的軟體防護方法來抵擋這類攻擊。

Fault Injection造成的結果

當產品的執行條件超出了原本預設的規範,就會使產品的運作出錯;如果能夠限縮這樣的執行條件出現在特定的時間,且只持續一段極短的時間,便足以能夠讓產品在執行特定指令的時候出錯,而其他指令又能夠正常的執行。

也就是說,透過Fault Injection,可以讓特定指令的執行失效,例如讓加密硬體系統錯誤的執行讀取密鑰的任務,使其載入空白密鑰(zero key)來加密資料,如此一來只要再使用空白密鑰,就能將密文還原成明文。

Figure 1. Skip Instruction Attack

圖1:Skip Instruction Attack。

Figure 2. Zero Key Attack

 

圖2:Zero Key Attack。

常見且低成本的Fault Injection方式

Fault Injection攻擊手段通常可區分為侵入式攻擊和非侵入式攻擊。侵入式攻擊影響的是產品功能永久性的故障和異常,這手段通常是透過高精密的儀器對產品內部電路或資料做修改和破壞,因此所需的硬體成本和技術門檻都很高。

非侵入式攻擊則是在產品運作中注入攻擊,使其短暫的影響產品當下運作行為,造成異常或功能故障;這類攻擊手段常見的方式為攻擊產品輸入電壓和頻率。因為這樣的攻擊是針對電壓及頻率且持續時間短暫,我們稱之為Voltage Glitch攻擊與Clock Glitch攻擊。這兩種攻擊方式只需具備可以產生對voltage和clock訊號干擾的硬體設備即可達成,因此實現所需成本比侵入式攻擊低上許多,也更容易取得和實現。

Figure 3. Voltage Glitch Attack

圖3:Voltage Glitch攻擊。

因為Voltage Glitch和Clock Glitch的攻擊都可以造成產品執行時,跳過某些指令或是影響某些操作的輸出結果,本章節接下來將以Voltage Glitch攻擊範例來說明常見的Fault Injection影響。

Voltage Glitch對TrustZone配置設定的攻擊

在具備TrustZone技術的微控制器產品中,都會具有Secure Attribution Unit (SAU)控制單元用來將微控制器的所有資源,設置為Secure和Non-secure區域,目的是為了透過隔離Secure與Non-secure區域的方式,來保護Secure區域中的資源。

在針對TrustZone技術的攻擊中,攻擊者會企圖透過讓SAU的設置無效化,來瓦解這樣的隔離保護機制,此攻擊主要是在系統程序配置SAU屬性時進行Voltage Glitch的攻擊,讓系統執行指令出現錯誤,造成SAU配置和系統原先規劃的不一致,以期在這當中尋找到可利用的漏洞。

我們以試圖攻擊新唐M2351微控制器在配置SAU過程中設定Non-secure區域為例,整個M2351的快閃記憶體容量大小為512KB,如果規劃其中的Secure空間大小為256KB,那麼剩下的256KB空間就屬於Non-secure,其在記憶體空間中的地址如4

Figure 4. TrustZone® Secure, Non-secure Partition。

圖4:TrustZone Secure與Non-secure區域。

在這樣的記憶體配置下,Secure程式碼與Non-secure程式碼被遠遠區隔開來,實現了TrustZone的硬體隔離,而想要進行這樣的隔離配置,實際上所需要的設置有三個部分,一個是SAU的配置設定,一個是Flash Non-secure Boundary的設定,最後則是編譯程式碼需要的設置。

SAU的配置主要在指定Non-secure區域的起始地址與結束地址,這裡設定的範圍是由0x10040000到0x1007FFFF,至於其他未定義的區域,則預設為Secure區域。Flash Non-secure Boundary的設定,是指快閃記憶體空間中由哪裡開始要劃分給Non-secure使用,在這裡其設定為0x40000,表示Flash後面的256KB將劃歸給Non-secure使用,其餘則是給Secure使用。Flash Non-secure Boundary的設定,是一出廠就設置好的,不會再改動 。

由圖3可知,Secure區域跟Non-secure區域是分開的,因此在編譯時,Secure程式碼與Non-secure程式碼的RO Base就必定不同,也就是Secure的RO Base必須落在0x0到0x3FFFF的範圍,而Non-secure的RO Base則是要落在0x10040000到0x1007FFFF的範圍內,這裡我們設定Secure RO Base為0x0,Non-secure RO base為0x10040000。

上述的三種設置,其中只有SAU的設置,會在系統運作中進行,因而有機會被Voltage Glitch攻擊,如果系統在寫入SAU區域設置時,遭到攻擊,就有可能造成指令執行失敗,因而使得SAU的設置不正確,也就是設置SAU Non-secure Region的起始位址 0x10040000這行指令執行失敗,這將造成SAU Non-secure Region的實際設定為0x0,則系統的記憶體規劃將變成如5所示。

Figure 5. Secure, Non-secure Partition after Attack SAU Setting.

圖5:攻擊SAU配置後的Secure與Non-secure分區。

注意在Non-secure Region起始地址被竄改成0x0的情況下,0x0至0x0003_FFFF記憶體的屬性並不會真的被改成Non-secure,這是因為另一個固定的屬性設置單元Implementation Defined Attribution Unit (IDAU)所造成的影響。

在SAU於0x0到0x0003_FFFF設置為Non-secure的情況下,最終的0x0到0x0003_FFFF的屬性將依照較嚴格的IDAU設置,這表示即使成功地攻擊SAU,讓Non-secure起始地址設定為0x0,仍然無法讓原來的Secure區域改變為Non-secure區域,而是變成IDAU設置的Non-secure callable區域,而Non-secure callable區域,其本質上仍是屬於Secure區域的一部分。

另外,雖然成功攻擊SAU後,會讓大部分的Secure區域,轉變為Non-secure callable區域,但是因為這些區域缺乏SG (Secure Gateway)指令的緣故,Non-secure code是無法任意用Non-secure callable方式呼叫這區域的指令的。

值得注意的是,M2351微控制器SAU最多總共有8個區域可以設定,可是這8個區域的範圍是不允許重疊的。重疊區域的設定將導致該重疊區域強制為Secure屬性,也就是說,若是原來的設定中,本來就有劃定0x3F000至0x3FFFF為Non-secure callable區域,而因為此區域跟被攻擊後的SAU區域0x0到0x1007FFFF重疊了,將使得0x3F000至0x3FFFF這個區域的設定直接成為Secure區域,這將造成所有的Non-secure callable API無法被Non-secure code呼叫。

因此,單純的攻擊SAU設置無法為Non-secure code取得額外的權限,甚至會失去原本可以呼叫Non-secure callable API權限,所以即使成功的攻擊了SAU的設置,也並無法形成一個有效的攻擊,不會有任何Secure區域資訊的洩漏或被Non-secure code取得任何的Secure權限。

Voltage Glitch對AES加密的攻擊

此攻擊方式主要是在程式碼執行AES加密相關處理時,使用Voltage Glitch攻擊其運作,使其產生錯誤的密文。執行AES加密的基本流程如圖6所示,最終會產生密文。

Figure 6. AES Encrypt Procedure.

圖6:AES加密流程。

例如在輸入AES Key操作時被Voltage Glitch攻擊,可能出現輸入密鑰的動作被忽略或是輸入錯誤的密鑰值。如果是輸入密鑰的動作因為攻擊而沒有實際上的密鑰值輸入,那麼接下來的加密過程,就會直接使用其暫存器內原來的值,通常這會是一組全部為0的密鑰值,所以對於最後加密過後的密文,只要使用全0的密鑰來解密,就可以還原出正確的原文了。

Figure 7. Zero Key Fault Injection Attack.

圖7:Zero Key故障注入攻擊。

另一種狀況是在原文已知道情況下,攻擊者利用Voltage Glitch造成輸入錯誤的密鑰,然後加密過後,得到對應的密文,以此重複多次,攻擊者就可以根據原文、正確密鑰加密後的密文、各種錯誤密鑰加密後的密文,經過Differential Fault Analysis (DFA) 差分故障分析方法,就可以還原出正確的密鑰。

Figure 8. Use Fault Injection to get N Encrypted Text for DFA.

圖8:以故障注入取得加密文以進行DFA。

如何透過軟體來防護這些攻擊

由上述幾個採用Voltage Glitch攻擊的例子可以發現,攻擊者需要在正確的時間點進行Fault Injection攻擊,才有一些機會得到其想要達成的目的;因此讓攻擊者無法輕易的了解系統內部運作的時序,將會是一個有效的防護。最簡單的方法就是建立不可預測的系統時序和處理流程, 讓攻擊者不容易找到合適的攻擊時間點,也不容易持續攻擊到同一個關鍵運作點,而這可以透過隨機延遲和隨機變化處理流程的順序來實現。

Figure 9. Add Random Delay
圖9:添加隨機延遲。

Figure 10. Change Execution Procedure Randomly

圖10:隨機變化處理流程。

但是只要無法擋住攻擊的來源,攻擊者總會達成他們所要的攻擊目的。如果軟體可以偵測到系統可能被攻擊,就可透過對應的處理程序將攻擊損害程度降到最低。接下來將依據前面提到的故障攻擊範例來說明軟體解決方案,並實現可偵測出系統是否被攻擊以及對應的處理。

關鍵設置攻擊防護

在先前所舉TrustZone設定攻擊的例子中,我們知道攻擊者企圖利用跳過SAU配置指令來影響Secure與Non-secure區域範圍的設置,企圖擴大Non-secure區域範圍,藉此取得存取Secure資源的機會。雖然在之前的描述中提到,因為Secure與Non-secure範圍設置,除了SAU,還需要搭配IDAU,所以單純的攻擊SAU,並無法取得有效的權限,但這裡我們仍然為這樣的攻擊提出對應的策略,讓攻擊者連SAU的設置都無法攻擊成功。

這個防護最主要原理,是偵測異常的SAU配置並做復原SAU配置的處理,讓針對SAU設置的攻擊無效化。首先要偵測出異常的SAU設置,可針對所有的SAU設置進行冗餘檢查。

  • 步驟1:記錄有效的系統SAU設定值;系統SAU設定值已預先被定義在h內,需要將這些設定值預先記錄下來,可供後續步驟的使用。
  • 步驟2:計算出有效的系統SAU設定值總和;將有效的SAU相關設定例如RBAR、RLAR和CTRL等設定值全部加起來做運算,會得到一個Checksum值。
  • 步驟3:將有效的SAU設定值寫入對應的SAU region;將h內定義有效的SAU設定值和屬性寫入各自的SAU區域內。
  • 步驟4:讀出全部有被寫入SAU region的設定值並做加總運算。
  • 步驟5:判斷寫入SAU是否正確;在此比對步驟2和4計算出來的總和值是否一致,便可得知在寫SAU設定值是否因遭到攻擊而產生異常的設定結果。

上述步驟1、2、4、5是針對偵測攻擊所加的步驟,而步驟3則是原來沒有加防護程式碼時的SAU設置。如下圖所示:

Figure 11. Fault Injection Countermeasure Flow.

圖11:故障注入對策流程。

接下來,偵測到錯誤後必須要讓系統能夠自行回復,所以需要重複步驟3再次寫入SAU設定。

防護Zero Key攻擊與AES加密攻擊

Zero Key攻擊與SAU設置攻擊類似,都是讓軟體寫入動作失效,也就是讓系統無法寫入正確地密鑰到運算單元中,因而使用預設的空白數據,據此產生使用空白密鑰的效果。對AES加密運算的攻擊,目的是影響密鑰的載入使其加密出錯誤的密文,然後攻擊者透過分析大量不同的錯誤密文和正確密文的關係,透過DFA分析方法推導出系統內使用的加密密鑰後,再解密密文就可得到明文數據。

因此AES加密攻擊的防護重點,是讓軟體可以知道AES加密運算過中有受到攻擊,避免使用到空白或錯誤的密鑰,並且不能將被攻擊後產生的密文回報給攻擊者,使其有機會進行DFA分析。攻擊者在攻擊密鑰的載入前需要先精確的定位到特定的時間點,因為配置密鑰與輸入明文的程序是可以互換的,軟體可以在這個部分進行隨機的次序調換,如此可以增加攻擊者定位密鑰載入時間點的難度。

Figure 12. Random change the plaintext, Key input procedure.

圖12:隨機變換密鑰程序與明文輸入次序。

由於對AES運算的攻擊,重點在於使其密鑰的載入出錯,無論是Zero Key或是大量錯誤的Key,所以只要在載入密鑰之後,再針對暫存器中的密鑰做檢查,即可保障密鑰輸入的正確性,而且如果運算中有使用到DMA的話,DMA的Source、Destination與Transfer Count都應該也納入檢查。

而加密運算使用密鑰時的攻擊,則可在加密完成後直接把密文用同一把密鑰解密,並與原來的明文做比對,即可驗證在加密過程中是否有任何出錯。整個防護對策流程如圖13所示。

Figure 13. AES Key Fault Injection Countermeasure Flow.

圖13:AES密鑰故障注入攻擊對策防護流程。

總結

對於微控制器產品而言,Fault Injection確實是一個簡單、有效又低成本的攻擊,只是要能夠完整的取得有用的成果,攻擊仍然必須能夠精確的定位安全設定、密鑰載入、加密運算的關鍵時序,這對並不熟悉微控制器內部運作的程序的惡意攻擊已屬不易,而且軟體也可以利用隨機的延遲與程序交錯等方式,更加深定位的困難度。

即使攻擊者精確找到關鍵位置,只要軟體多一道自我校驗程序,就可以讓攻擊的難度急遽增加,因此對於系統中的關鍵設置、密鑰載入部分,增加相對應的防護會是一個很值得做的事。

(本文同步刊登於《電子工程專輯》雜誌2020年7月號)

 

發表評論