アクセスログの攻撃痕跡を読む — スキャン・ブルートフォース・脆弱性試行を見抜く演習
記事の概要を読む
合成のWebアクセスログを題材に、スキャナ特有の連続アクセスや不自然なUser-Agent、ログインへの短時間POST集中、SQLインジェクション・パストラバーサルの試行痕跡を読み解き、正常アクセスと見分ける判断力を鍛える演習です。
この記事の目次 5項目から選ぶ
Webサーバーのアクセスログは、外部からの不審な動作を調べる材料のひとつです。偵察、ログイン画面へのブルートフォース攻撃、SQLインジェクション等を疑う痕跡が見つかることがあります。ただし、アクセスログだけで主体・意図・侵害の成否は確定できません。まず通常時との差を整理し、認証ログやアプリの記録へ照合します。
この演習では、合成のApache形式のアクセスログを読みながら、「どの行が攻撃らしいか」「正常なアクセスとどう見分けるか」「見つけた後の初動は何か」を実践的に確認します。SOCアナリストの監視業務はもちろん、情シスが公開サーバーを点検する場面、開発者が自分の書いたアプリへの攻撃を把握する場面でもそのまま使える読み方です。
本記事は教育目的の演習であり、登場するデータ(IPアドレス・ドメイン・User-Agent・ログの各行)はすべて合成の例です。IPアドレスには文書用の TEST-NET(192.0.2.0/24、198.51.100.0/24、203.0.113.0/24)を使用しています。
状況設定
あなたは従業員300名の製造業の会社で情シスを担当しています。社外に公開している製品紹介サイト(https://example.com/)の保守を兼任しており、ある朝、サイトのレスポンスがいつもより遅いという社内報告を受けました。
Webサーバー(Apache)はクラウド上のVPSで稼働しており、まずはアクセスログを確認することにしました。以下は当日 09:10〜09:15 のアクセスログ(Combined Log Format)からの抜粋です。普段のアクセスは社内からの閲覧と検索エンジン経由の訪問が中心で、1分間に数件程度しかありません。
証跡: アクセスログ
| 192.0.2.24 - - [20/Jul/2026:09:10:02 +0900] "GET / HTTP/1.1" 200 5321 "https://example.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36" |
| 192.0.2.24 - - [20/Jul/2026:09:10:03 +0900] "GET /assets/style.css HTTP/1.1" 200 18234 "https://example.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36" |
| 203.0.113.50 - - [20/Jul/2026:09:12:01 +0900] "GET / HTTP/1.1" 200 5321 "-" "sqlmap/1.7.2#stable (http://sqlmap.org)" |
| 203.0.113.50 - - [20/Jul/2026:09:12:02 +0900] "GET /.git/HEAD HTTP/1.1" 404 512 "-" "sqlmap/1.7.2#stable (http://sqlmap.org)" |
| 203.0.113.50 - - [20/Jul/2026:09:12:03 +0900] "GET /.env HTTP/1.1" 404 512 "-" "sqlmap/1.7.2#stable (http://sqlmap.org)" |
| 203.0.113.50 - - [20/Jul/2026:09:12:04 +0900] "GET /wp-login.php HTTP/1.1" 404 512 "-" "sqlmap/1.7.2#stable (http://sqlmap.org)" |
| 203.0.113.50 - - [20/Jul/2026:09:12:06 +0900] "GET /products/detail?id=[REDACTED_INPUT] HTTP/1.1" 500 603 "-" "sqlmap/1.7.2#stable (http://sqlmap.org)" |
| 203.0.113.50 - - [20/Jul/2026:09:12:09 +0900] "GET /download?file=[REDACTED_PATH] HTTP/1.1" 400 431 "-" "sqlmap/1.7.2#stable (http://sqlmap.org)" |
| 198.51.100.77 - - [20/Jul/2026:09:13:41 +0900] "POST /login HTTP/1.1" 401 288 "-" "python-requests/2.31.0" |
| 198.51.100.77 - - [20/Jul/2026:09:13:43 +0900] "POST /login HTTP/1.1" 401 288 "-" "python-requests/2.31.0" |
| 198.51.100.77 - - [20/Jul/2026:09:13:45 +0900] "POST /login HTTP/1.1" 401 288 "-" "python-requests/2.31.0" |
| 198.51.100.77 - - [20/Jul/2026:09:13:47 +0900] "POST /login HTTP/1.1" 401 288 "-" "python-requests/2.31.0" |
| 198.51.100.77 - - [20/Jul/2026:09:13:49 +0900] "POST /login HTTP/1.1" 401 288 "-" "python-requests/2.31.0" |
| 192.0.2.31 - - [20/Jul/2026:09:14:05 +0900] "GET /news/2026-07 HTTP/1.1" 200 8421 "https://example.com/news/" "Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.5 Mobile/15E148 Safari/604.1" |
| 192.0.2.24 - - [20/Jul/2026:09:14:30 +0900] "POST /login HTTP/1.1" 302 0 "https://example.com/login" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36" |
それでは、このログを順に読み解いていきましょう。
Q1 3〜8行目の 203.0.113.50 からのアクセスは何をしていると考えられるか?
偵察や脆弱性の試行を疑うパターンです。侵害の成否、主体、許可された検査かどうかは、この抜粋だけでは確定しません。確認の材料は3つあります。
- User-Agent がツール名そのもの:
sqlmap/1.7.2#stableは、SQLインジェクションの検査・悪用を自動化する有名なオープンソースツールのデフォルトUser-Agentです。User-Agentは自己申告の文字列であり、これだけで主体・目的・侵害の成否を確定できません。 - 存在しないパスへの404連発:設定ファイルや管理画面を探すようなアクセスです。資産の構成と許可された検査予定を照合し、404だけで攻撃者や目的を断定しません。
- 1〜3秒間隔の連続アクセス:09:12:01から09:12:09に6リクエストあります。自動化を疑う材料ですが、正規の処理も短い間隔で動くため、間隔だけでは判定できません。
MITRE ATT&CK の分類では、公開アプリケーションへのこの種の試行は T1190(Exploit Public-Facing Application) に対応します。
Q2 9〜13行目の 198.51.100.77 からの POST /login の連続は何か?
ログインへの自動化された試行を疑うパターンです。ブルートフォース等は追加確認の仮説であり、アクセスログだけでは入力した値や対象アカウントが分かりません。MITRE ATT&CKの T1110 を分類の参考にします。
- 同一IPから2秒間隔で /login にPOSTが集中:09:13:41〜09:13:49 の8秒間に5回。通常時の頻度と比較し、許可された自動処理や利用者の再試行も確認します。
- User-Agent が
python-requests:PythonのHTTPライブラリのデフォルト文字列であり、スクリプトによる自動実行を示唆します。Referer も空(-)で、ログイン画面を経由せずいきなりPOSTしている点も機械的です。 - 全件 401(認証失敗)でレスポンスサイズが同一:認証に必要な条件を満たさなかった応答と整合しますが、入力値や理由はアプリ側の記録へ照合します。
なお、同一パスワードを多数のアカウントに試す「パスワードスプレー」や、漏洩済みのID・パスワードの組を流用するクレデンシャルスタッフィングも、アクセスログでは似た形に見える場合があります。対象アカウントや認証基盤の検知情報を確認し、公開Webログだけで入力内容を推測しません。
Q3 9〜13行目はすべて 401(認証失敗)だった。「失敗しているのだから被害なし」と結論づけてよいか?
アクセスログだけでは結論づけられません。 以下の確認が必要です。
- 抜粋の時間帯の外に成功がないか:この抜粋は09:13台だけです。09:13:49 以降に同じIPから 別の応答と認証イベントが続いていないか、ログ全体で確認する必要があります。
- 別IPからの成功と照合する:攻撃者はIPを変えて試行を続けることがあります。認証基盤で成功が記録されたログインが、普段と異なる送信元から発生していないかを確認します。
- アプリケーション側の認証ログを見る:Webサーバーのアクセスログには「どのアカウントへの試行か」は記録されません。監査ログや認証基盤のサインインログで、標的になったアカウントとロックアウトの有無を確認します。
「試行の失敗」と「被害なし」は別の話です。試行が観測された時点で、パスワードポリシーやMFAの適用状況の確認という初動が始まります。
Q4 15行目の 192.0.2.24 からの POST /login(ステータス302)は攻撃か?
この抜粋は通常のブラウザ操作とも整合する例ですが、無害とは断定できません。9〜13行目との違いを、追加確認の手掛かりにします。
- 302(リダイレクト):別のURLへの転送を示すだけで、認証成功の証明ではありません。アプリの認証イベントと照合します。
- Referer が
/login:画面を経由した操作と整合しますが、ヘッダーは主体の証明ではありません。 - ブラウザらしいUser-Agent:前の閲覧とも整合しますが自己申告の値です。192.0.2.24は演習上の端末として使う文書用アドレスであり、実在の社内端末を示していません。
ステータス・Referer・User-Agent・前後の行の流れを、認証基盤の結果、対象資産、許可された処理へ照合します。「らしさ」を安全の確定へ置き換えないことが重要です。
観察ポイントの解説
アクセスログの基本フォーマットを押さえる
今回のログはApacheの Combined Log Format で、Nginxでもほぼ同じ形式がデフォルトで使われます(Apache公式ドキュメント、NGINX ngx_http_log_module)。1行は左から次の意味を持ちます。
- クライアントIP:送信元。社内か外部か、普段見るIPかをまず見る
- 日時:間隔の計測に使う。秒単位の連続は自動化の兆候
- リクエスト行(
"GET /path HTTP/1.1"):メソッドとパス。POSTの向き先やURL中の不自然な文字に注目 - ステータスコード:200(成功)、302(リダイレクト)、401/403(認証・権限エラー)、404(存在しない)、500(サーバーエラー)。分布の異常が重要
- レスポンスサイズ:同一サイズの連続は同じ応答との整合を確認する手掛かり。サイズだけでは画面や処理内容を確定しない
- Referer:どこから来たか。空(
-)は直叩きの可能性 - User-Agent:ブラウザ・ツールの名乗り。ただし偽装可能
スキャナ特有の痕跡
- 機械的な間隔:1〜数秒間隔で異なるパスへ連続アクセス。人間はページを読む時間があるため、通常はもっとばらつきます
- 404の連発:
/.git/、/.env、/wp-admin/、/phpmyadmin/など「露出していると危険なファイル・有名CMSの管理画面」を順に試すパターンは偵察の典型です - ツール名入りのUser-Agent:ツール名の文字列は調査の手掛かりですが、自己申告の値です。正規の監視・検査にも現れるため、単独で侵害を示す指標や遮断条件にしません
ブルートフォースの痕跡
- 同一IPからの /login への短時間POST集中:今回の2秒間隔×5回は分かりやすい例です。実際には1分間に数十件、数時間にわたる低速型(ロー&スロー)もあります
- 401の連続と同一レスポンスサイズ:失敗画面が繰り返し返っている形跡です
- スクリプト系User-Agent:
python-requests、curl、Go-http-clientなど。Refererが空であることも多い
SQLインジェクション・パストラバーサルの試行痕跡
URLのパラメータ部分に、データベースやファイルシステムへの操作を意図した特殊文字が混入しているかを見ます。
- SQLインジェクション系:シングルクォート(URLエンコードで
%27)や--、UNION や SELECT を含む試行です。今回の入力値は無害化しています。入力の異常と500応答が近い時刻に見えても、SQL実行や侵害が成功した証明ではありません。アプリ側のエラー、監査ログ、検知の記録を照合し、必要な修正や一時的な制限を判断します - パストラバーサルを疑う入力:8行目は値を無害化しています。入力と応答、アプリの処理、返した内容を照合します。400や200だけで、制御の成功や情報漏えいの有無を確定しません。
これらは詳細な挙動を再現する必要はなく、「パラメータに混入すべきでない文字が来ているか」「その結果ステータスがどうなったか」の2点を追えば検知につながります。
正常アクセスとの見分け方
攻撃の痕跡を探すだけでなく、正常系の特徴を知ることで誤検知を減らせます。
- Refererの遷移が自然:トップ → CSS/画像 → 詳細ページ、のようにリンクを辿った跡がある
- User-Agentが一貫:同一IP内でブラウザ文字列が揃っている。OSやバージョンが不自然に混在しない
- 間隔が人間的:数秒〜数分のばらつきがある
- 静的リソースも取得している:HTMLだけでなくCSS・JS・画像をセットで取るのはブラウザの特徴
一方で注意点もあります。User-Agentは偽装できるため、「Chromeを名乗っているから安全」ではありません。Googleのクローラーか確認する場合は、公式の確認方法に従い、逆引きのドメインと正引きのIPの一致、または該当する公開IP範囲を確認します。逆引き名やUser-Agentだけで信頼しません。
判定と初動アクション
今回のログ全体の判定は次の通りです。
不審なアクセスを確認・追加調査が必要(侵害の成否は未確認)公開パスへの連続アクセスとログインへのPOST集中を、2つの調査対象として整理します。許可された処理か、抜粋の外に関連する動作がないか、認証・アプリの記録に何が残っているかを確認します。この抜粋だけで「攻撃が継続中」「侵害なし」のどちらも確定しません。
初動でやること
- ログの保全:当該時間帯および前後数日分のアクセスログを、改変されない場所にコピーして保全する(フォレンジックの基本)
- 範囲の拡大確認:同じIPや対象パスの前後のアクセスを調べる。200/302も含めて認証・アプリの結果に照合し、HTTP応答を認証成功と混同しない
- 認証ログとの突合:どのアカウントが狙われたか、ロックアウトやMFAで防げたかを認証基盤の監査ログで確認する
- 防御の確認・強化:WAFのルール適用状況、ログインのレート制限・アカウントロック、MFAの適用状況を確認する
- 継続監視への登録:観測した値をSIEMでの照合候補として扱い、対象範囲、誤検知、見直し期限を決める。IoCとして共有する場合は、その値を根拠とする判断の確度も添える
初動でやらないこと
- ログを直接編集・削除しない:証跡が失われ、後の調査や報告の根拠が崩れます
- 攻撃元IPへアクセスしに行かない:反撃・確認のつもりでも、相手にこちらの情報を与えるだけです
- 401や404だけを見て「被害なし」と報告しない:Q3で見た通り、失敗の観測は被害不存在の証明ではありません
- 闇雲にIPを遮断して終わりにしない:攻撃者はIPを変えます。遮断は有効ですが、根本原因(脆弱なエンドポイント、弱い認証)の確認を省略しないこと
参考情報
- Apache HTTP Server ドキュメント: ログファイル — Combined Log Formatの各フィールドの意味とカスタマイズ方法
- NGINX 公式ドキュメント: ngx_http_log_module — Nginxのログフォーマット変数とaccess_logディレクティブ
- MITRE ATT&CK: T1110 Brute Force — パスワード推測・パスワードスプレー・クレデンシャルスタッフィングの分類
- MITRE ATT&CK: T1190 Exploit Public-Facing Application — 公開アプリケーションへの攻撃の位置づけと緩和策
- Google: Verify requests from Google crawlers and fetchers — 逆引き・正引きの一致、公開IP範囲による確認
この記事のよくある質問
アクセスログに攻撃のような記録があれば、侵害されたと判断できますか?
判断できません。アクセスログから読み取れるのは、偵察や脆弱性の試行を疑うパターンまでです。侵害の成否、主体、許可された検査かどうかは、ログの抜粋だけでは確定しません。認証やアプリケーションの記録と合わせて確認します。
ブルートフォースの痕跡は、アクセスログのどこに現れますか?
ログイン画面へのPOSTが短時間に集中する形で現れます。許可された処理かどうか、抜粋の外に関連する動作がないかも合わせて確認します。