難読化とは、プログラムの動きはそのままに、コードを読みにくくする技術です。第三者が中身を追いにくくなり、まねや書き換え、不正に使うことの手間を増やせます。
ただし、難読化だけで安全になるわけではありません。時間をかけて調べれば中身を読まれることはあり、脆弱性の修正や認可、監視の代わりにもなりません。
難読化が使われるねらいは、大きく分けて次の3つです。
ねらいは「攻撃を完全に止める」ことではなく、調べる手間を増やして割に合わなくすることです。
難読化は古くからあり、ゲームや商用ソフトのコピー対策や改造をしにくくする対策で使われてきました。Webが広がり、クライアント側で配るJavaScriptなどのコードが広く見られるようになったことで、難読化はより身近な技術になりました。
今は、ただ読みにくくするだけでなく、解析用のツールが追いにくい形にしたり、改ざんの検知やデバッグ妨害と組み合わせたりして、何段かに分けて守る使い方へ広がっています。
いまのソフトウェアは、API連携、サードパーティSDK、モバイルアプリ、IoT、Webフロントエンドなど配り方が多く、攻撃者が実物のコードを手に入れやすい場面が増えています。とくにクライアント側のコードは、配った時点で見られることを前提に考える必要があります。
そのため、難読化は、見られても調べにくい状態を作るための一つの手として使われます。ただし、クライアントに置いた鍵やログイン情報は、いつか読まれるおそれがあります。難読化だけに頼らず、サーバー側の設計や認可、監視と合わせて考えることが大切です。
難読化にはいくつもの手法があります。ここでは、よく挙げられる例と、それぞれの効き方、気をつけたい点を見ていきます。
名前を分かりにくくする方法は、変数名、関数名、クラス名などを意味のない短い名前へ変えるやり方です。人がコードの意図を読み取りにくくなりますが、動きやアルゴリズムそのものは変わりません。
Web開発では、JavaScriptのminify(圧縮)と合わせて使われることも多く、入りやすい手法です。ただし、実行中の動きまで追われると中身を推測されることがあるため、これだけで強い守りになるわけではありません。
文字列を隠す方法は、コードに入りやすい文字列(URL、エラー文、分岐に使う値など)を見えにくくするやり方です。暗号化、エンコード、分割してつなぎ直す方法などがあります。
ただし、クライアント側で元に戻して使う以上、実行中に値を取り出されることがあります。文字列を隠す方法は、表に出る時期を遅らせる助けにはなりますが、鍵やトークンの置き場には向きません。そうした情報はサーバー側で持つのが原則です。
処理順を追いにくくする方法は、条件分かれ目やループ、関数呼び出しの並びを分かりにくくして、プログラムの進み方や意図をつかみにくくするやり方です。意味の薄い分岐を足す、switch文の形を変える、例外への対応をからめる、といった方法が使われます。
その一方で、複雑になりすぎると性能や保守へ影響が出ることがあり、どこまで使うかを決めておく必要があります。
同じ働きを別の書き方に変える方法は、同じ結果になる別の表現へ置き換えて、決まった形を探す解析をしにくくするやり方です。単純な計算や比較をいくつかの段に分けたり、同じ結果になる演算へ置き換えたりして、中身をつかみにくくします。
この方法の効き方はコードの性質で変わります。何にでも同じように効くわけではないため、大事な部分にしぼって使うのが一般的です。
いくつかの手法を重ねる方法は、別々の難読化を組み合わせて、調べる手間をさらに増やす考え方です。一つだけでは破られやすくても、重ねることで読むまでの時間を延ばせる場合があります。
ただし、強くしすぎると、開発、検証、障害時の対応が難しくなり、更新のたびに負担が増えることがあります。何を守りたいのかをはっきりさせ、その部分にしぼって使うのが現実的です。
難読化は、防御をそれだけで成り立たせるものではありません。攻撃の難しさと手間を上げるための補助として効きます。
とくに、秘密の情報をクライアントに置き、難読化で隠そうとする設計は危険です。時間をかけて調べられれば、いずれ読まれるおそれがあります。
難読化を使うときは、次のような見方が大切です。
難読化は、攻撃者がコードの形や処理を読み取り、悪用まで進むまでの時間を延ばす助けになります。とくにクライアント側へ配るコードでは、読むことを前提にした攻撃が起きやすく、難読化が抑止の手段として使われます。
ただし、難読化は脆弱性を直すものではありません。弱点はパッチや設計の見直しで消し、難読化は調べる手間を増やす補助として使うのが安全です。
リバースエンジニアリングは、配布したソースやバイナリから中の仕様を推測し、元の作りをたどる行為です。合法な調査から不正な改造まで、使われ方には幅があります。難読化はこの手順を追いにくくし、まねや改造、弱点探しの効率を下げる助けが見込めます。
難読化によって、攻撃者が脆弱性を見つけるまでの手間が増えることはあります。ただし、弱点そのものが残っていれば、いずれ悪用される可能性は残ります。難読化はリスクを下げる助けではあっても、弱点への対策の代わりではありません。
不正アクセスを防ぐ中心は、認可、入力の確認、秘密の保管、監視といった基本の対策にあります。難読化はそれらを補う形で、「攻撃者が仕組みを読んで悪用する」までの壁を高める位置で使うのが現実的です。
難読化は、コードやバイナリを読みにくくして解析をしにくくする技術です。これに対して暗号化は、鍵を持たない相手が中身を読めない形へデータを変える技術です。
大きな違いは、暗号化が「鍵がなければ読めない」ことを目ざすのに対し、難読化は「読めるが手間がかかる」状態を目ざす点です。また、暗号化は通信や保存データを守るために使われ、難読化はコードを読まれにくくするために使われることが多いです。
個人の情報、ログイン情報、決済に関わる情報など、機密性が要るデータは、暗号化とアクセス制御で守るのが原則です。一方、配布したコードを読み取りにくくしたいときは難読化を使います。ねらいが違うため、場面ごとに使い分けます。
実際の開発では、両方を合わせて使うことがあります。たとえば、アプリのコードは難読化しつつ、扱うデータは暗号化して保存や送信を行います。ただし、クライアント側へ置いた秘密を難読化だけで守る設計は危険です。秘密はサーバー側を中心に持つことが大切です。
これからも難読化は、人やツールによる解析との競争の中で変わっていくと考えられます。自動で読む仕組みや補助ツールが進むほど、難読化だけでは破られやすくなるため、改ざん検知、署名の確認、サーバー側での不正の見分け、使われ方の監視などと合わせて使う流れが強まると見られます。
Web、モバイル、IoTなど、配るコードが増えるほど、難読化は「見られる前提で使う抑止策」として意味を持ちます。とくに不正な改造やチート、商用ロジックのまねをしにくくする用途では、今後も一定の効き目が見込めます。
難読化は、コードを止めたまま見る解析だけでなく実行中の解析も見すえた設計へ進んでいます。どこへ適用するかを自動で調整する仕組みや、大事な部分へ強さを集める方法など、運用のしやすさと効果のつり合いを取る向きで進むでしょう。
AIは、難読化の生成や強さの調整を助ける一方で、攻撃側が解析を進める手助けにも使われ得ます。そのため、防御側は難読化を強くするだけでなく、認可、監視、検知、封じ込めまで含めた全体の設計で、攻撃に耐える仕組みを作ることがいっそう大切になります。
なりません。難読化は読む手間を増やすための手法で、暗号化のように鍵なしで読めない形を作るものではありません。
一時しのぎにしかなりません。弱点があれば、いずれ見つかって悪用されるおそれがあるため,先に修正が要ります。
ねらいによります。独自の工夫を守る、改変をしにくくするといった使い方には向きますが、秘密の情報を守る手段にはなりません。
名前を変える、文字列を隠す、分岐や呼び出しを追いにくくする、同じ動きを別の書き方に変える、いくつかを重ねる、といった手法があります。
守れません。クライアントで使う以上、実行中に取り出されるおそれがあるため、鍵やトークンはサーバー側で持ちます。
本当です。ログやスタックトレースが読み取りにくくなることがあるため、ソースマップや解析用の手順が要ります。
まずは守りたい箇所にしぼるのが一般的です。全体へ強くかけると、開発や保守の負担が増えます。
それだけでは防げません。認可や監視などの基本の対策を補う役割として使います。
あります。難読化は読む手間を増やすだけなので、時間をかければ解析されることがあります。
認可、秘密の保管、改ざん検知、署名の確認、監視、脆弱性の修正などを合わせて使います。