こんにちは。技術部の中尾です。
奇跡的?に8月はアサインされた案件が少なかったので、夏休みの自由研究として以前からやってみたかった Voltage Fault Injectionをやってみました。 この攻撃は、サイドチャンネル攻撃の一種で、プロセッサの電源にグリッチを印加する、すなわち一瞬だけ電圧を下げることで誤動作させるというものです。
例えば、あるスマートキーに以下のようなCプログラムが実装されているとしましょう。
result = (input_key == correct_key);
if(result)
unlock();
else
lock()
1行目で、入力された鍵を検証し、2行目で正しければ解錠するという条件分岐があります。 攻撃者は、誤った鍵を入力し、2行目の条件分岐を実行されるタイミングでグリッチを入力します。この時、間違った鍵が入力されている(resultがfalse)にもかかわらず、unlock()が実行されてしまうことがあります。
このように、グリッチによって誤作動する事を利用した攻撃が、Voltage Fault Injection Attackです。
正直、これは研究室レベルの話でだと思っていたのですが、近年、Nintendo WiiU[1]のSecure Bootのバイパス手法として実際に使われたことが報告されています。
攻撃対象
今回の攻撃対象は、Atmel社のマイコンATMega328のArduino互換ボードを使用しました。クロックは16MHzです。基板とパーツ合わせて500円くらいでした。
マイコンで動作するプログラムはこんな感じにしました。
volatile bool flag = true;
volatile bool once = true;
volatile const unsigned WAIT = 0xEFFF;
snip...
#pragma GCC optimize ("O0")
void loop() {
volatile unsigned k;
volatile unsigned i;
while(flag){
k = 0;
Serial.print("Loop");
for(i=0; i<WAIT; i++)
k++;
flag = (k==WAIT);
}
if(once)
Serial.print("\n\rSuccess!!");
once = false;
}
このプログラムは、Loopという文字列を無限ループで出力するプログラムです。グリッチが印加されることで、Voltage Fault Injectionが成功すると、変数kが想定外の値になり、無限ループを抜け、"Success!"という文字列を出力します。
この攻撃は、とにかくタイミングが命です。攻撃が有効な時間をとにかく広げるような作りにしています。また、コンパイラによる最適化を抑制するpragmaも追加しています。
Glitcher
CPUに印加する電圧を一瞬下げるための装置(Glitcher)を作成しました。というとなんかすごそうですが、実際は転がっていたZybo Z7というFPGAボードで、グリッチの素になるパルスを作って、トランジスタで電圧変換&電流増幅しただけです。
Zybo Z7には、4つのスライドスイッチ、6つのプッシュボタンが使えるので、プッシュボタンを押した時にGlitchが出るようにしています。 また、スライドスイッチその組み合わせでグリッチの長さを変えられるようにしてあります。
Glitcherの出力波形を下図に示します。 ブレットボードにそのへんにあった部品で適当に電圧変換&電流増幅回路を実装したので、あまりきれいな波形ではないですが、200ns程度のGlitchはできているようです。(パルス回路はむずかしい...)
攻撃開始!
それでは、実際に攻撃してみます。プログラムが実行されると、シリアルポートに、Loopと表示され続けます。この時にGlitcherのプッシュボタンを連打すると...
攻撃成功!
上の写真は、Glitcherの出力をCPUボードのVcc端子に接続して、Glitcherの出力をオシロスコープでモニターしながら、グリッチを入力した時のものです。Success!という文字列が出力されたことから、グリッチにより無限ループを抜け、Voltage Fault Injection攻撃が成功したことがわかります。
おわりに
この攻撃手法をはじめて聞いた時、ハードウェアの電源ラインにアクセスして、大量の Try & Error をやらなきゃいけない攻撃手法なんて、実際の攻撃にはつかえないと正直なところ思っていました。
しかし、IoTデバイスが攻撃対象となった場合、攻撃対象のハードウェアは攻撃者の手の内にあります。すなわち、これまで使えそうもなかった攻撃が現実的なものになりうるということでもあります。
今回はシンプルなCPUボードと、攻撃が簡単なファームウェアを用いた検証でした。また時間を見つけて、次はLinuxが動いているARMボードといった、もう少しリアリティのあるものを対象にしたいと考えています。