ガイドSC

ディレクトリトラバーサル・OSコマンドインジェクション・ファイルアップロード攻撃

公開: 2026-09-26更新: 2026-09-26
資料共有サービスを例に、パス解決、コマンド引数、アップロードの受信・保存・解析・配信の防御点を学ぶ。

ファイルを選んでダウンロードし、PDFを変換して保存するWebアプリには、似て見える三つの異なる境界があります。ファイル名が保存領域の外へ出るディレクトリトラバーサル、値がOSコマンドとして解釈されるインジェクション、アップロードされたファイルが実行・解析・公開される経路です。架空の資料共有サービスfiles.exampleで順に追います。

科目B(午後)では『拡張子を検査した』だけで終えず、どの入力がパス、コマンド引数、ファイル本体、公開URLへ渡ったか分けます。成立条件、読めた範囲、改変の有無、復旧に必要な証拠を問う内容です。以下のドメイン、パス、ログは教材用の架空例です。

1. 三つの処理と信頼境界

files.exampleは、GET /download?id=...で資料を返し、POST /convertでPDFを画像に変換し、POST /uploadで資料を受け付けます。保存領域は/var/app/documents、公開Webのドキュメントルートは/var/www/publicとします。Web実行ユーザは資料領域への限定された権限だけを持つ設計です。

攻撃・機能

利用者が制御するものと越える境界

ディレクトリトラバーサル

ファイル名やパス指定に../や符号化した区切りを混ぜ、/var/app/documentsの外のファイルを読もうとする。パスの正規化、シンボリックリンク、OS権限が結果を左右する。

OSコマンドインジェクション

PDF変換などで外部プログラムを呼ぶ際、利用者値がシェルの構文として解釈される。シェルを使わなくても、値が変換プログラムのオプションとして解釈される引数注入が残る。

ファイルアップロード攻撃

利用者が内容・元のファイル名・Content-Typeを送る。保存先、実行可否、後段の解析器、公開時のContent-Typeなどで別の危険が生じる。

アプリの認可

ファイルが許可ディレクトリ内にあっても、利用者がその資料を読む権限があるとは限らない。IDから対象を引き、所有者や共有範囲を確認する。

OS実行権限

脆弱なアプリ処理が使うサービスアカウントのファイル・ネットワーク権限。管理者権限で動いていれば影響が増える。OS権限の限定はアプリの欠陥を直さないが、被害範囲を狭める。

三つの攻撃を同じ『不正ファイル名』で説明しないことが重要です。トラバーサルはパス解決、コマンド注入はプロセス起動の構文、アップロードは保管・解析・配信の各段階に着目します。同じURLパラメータでも、到達先のAPIによって必要な対策が変わります。

2. ディレクトリトラバーサルは何を越えるか

危険な設計では、GET /download?name=report.pdfのnameを/var/app/documentsへ文字列連結して開きます。攻撃者が../を入れると、正規化後のパスが資料領域の外へ出る可能性があります。ファイルへの読取り権限がOS側にある場合、設定や資格情報のファイルまで読めることがあります。

text
危険な処理の概念:
  base = /var/app/documents
  requested = base + "/" + user_input
  open(requested)

入力例:
  user_input = ../../config/secret.txt

安全な設計の要点:
  idからサーバ側で資料レコードを引く
  認可済みレコードに対応する保存キーだけを使う
  許可した保存領域の外へ出ないことを確認する

例の相対パスが実際にどこを指すかは、基準ディレクトリ、区切り文字、正規化の回数、シンボリックリンクに依存します。入力に../が見えたことと、資料領域外の秘密ファイルを実際に読めたことは別です。サーバの解決結果とファイルアクセスログで確かめます。

対策点

効く理由と注意点

不透明な資料ID

利用者には直接パスを指定させず、サーバがID→保存キーを引く。DBで利用者の所有・共有権限も確認する。入力にパス構文を含める必要をなくす。

正規化と領域確認

業務上パス入力が必要なら、デコード後にOSのパス規則で正規化し、許可基準ディレクトリ内の対象か確かめる。文字列の単純な前方一致では、似た名前の隣接ディレクトリを誤許可し得る。

シンボリックリンク対策

パスが領域内に見えてもリンク先が外へ向く場合がある。リンク禁止又はディレクトリハンドル相対の安全なファイルオープンを使い、確認後の差替え競合も考える。

OS権限

Web実行ユーザが/var/app/documents以外の秘密ファイルへ不要にアクセスできないようにする。アプリ欠陥があっても読み取れる範囲を縮める。

復号回数と区切り

URLの%2e%2e%2fや二重符号化、Windowsのバックスラッシュなどを、実際のフレームワークとOSがどう解釈するか確認する。一箇所だけの文字列置換を対策の中心にしない。

パスが許可領域内と確認できても、ファイルの中身が他人の資料ならIDORになります。パス境界の検証と利用者のデータ認可は別です。試験の条件で『別部署の資料を読めた』なら、パスの外へ出たのか、領域内の他人の資料へ到達したのかを分けて答えます。

2-1. 確認後のパス差替えをどう考えるか

アプリがパスを正規化して領域内と確認した後、別処理がシンボリックリンクを外部の秘密ファイルへ差し替えると、実際にopenした対象が確認時と変わる可能性があります。これは検査時と使用時の競合です。攻撃者が該当ディレクトリを変更できることが成立条件で、単なるHTTP入力だけでは必ず起きません。

資料IDから固定の保存キーを引き、利用者が保存先のディレクトリ構造を変更できない設計が基本です。どうしてもファイルシステムのパスを扱うなら、信頼できるディレクトリハンドルを起点にした相対オープンやリンク追跡の制限をOS・言語のAPIで検討します。正規化した文字列だけで実ファイルの同一性が保証されるわけではありません。

資料領域外のファイルへ到達するまで攻撃者がパス入力を支配し、アプリが連結・オープンする条件が必要。1パスを入力2基準へ連結3領域外を開く4内容を返す
資料領域外のファイルへ到達するまで
  1. 1. パスを入力:証跡 HTTP要求値/防御・対処 資料IDだけ受け付ける
  2. 2. 基準へ連結:証跡 アプリの組立処理/防御・対処 正規化と領域確認
  3. 3. 領域外を開く:証跡 実ファイル・OS記録/防御・対処 安全な相対オープン
  4. 4. 内容を返す:証跡 応答と送信ログ/防御・対処 読取り権限を限定

攻撃者がパス入力を支配し、アプリが連結・オープンする条件が必要。

図のopen段階が成立しても、OSがそのファイルの読取りを拒否すれば内容は返せません。逆に、読取り成功ログがありHTTP応答へ内容が含まれれば、情報流出の範囲を具体的に調べます。各段階の証拠を揃えて、試行・到達・読取り・外部送信を区別します。

3. OSコマンドインジェクションはどこで意味が変わるか

PDF変換に外部ツールを呼ぶとして、アプリがシェルへコマンド文字列を渡す実装を考えます。利用者のファイル名をその文字列へ連結すると、シェルの区切り記号や置換構文が入力データではなく命令として解釈され得ます。攻撃者が使えるのはWebサーバのプロセス権限で、成功には該当経路を呼び出せることが必要です。

text
危険な概念:
  shell("converter " + user_filename + " output.png")

改善の概念:
  converter_api(input_file_handle, output_file_handle)
  または、固定実行ファイルと検証済み引数配列で起動する

別の注意:
  シェルを使わなくても、引数が --help 等なら
  ツールのオプションとして解釈されることがある

対策

作用する位置と残る問題

OSコマンドを呼ばない

画像・PDF処理のライブラリAPIで操作する。シェル構文への入力混入を断つ。ただしライブラリ自身の脆弱性や巨大ファイル対策は別に要る。

実行ファイル固定・引数分離

必要な外部プログラムだけを固定パスで起動し、シェルに一文字列として渡さない。引数は配列で与える。これでシェル注入を減らせるが、引数注入を完全には防げない。

許可リスト・オプション終端

入力ファイルはサーバが生成した安全な保存名を使い、必要ならオプション終端の--を利用する。ツールが--をどう扱うかは実機で確認する。

実行権限の最小化

変換プロセスを隔離し、不要なファイル・ネットワーク・資格情報へのアクセスを与えない。コマンド注入が残っても被害範囲を縮める。

記録と監視

起動したプログラム、引数の安全な要約、終了コード、出力ファイルを記録する。利用者入力や秘密を無制限にログへ残さない。

文字をバックスラッシュで逃がすだけの対策は、OS・シェル・対象ツールの解釈差に依存します。シェルを使わない構造化呼出しに変え、入力の意味を有限の選択肢へ制限します。開発工程の設問ならこの呼出し方を修正し、運用工程の設問なら不審プロセスやファイルへのアクセス履歴を調べます。

3-1. プロセス起動ログの読み方

OSのプロセスログにconverterという名前があるだけでは、正規のPDF変換か不正コマンドか分かりません。親プロセス、実行ファイルの絶対パス、引数列、作業ディレクトリ、実行ユーザ、開始時刻、終了コード、生成したファイルを確認します。シェルが親となり想定外の子プロセスを起動していれば、文字列連結の悪用を疑う材料になります。

変換ツールがネットワークへ出る必要がないのに外部接続があれば、追加調査が必要です。ただし外部接続だけでコマンド注入や流出は確定せず、更新確認など正規動作とも区別します。プロセス起動とネットワークログを同じ時刻で結び、対象ファイルと送信量を調べます。

観測

言えることと限界

シェル起動

アプリがシェルを使った。利用者入力が命令として解釈されたかは実際のコマンドと引数、後続プロセスが必要。

予期しない子プロセス

設計上の変換処理以外が実行された可能性。誰が起動したか、実行ユーザ、引数を調べる。

終了コード0

プログラムが成功扱いで終了した。出力ファイルの内容、権限、機密流出は別に確認する。

出力ファイルの改変

処理結果が変わった。利用者入力、変換器、保存処理のどこが原因かを特定する。

4. アップロードは受信・保存・解析・配信を分ける

POST /uploadでPDFだけを受け付ける例です。ブラウザが送るファイル名やContent-Typeは攻撃者も変更できます。拡張子が.pdfでも中身がPDFとは限らず、PDF形式でも脆弱な解析器を攻撃する内容を含められます。受信時の検証一回で安全が確定するわけではありません。

資料アップロードの防御点一時領域から安全な保存名へ移し、検査後に権限付きで配信する。利用者Webアプリ検査処理非公開保管1. PDFを送信2. 形式と内容を検査3. 判定を返す4. 安全名で保存5. 資料IDで取得6. 認可後に読取7. 資料を返す8. 安全なヘッダで返す
資料アップロードの防御点

一時領域から安全な保存名へ移し、検査後に権限付きで配信する。

スキャンに時間がかかる場合は、検査完了前のファイルを非公開の隔離領域に置きます。検査結果が出る前に公開URLから取れる構成では、後段の検査が間に合いません。検査失敗、タイムアウト、再試行時の公開可否も定義します。

段階

具体的な検査と限界

受信

認証・認可、件数、ファイルサイズ、総量、拡張子の許可を確認する。クライアント申告のContent-Typeだけで種類を決めない。ZIPなど圧縮形式は展開後サイズも考える。

ファイル形式

ファイルシグネチャや実際の構造を検証し、PDF解析器で安全に読めるか確認する。マジックバイトが合っても悪意あるPDFやパーサ脆弱性を排除し切れない。

保存名と場所

利用者の元ファイル名をパスに使わず、サーバが新しい保存キーを発行する。公開Webルート外又は独立した保管先に置き、実行権限を与えない。

内容処理

マルウェア検査、必要ならCDR、制限付きサンドボックスでの変換を使う。検査器自体の更新と失敗時の隔離方針も必要。

配信

資料IDから所有者・共有範囲を確認し、正しいContent-TypeとContent-Disposition、必要なブラウザ側制約を設定する。アップロード内容を同一オリジンの実行可能HTMLとして配信しない。

廃止・削除

利用者削除後も一時領域、公開キャッシュ、バックアップに複製が残り得る。保存キーと公開経路を棚卸しする。

Webシェルが成立するには、攻撃者が実行可能な内容を保存し、Webサーバがそのファイルをスクリプトとして解釈する配置と設定が要ります。単に.phpという名前のファイルを受け付けただけで、サーバ上でコードが実行されたと断定しません。逆にPDFに偽装した内容が解析器を攻撃する場合は、スクリプト実行設定がなくても危険です。

4-1. 配信時のActive Contentとブラウザ側の危険

アップロードしたファイルをorders.exampleと同じオリジンでHTMLとして配信すると、その中のJavaScriptがそのオリジンの文脈で動く可能性があります。サーバ上でスクリプトを実行しない設定でも、ブラウザ側のXSSやフィッシングが起き得ます。資料の公開要件があるなら、別オリジンの配信先やダウンロード扱いを検討します。

Content-Disposition: attachmentを付けても、すべての閲覧経路の安全を自動で保証するわけではありません。実際のContent-Type、ブラウザの型推測の抑制、アクセス権、公開キャッシュを合わせて設計します。元のファイル名をダウンロード名へ使う場合も、HTTPヘッダとして安全に表現します。

4-2. 圧縮ファイルと後段の解析

ZIPを許可する場合は、受信したZIPのサイズだけでなく、展開後の総容量、ファイル数、入れ子の深さ、展開先のパスを制限します。圧縮内のファイル名が../を含めば、展開処理でトラバーサルが再び起き得ます。アップロード時の元ファイル名を安全にしても、アーカイブ内の名前は別の入力です。

PDFや画像のサムネイル生成も、解析器に攻撃者のバイト列を渡します。検査器と変換器を低権限で隔離し、CPU・メモリ・時間・ネットワークを制限します。マルウェア検査が『clean』でも、未知のパーサ脆弱性や業務上の不正内容を必ず排除できるわけではありません。

5. 架空ログから攻撃の成否を段階ごとに読む

次は三つの処理で見つかった架空ログです。時刻はUTC、実際の利用者入力は一部を省略しています。ログに『試行』があることと目的達成を分けて読みます。

text
12:00:00 app req=F1 user=guest route=/download
  document_id=../config/secret.txt result=400 reason=bad_id
12:01:00 app req=F2 user=alice route=/convert
  input_key=doc-42 process=converter exit=0
12:02:00 app req=F3 user=guest route=/upload
  original_name=invoice.pdf content_type=application/pdf
  size=2MiB scan=fail visibility=quarantine
12:03:00 web req=F4 path=/uploads/invoice.pdf
  status=404

行

確定事項と限界

F1 bad_id

不正なID形式が拒否された。/var/app/documents外のファイルを読めた証拠はない。別の入力経路や既存データまで安全とは言えない。

F2 converter exit=0

変換プログラムが終了コード0で終わった。実行時の引数、出力、OSの副作用はこの行だけでは分からない。

F3 scan=fail

受信したPDF申告ファイルが検査に失敗し隔離された。悪意のあるコードが実行されたかは解析器・隔離処理のログを確認する。

F4 status=404

その公開URLは見つからなかった。別URL、別保存名、キャッシュから取れないことまでは証明しない。

発生時にはWebアクセスログ、アプリの資料IDと保存キー、OSのファイルアクセス、起動プロセス、アップロード保管先、検査器ログを時系列で結びます。攻撃者が読めたファイルや操作した資料、公開された期間を特定します。拒否ログだけで『影響なし』と結論付けません。

6. 修正と事故後の復旧

不審なファイル操作を検知した後入口修正に加え、保存済みファイルと実行プロセスの影響を調べる。1入口を止める2範囲を調査3実装を修正4残存物を除去5再開を判断
不審なファイル操作を検知した後
  1. 1. 入口を止める:対応 危険な経路と公開を停止/確認する証跡 設定・アクセス記録
  2. 2. 範囲を調査:対応 読取・保存・実行を照合/確認する証跡 ファイル・プロセスログ
  3. 3. 実装を修正:対応 ID参照・安全な呼出しへ/確認する証跡 コード差分・試験
  4. 4. 残存物を除去:対応 不審ファイルと資格を確認/確認する証跡 保存先・鍵・アカウント
  5. 5. 再開を判断:対応 正常処理と拒否を試す/確認する証跡 復元・認可試験

入口修正に加え、保存済みファイルと実行プロセスの影響を調べる。

トラバーサル疑いなら、アクセス可能だった秘密ファイルの内容と資格情報を調べ、読まれた可能性がある資格を交換します。コマンド注入疑いなら、サービスアカウントの権限、起動した子プロセス、永続化、外向き通信を調べます。アップロード疑いなら、隔離前に公開された複製や処理済みファイルを追います。

  1. ダウンロードは資料IDからサーバ側保存キーを引き、パス境界と利用者認可を検証する。

  2. 変換はシェル文字列連結をやめ、固定ツール・分離した引数・許可された入力ファイルだけで実行する。

  3. アップロードは種類・サイズ・構造・内容を検査し、サーバ発行名で非公開保管し、認可付きで配信する。

  4. 正常なPDFと資料取得が成功し、../、符号化した区切り、オプション風ファイル名、不正形式、巨大ファイル、未認可取得が拒否されることを確認する。

被害の復旧はコードの修正だけでは終わりません。漏れた秘密情報の交換、不審ファイルの削除又は再構築、バックアップの健全性確認、公開キャッシュからの撤去、正規利用者の再開試験まで行います。

6-1. 変更後に確認する拒否例

機能

正規例と拒否例

ダウンロード

権限のあるdoc-42は取得できる。他人のdoc-99、../を含む入力、符号化した区切り、リンク先が領域外の資料は拒否される。

PDF変換

正規の保存キーから変換できる。利用者が指定した--で始まる値やシェル記号は実行ファイルのオプション・命令にならない。

アップロード

許可されたPDFは検査後に取得できる。不正形式、過大ファイル、ZIP展開爆弾、解析失敗は隔離され公開されない。

配信

認可済み利用者だけが取得でき、許可外のHTMLやスクリプトは同一オリジンで実行されない。公開キャッシュも別途確認する。

7. 科目B(午後)の記述演習

演習1:領域内の別人資料

条件:GET /download?id=doc-99で、doc-99は許可領域内にあるが別部署の資料。問い:どの確認が不足しているか。

解答:資料IDに対する利用者の所有・共有権限の確認。パスが領域内という判定だけではIDORを防げない。誤答『../を拒否すれば十分』は認可の欠落を見落とす。

演習2:符号化した../

条件:入口の文字列検査は../を拒否するが、%2e%2e%2fは通る。後段がデコードしてファイルを開く。問い:危険になる条件と修正を述べよ。

解答:検査時とファイルオープン時の解釈が違い、正規化後に基準領域外へ出られると危険。ID参照へ変え、必要なパスは後段と同じ規則で正規化して領域内を確認する。誤答『文字列../はないので安全』はデコード後の値を見ない。

演習3:引数配列なら完全か

条件:シェル文字列はやめたが、利用者指定ファイル名を変換ツールの引数配列へそのまま渡す。値は--output=/tmp/xを指定できる。問い:残る問題を述べよ。

解答:ツールがオプションとして解釈する引数注入が残る。サーバ発行の保存名や許可リスト、必要ならオプション終端を使う。誤答『シェルを使わないので全入力が安全』はツール自身の構文を無視する。

演習4:拡張子だけの確認

条件:.pdfだけを許可し、Content-Typeは利用者申告を採用、ファイルはWebルート直下に置く。問い:追加対策を述べよ。

解答:実際の形式・内容・サイズを検査し、サーバ発行名で非公開領域へ置き、実行を禁止し、認可付きで配信する。誤答『.pdfなので無害』は拡張子偽装と解析器の危険を無視する。

演習5:検査失敗後の公開

条件:F3はscan=failだが、実際にはアップロード直後の数秒だけ公開URLで取得できた。問い:設計上の原因と復旧確認を述べよ。

解答:検査前に公開領域へ置いたことが原因。非公開隔離から検査後に公開状態へ移し、公開期間のアクセス・キャッシュ・複製を調べる。誤答『最終的に隔離したので影響なし』は先に読まれた可能性を無視する。

演習6:Webシェル成立の判断

条件:攻撃者がshell.phpを送信し、アップロードAPIは保存した。問い:コード実行を断定できるか。

解答:断定できない。保存先がスクリプトとして公開・実行される設定か、実際にアクセス・実行されたかを確認する。誤答『.phpが保存されたので必ず実行』は保存と実行を混同する。

演習7:ZIP内のパス

条件:アップロードするZIP自体のファイル名は安全だが、中の項目名に../configがある。問い:どの段階で危険になり、何を確認するか。

解答:展開時に項目名を保存先へ連結すると領域外へ書ける可能性がある。展開先の正規化と領域制限、実際に書かれたパスと権限を確認する。誤答『ZIPの名前が安全だから中身も安全』は別の入力を見落とす。

8. 一次資料

OWASP:Path Traversal

OWASP:OS Command Injection Defense Cheat Sheet

OWASP:File Upload Cheat Sheet

OWASP:Input Validation Cheat Sheet

OWASP:Double Encoding

この記事についてAIに深掘り質問する

ChatGPT、Claude、Perplexityにこの記事を参照させ、要点の確認や疑問点を自由に質問できます。

次におすすめの学習

編集・検証について

編集・検証:IT資格ラボ編集部

IPAが公開する試験要綱・シラバス・過去問題と、各技術の公式資料を優先して内容を確認しています。制度変更や誤りを確認した場合は、記事を見直して更新します。

編集方針・情報源・訂正方針を見る
この記事を共有する