20210603

20210603

https://www.ipa.go.jp/security/awareness/vendor/programmingv2/web01.html

ショッピングサイト等のWebアプリケーションでは、ユーザから入力された商品申込みや問合せ等の内容を、メールで送信する機能をもつものがある。 このような場合、送信先のメールアドレスは固定されており、Webアプリケーションの管理者以外は変更できないようになっている。その実装によっては、外部の利用者が送信先メールアドレスを自由に指定できてしまう場合がある。この問題は「メールの第三者中継」と呼ばれ、迷惑メールやウイルス等を送信する際に身元を隠すために使用される。

https://www.ipa.go.jp/security/awareness/vendor/programmingv2/web01.html

Webサーバコンピュータ上の本来保護されるべき重要なファイルの内容を、インターネット越しに容易に読み出せる場合がある。

このファイル流出の問題は、Webサーバのファイル公開機能によりファイルが漏れ出す「Webサーバからのファイル流出」と、Webアプリケーションプログラムのディレクトリトラバーサル脆弱性等によって起こる「プログラムからのファイル流出」のふたつに分けられる。ここでは前者について説明する。また、後者については、次の記事において説明する。

Webサーバからのファイル流出は、さらに「データファイルの誤った公開」と「Webプログラムソースコードの流出」のふたつに分かれる。

データファイルの誤った公開

データファイルの誤った公開は、個人情報を含む顧客リスト等の重要なデータファイルをWeb公開領域に誤って設置してしまう問題である。この問題が生じる要因として次が想定される。

要因 1
Webアプリケーションの設計時に問題があると意識せずに公開領域に重要なファイルを置く設計を行った。あるいは、Webプログラムの実装時にプログラマの裁量で重要なファイルの置き場所を決めたが、それがWeb公開領域であった

要因 2
画像、文書、表計算ワークシート等、ファイルの形をしたコンテンツであって、特定のユーザのみに開示すべきものを、ファイルの形のままWeb公開領域に配置した

要因 3
Webサーバコンピュータの運用時に、誤って重要なファイルのバックアップコピーをWeb公開領域に置いたままにした
対策 1
重要なファイルはWebサーバ公開領域に置かない設計・実装・設定を行う。[要因 1]

対策 2
特定のユーザのみに開示すべきコンテンツは、それがファイルの形で存在したとしても、アクセス制御ロジックをもつプログラムを通じて提供するよう、設計・実装する。 [要因 2]

対策 3
一時的バックアップコピーの制限。本番運用しているWebサーバ上に重要なファイルの一時的バックアップコピーを作らないようにする。 [要因 3]

対策 4
初期設定ならびに運用時、あらかじめリストに掲載されているもの以外のファイルをWeb公開領域に置かないようにする。違反がないか、シェルスクリプト等を用いて定期的に検査することも、ひとつの方法である。 [要因 1, 要因 2, 要因 3]

Webプログラムソースコードの流出

JSP、Perl、PHP等、スクリプトの形で記述されるWebアプリケーションプログラムの場合、これらのソースコードが誤ってWebサーバコンピュータから流出することがある。その要因として次が想定される。

要因 4
include, require, use等の命令で取り込むためのインクルードファイル名に「.inc」「.pm」等、標準ではWebサーバ(ソフトウェア)やWebアプリケーションサーバがスクリプトとして認識しない拡張子をもたせている。これらのインクルードファイルはURLさえ見当がつけばインターネットから閲覧できるおそれがある

要因 5
Webアプリケーションの修正を行った際ソースコードのバックアップ・ファイルが作られて、それがWebサーバコンピュータ上に放置されている。プログラマが意図的に旧バージョンの写しを作る場合と、テキストエディタが自動でバックアップファイルを作ってしまう場合の 2通りがあり得る

これらの要因が生じないようにするには、次の対策を講じることになる。

対策 5
標準的な拡張子の使用。インクルードファイルに与える拡張子には、スクリプトの標準的な拡張子(PHPであれば.php等)を用いる。非標準の拡張子(.inc、.pm等)を用いない [要因 4]

対策 6
非標準拡張子の動作の定義。インクルードファイルに .inc のような標準では動作が定義されていない拡張子を与えるのであれば、WebサーバもしくはWebアプリケーションサーバにおいて、この拡張子をもつファイルの内容をブラウザに開示するのではなくスクリプトとして処理するよう定義する [要因 5]

対策 7
プログラム保守の制限。本番運用している WebサーバコンピュータにおいてWebアプリケーションプログラムの修正を行わないようにする。別のコンピュータで動作確認を済ませてから必要なもののみファイルの入れ替えを行う[要因 5]

「入力対策」の基本は入力を受け取る箇所を特定し、正しく処理できる入力だけを受け取る様にすることである。想定外の動きにならない為に、どれだけの長さまたは大きさのものまで取り扱うのか、どのような型のデータとして取り扱うのかなどの仕様を明確にし、できるだけ限定するようにしなければならない。

入力検査漏れ

クライアント側スクリプトの検査ロジックが迂回される

数値範囲検査において攻撃を見逃す

https://www.ipa.go.jp/security/awareness/vendor/programmingv2/web01.html

「注入対策」としてここではコマンド注入攻撃とSQL注入攻撃について述べる。実装時出力先に応じて特殊な意味を持つ記号などに対策を行うことは「注入対策」全般に共通する。方式設計の段階で考慮すべき対策もある。注入攻撃はコマンドやSQL以外にも出力先毎にある。

コマンド注入

「コマンド注入(Command injection)」は、Webアプリケーションプログラムがシェルコマンド文字列を組み立てて実行している箇所がある場合、そこに外部からデータに紛れさせたコマンド文字列を送り込まれると、コンピュータを不正に操られてしまう問題である。

コマンド注入に伴って想定される被害

コマンド注入を行う攻撃への対処が不十分であると、コンピュータの乗っ取り、他のコンピュータへの攻撃の踏み台、コンピュータウイルスのばらまき、フィッシング詐欺等の悪用が起こり得る。

対策 その1: うっかりシェルを動かさない
自分ではそのつもりが無くても、プログラマがシェルを起動するAPIを気づかぬうちに使っていることがありうる。
使い方によっては、シェルを起動してコマンドを解釈させることになるAPIがあることを認識し、できればそれらのAPIを使わないようにする。

対策 その2: 別プログラムの起動を避ける
可能であれば、ソフトウェア構成を設計する際に(方式設計において)、別のプログラムを呼び出すことを避けた設計を行う。クラスライブラリやランタイムライブラリで解決できる場面で別プログラムを用いない。

対策 その3: 別プログラムを起動せざるを得ないとき
(1) シェルが用いられないAPIを選ぶ
別のプログラムを起動せざるを得ない場合、内部でシェルが呼び出されないAPIを選ぶことが望ましい。
C言語においては、execve等のexec系関数が、JavaではRuntimeクラスのexecメソッドがそれにあたる。
Perlには、シェルを動作させずに他のプログラムを呼び出せるAPIが備わっていない。
PHPには、プロセス制御関数群(PCNTL)の中にはpcntl_execというライブラリ関数が用意されている。これはまさにPOSIXのexec系関数を呼び出すものであるが、逆に現在のプロセス空間に別のプログラムをロードしてしまうため、場合によってはWebサーバプロセスの動作に大きな支障が出ることも考えられ、PHPのpcntl_execのWebアプリケーションにおける使用は推奨されていない。

(2) 特殊記号の排除
別のプログラムに与えるパラメータに用いる文字種を英数字のみ等安全なものに限定し、検査してから渡す。
bashの場合、次の特殊記号は別コマンドの実行に使われるものとして特に警戒する。
「;」「|」「&」「`」「(」「)」。
また、次の特殊記号もファイルへのアクセスが起こったりコマンドの意味が変わり得るので警戒する。
「$」「<」「>」「*」「?」「{」「}」「[」「]」「!」

(3) 環境変数のリセット
別のプログラムを呼び出す際の環境変数領域は呼び出し側プログラムによって初期化したものを与える。

対策 その4: 特殊な動作環境
chroot等による制約を課す
可能ならば、別のプログラムを起動する際は起動されるプログラムがアクセス可能なファイルシステム領域をchrootによって限定する。呼び出し側プログラムはchroot使用に必要となるroot権限を行使しだい速やかに放棄する。

対策 その5: シェル以外のコマンド注入対策
スクリプト実行関数を避ける
スクリプト言語にはシェルの起動と類似のAPIが存在する場合がある。
例えば、PerlにはPerlスクリプト文字列を解釈実行できる eval()関数がある。次は数値演算を行い、ゼロ除算エラーを検知して対処できるようにする際に eval()関数を利用する例である。
  • ファイル名チェック
  • Hash値生成のときにランダム文字列をくっつけとく
  • (一定期間経ったらファイル消去)

以下の方法で実装(危険な文字列を全て_に置換する方法をとった)

original_filename = original_filename.replace(/\$/g, "_").replace(/\;/g, "_").replace(/\|/g, "_").replace(/\&/g, "_").replace(/\'/g, "_").replace(/\(/g, "_").replace(/\)/g, "_").replace(/\</g, "_").replace(/\>/g, "_").replace(/\*/g, "_").replace(/\?/g, "_").replace(/\{/g, "_").replace(/\}/g, "_").replace(/\[/g, "_").replace(/\]/g, "_").replace(/\!/g, "_").replace(/\`/g, "_");

以下の方法で実装(ランダム文字列も使ってHash値を計算した)

//ランダムな文字列を生成
var chars = 'ランダム文字列';
var rand_str = '';
for (var i = 0; i < 8; i++) {
    rand_str += chars.charAt(Math.floor(Math.random() * chars.length));
}

//日付とEmailアドレスとランダム文字列からハッシュ値を計算
var hash = crypto.createHash("md5").update(dt + email + rand_str).digest("hex");
  • 20210603.1622699595.txt.gz
  • 最終更新: 2021/06/03 05:53
  • by 133.11.144.10