| デベロッパー | 2008年3月14日 10:00 |
|
JEEアプリケーションでのファイルのウイルススキャンの実装 著者: Vlad Kofman オリジナル版を読む ▼2008年3月14日 10:00 付の記事 ■海外internet.com発の記事 はじめにこの記事では、Java(JEEアプリケーション)でファイルのアンチウイルススキャンを実装する方法の一例を紹介します。現在のコンピュータ環境、特にWindowsオペレーティングシステムでは、ウイルスやトロイの木馬をはじめとするさまざまなマルウェアやスパイウェアが大きな問題となっています。 Javaで開発するアプリケーションに、外部からファイルをアップロードできるようにするという要件がある場合、セキュリティリスクが生じる可能性があります。ここで言うアップロードとは、HTTPプロトコルなり他の方法なりを使って、何らかの形で企業のファイアウォール内に外部のファイルを送れるようにすることを指します。こうした要件はエンタープライズアプリケーションでは非常によくあるもので、しかもJavaは最も広く使われているWeb開発プラットフォームの1つです。にもかかわらず、このように大きく口を開けたセキュリティリスクが往々にして見過ごされているのは、残念なことです。 Java Development Kit(JDK)には、アンチウイルススキャンのための機能は標準装備されていません。その理由として大きいのは、Javaはプログラム言語であり、ウイルススキャンのパッケージを備えていないということです。しかも、アンチウイルスソフトウェアはSunの専門外ですし、同社のビジネスモデルにも含まれていません。ウイルス対策のソフトウェア(あるいはJavaパッケージ)を開発することや、さらに重要な、維持やメンテナンスを続けていくことは、Sunにとってかなりの重荷です。ウイルスは常に進化を続けていくので、ウイルス定義を最新の状態に維持していくのは骨の折れる作業です。ウイルスの検出と対処を行うための製品は、McAfee、Symantec、Zone Labsなどの大企業が開発し、多大なリソースを投入してそのメンテナンスにあたっています。 アプリケーション環境Javaでファイルのウイルススキャンを実装するには、サードパーティ製のパッケージを利用する必要があります。この記事では、Java APIを備えたSymantec Scan Engine(SSE)パッケージを使うことにします。このパッケージは、TCP/IPサーバーとして動作するアプリケーションです。プログラミングインターフェイスが用意されており、コンテンツのスキャン技術をJavaアプリケーションに組み込むことができます。この記事ではSymantec Scan Engine 5.1を使用します。この製品には、UNIX版とWindows版の両方があります。 他社製のアンチウイルスパッケージを使用する場合は、どんなAPIが用意されているかは各自で調べてください。もっとも、基本的なアプローチは似ているはずです。また、ここで紹介する実装方法は、使用するJEEテクノロジは問わず、最近のMVCフレームワーク(StrutsやSpringなど)に対応しています。 アーキテクチャは次のようになります。まず、SSEを常時稼動するサーバーマシンが必要です。アプリケーションサーバーをホストするマシンと同じにすることもできますが、エンタープライズ環境の場合は、別のマシンにすることをお勧めします。また、ファイアウォールでデフォルトポートを開けておき、スキャンエンジンと通信できるようにしておく必要があります。ファイルスキャンを行う必要があるすべてのJEEアプリケーションは、デフォルトポートを通じてSSEサーバーマシンと通信できます。なお、別々のアプリケーションサーバーで稼動している複数のアプリケーションが同じスキャンサーバーを共用することもできます。詳細については、SymantecのWebサイトにある、Symantec Scan Engine(SSE)のインストールガイドを参照してください。 スキャンが必要な外部ファイルを、プログラミングインターフェイス(デフォルトポートを使用するJava API)を使用してSSEに送信すると、そのファイルに対する他の操作を行う前に、SSEから結果コードが戻ります。たとえば、Webメール型のアプリケーションで、外部ユーザーが添付ファイルとしてファイルをアップロードしたとします。この場合、アプリケーションは、SSEのAPIを呼び出し、OKかNGかを示すリターンコードに基づいて、アップロードの結果を判断し、その電子メールを実際に送信してよいかどうかを決定します。Yahooメールのアカウントをお持ちの方なら、Norton Antivirusですべての添付ファイルがスキャンされるのを見たことがあるかもしれません(Javaを使った実装ではありませんが)。 サーバーへのScan Engineのインストールの詳細については、Symantecのサイトにある、Symantec Scan Engine(SSE)実装ガイドを参照してください。 SSEについて頭に入れておくべきポイントを以下にまとめます。
ps -ea | grep sym. 次のようなプロセスのリストが表示されます。
何も表示されない場合、SSEプロセスは起動していません。
SSEプロセスが起動しなかった場合、次のコマンドを入力してSSEを再起動します。
/etc/init.d/symscan restart プロジェクトのセットアップこの記事のために、Symantec SSE APIのラッパーとなる「av.jar」を用意しました。SymantecのJava APIを使用し、SSEサーバーのクライアントとして機能して、サーバーとのすべての通信を担います。「av.jar」は、本稿の冒頭のリンクからダウンロードできます。SSEに対して「av.jar」を使用するには、これをJava CLASSPATHに含める必要があります。このjarにはAVClientというクラスが含まれています。これは、SSEに対してバイト列でファイルを送信し、結果を返すという処理そのものを行うクラスです。 私のプロジェクト設定では、System.getPropertyを通じてアクセスする3つの変数を追加しています。次のような変数です。 AV_SERVER_HOST=192.168.1.150 AV_SERVER_PORT=''1344'' AV_SERVER_MODE=SCAN AV_SERVER_HOSTはScan Engineがインストールされているマシンのホスト名またはIPです。 AV_SERVER_PORTはScan Engineが受け取るファイルをリッスンするポートです。 AV_SERVER_MODEはスキャンモードで、次のいずれかです。
注
ファイルストリーム(バイト列)のスキャンの場合、有効な値はSCANとNOSCANのみです。
SSEでスキャンを行うJava APIの使用スキャンを行うクラスでは、「av.jar」内のAVClientオブジェクトに備わっているスキャンAPIを呼び出します。AVClientオブジェクトはScan Engineサーバーへの接続を確立し、以下のAPIを含みます。 図2 Scan Engineサーバーと通信するための主なAPI ![]() スキャンの対象がファイルシステム上のファイルで、SCANモード(スキャンのみのモード)を使用する場合は、パラメータとしてファイル名のみを受け取るメソッドを呼び出します。 スキャンの対象がファイルシステム上のファイルで、SCANREPAIRモードまたはSCANREPAIRDELETEモードを使用する場合は、入力ファイル名と出力ファイル名を受け取るメソッドを呼び出します。 スキャンの対象がメモリ内のファイル(バイト列)の場合は、バイト列を受け取るメソッドを呼び出します。 サンプルコードを以下に示します。
import com.av.*;
設定パラメータを初期化します。 static String avMode = (System.getProperty("AV_SERVER_MODE") != null) ? (String) System.getProperty("AV_SERVER_MODE") : "NOSCAN"; static boolean scan = avMode.startsWith("SCAN"); static String avServer = (String) System.getProperty("AV_SERVER_HOST"); static int avPort = Integer.parseInt( (String) System.getProperty("AV_SERVER_PORT")); メモリ内ファイルのバイト列をスキャンしてチェックする例です。 public void scanFile(byte[] fileBytes, String fileName) throws IOException, Exception { if (scan) { AVClient avc = new AVClient(avServer, avPort, avMode); if (avc.scanfile(fileName, fileBytes) == -1) { throw new VirusException("WARNING: A virus was detected in your attachment: " + fileName + "<br>Please scan your system with the latest antivirus software with updated virus definitions and try again."); } } } MVCハンドラ内でこのコードを使用する場合は、カスタムのVirusExceptionをスローでき、呼び出し側のメソッドでこれをチェックして必要なクリーンアップ処理を実行できます。このクラスも「av.jar」に含まれています。 使用例を次に示します。 catch (Exception ex) { logger.error(ex); if (ex instanceof VirusException) { // do something here } else { // there was some other error - handle it } } Scan EngineのクライアントAPIの詳細については、Symantec Scan Engineソフトウェア開発者ガイドを参照してください。 SSEの応答コードと通知オプション SSEに接続できなかった場合や、SSEライセンスが無効になったり有効期限が切れたりした場合に備えて、Javaコードには、システムサポート担当者に送信する通知や電子メールを自動生成するためのフックが必要です。こうした通知を生成する機能を使用するためには、アンチウイルスのクライアントコードをアプリケーションに組み込むときに、javamailやその他の電子メールパッケージを使用することが必要な場合があります。AVClientオブジェクトの コードの一覧を以下に示します。
私は、SSEサーバーからの応答文字列に、ライセンスの有効期限切れに対応する文字列「ICAP/1.0 558」を追加しました。対応が必要な主なコードには、ウイルスを示すtwoとthree、およびファイルが異常なしであることを示すfourがあります。 応答コードの定義の一覧については、Symantec Scan Engineソフトウェア開発者ガイド(表3-4の状態コード)を参照してください。 ライセンスが無効の場合に管理者に電子メールを送信するには、次のようにします。 if (server_response.equals(fourteen) || server_response.equals(sixteen)) { // license is bad // if you want to let files through without actually scanning the_return = "''clean''"; // send email - this must be working if option is "clean" String body = "Note the license for Symantec Scan Engine is invalid or has expired!¥n¥rPlease see - class AVRespond for more info.¥n¥rThis email is sent every time a client uploads an un-scanned file"; try { sendMail("symantec_scan_engine@mycompany.com", "YOU@mycompany.com", "Invalid or expired license for Symantec Scan Engine", body); } catch (Exception ex) { logger.error("AV client could not send email notification¥nMake sure properties has ¥"mail.smtp.host¥" entry in it ¥n " + ex); } } まとめこの記事では、JEEアプリケーションにファイルのアンチウイルススキャン機能を組み込む方法について説明しました。驚いたことに、このしくみについて知っている開発者はあまり多くありません。外部ファイルをスキャンせずにおくことはセキュリティリスクとなり得るにもかかわらずです。 現在のところ、スキャン処理の実装はサードパーティベンダごとに固有で、独自のJava APIを備えた製品を利用することになります。Java開発者としては、スキャンAPIの標準プロトコルをSunが策定して、各ベンダに準拠してもらう形になった方がうれしいと思います。ちょうど、Java Messaging Service(JMS)プロトコルの場合と同じようにです。エンタープライズ分野におけるスキャン処理は、JMSほどの存在感はないにせよ、一部のエンタープライズアプリケーションにとって重要な側面であることは間違いありません。 関連情報著者紹介Vlad Kofman(Vlad Kofman)
ウォールストリート有数の企業でエンタープライズレベルのプロジェクトに携わる。また、米国政府の防衛関連の仕事も手がけている。特に関心を寄せているのは、オブジェクト指向プログラミング方法論、UI、デザインパターン。
|
| トップページ | 画面トップ |
|