Javaバイトコードの脆弱性を見つける:結果をどうするか?



Solar inCodeは、Javaバイトコードの脆弱性を検出できます。 しかし、脆弱性を含むバイトコード命令を表示するだけでは不十分です。 そうでないソースコードの脆弱性を表示する方法は?



実際には、脆弱性検索ツールを使用する場合、見つかった各脆弱性に3つのアクションのいずれかを適用する必要があります。





3つのアクションはすべて、脆弱性の分析が必要です(たとえば、それを排除する方法と、それがもたらすリスクを理解する必要があります)。



Javaバイトコードに脆弱性が見つかったがソースコードがない場合、このような分析を行う方法



inCodeの作成時に脆弱性を検索する主な方法は、静的分析として選択されました-コードを実行せずに脆弱性を検索します。 静的分析には、次のものが必要です。





中間表現で脆弱性を見つけるには、さらなる分析のためにそれらをソースコードの観点で表示する必要があります。



Solar inCodeが脆弱性を探した最初のアプリケーションは、AndroidおよびJavaアプリケーションでした。 実行可能ファイルの脆弱性の検索は非常に需要があります。



  1. 契約条件に基づき、顧客はソースコードを送信することはできません。
  2. ソースコードが転送された場合でも、転送されたソースコードと一致しない実行可能コードは、バトルスタンド(またはGoogle Play)に送られます。
  3. 開発者はソースコードなしでサードパーティのコンポーネントを使用します。そのようなコードも制御する必要があります。


そのため、AndroidおよびJavaアプリケーションでは、静的分析の中間表現としてJavaバイトコードを選択しました。 モバイルアプリケーションのソースコードをJavaバイトコードにコンパイルした後、Dalvikコンパイラはクラスファイルを結合し、コードをDalvikのバイトコードに再コンパイルして、実行可能なdexファイルを取得します。 実行可能ファイルとリソースおよび構成ファイルはapkパッケージにパッケージ化されており、Google Play経由で配布されます。 apkパッケージの処理と変換を実装するツールがあります:リソースと構成ファイルの解凍、復号化、DalvikコードのJavaバイトコードへの変換( apktooldex2jar )。



バイトコードは、コンパイルによってソースコードから取得することもできます(JavaとScalaのソースコードを分析するときに行うように)。 したがって、JavaおよびAndroidアプリケーションのソースおよび実行可能コードを分析する場合、Javaバイトコードは単一の内部表現として非常に適しています(実際、Javaバイトコードにコンパイルされたすべての言語を分析することもできます)。



Javaバイトコードは逆コンパイルでき、コードは十分に高品質です。 Java用の多くの逆コンパイラ( JDfernflowerProcyon )があります。 復元されたJavaコードを中間表現として使用しませんでした。これは、逆コンパイルツールがミスを犯し、脆弱性検索の品質に影響を与える可能性があるためです。



そのため、Javaバイトコードに脆弱性が見つかりました(これを行う方法については、次の記事で説明します)。 結果をどうしますか?



それらを「ソース」コード、より正確には復元された高レベルのコードの観点から示す必要があります。 ここでの脆弱性とは、脆弱性を定義する一連のバイトコード命令位置(安全でないメソッド呼び出し、安全でないデータストリームが通過する一連の命令)を意味します。 したがって、バイトコードの各命令について、復元されたコードの行番号を一致させる必要があります。 クラスファイル(ソースコード内のクラスに対応するバイトコードファイル)には、属性LineNumberTableがあります。これは、バイトコード内の位置とソースコード内の行番号のマッピングを格納します。 したがって、Java言語の観点から脆弱性を表示するには、LineNumberTable属性をバイトコードに含める必要があります。



バイトコード(apkファイルから取得したものを含む)を分析するとき、LineNumberTable属性が表示されない場合があります。 コンパイル中またはapkからの逆変換中に削除できます。 これはそれほど重要ではありませんが、バイトコードから削除されたLineNumberTableは、復元された「ソース」コードではなく、開発者が作成したソースコードに対応していました。 つまり、分析されたバイトコードのLineNumberTable属性を復元する必要があり、復元されたコードを示します。



基本的なアルゴリズムは、Javaバイトコードを使用した逆コンパイルコード(AST)の抽象構文ツリーの構築と、ASTトラバース中のソースコードの出力に基づいています。 ASTトラバーサル(深さトラバーサル)中、復元されたコードの行番号とバイトコードメソッドの命令の位置の対応に関する情報も保存されます。



ツリーの各ノードでは、現在のメソッドの開始に対するバイトコード内の命令の位置と、復元されたコードのファイル内の行番号がわかります。 したがって、バイパス中、メソッドの境界も復元されたコードに保存され、「メソッドバイトコード内の位置」-「ファイル内の行番号」のペアの後続のフィルタリングに使用されます。



匿名クラスは、互いにネストされたメソッドを生成するため、個別に処理されます。 これを行うために、ラウンドの最後に、ソースコード内のメソッドの位置の間隔の入れ子の分析が実行されます。



復元されたマッピングおよび復元アルゴリズムの形式化






実際には、多くの場合、ソースコード(コンパイルにより行番号のテーブルを含むバイトコードを取得できます)とバイトコード(さまざまなサードパーティコンポーネント、ライブラリなど)の両方を含むプロジェクトを取得します。 そのようなプロジェクトを分析するために、inCodeはJavaでプロジェクトの前処理を組み合わせて実装します。 次の手順で構成されます。





このような前処理では、匿名クラスとネストされたクラスが考慮されます。1つのソースコードファイルが複数のバイトコードファイルに対応できます。



その結果、各バイトコードファイルには、Javaコード(復元またはソース)とこのファイルに接続する行番号のテーブルを含むファイルがあります。



この記事で説明されている手順とアルゴリズムを使用して、inCodeは、解析のために送信されたかどうかに関係なく、JavaまたはAndroidアプリケーションで見つかった脆弱性をソースコードに対して表示します。



iOSアプリケーションのバイナリファイルを分析する場合も同様のアプローチが使用されますが、すべてがより複雑になります。ARMアーキテクチャのバイナリコードを逆コンパイルするタスクは、あまり研究されていません。 このトピックについては、さらに出版物が掲載されます。



All Articles