OWASP ML Security Top 10とは

OWASP Machine Learning Security Top 10は、機械学習シスチE��特有�E最も重大なセキュリチE��リスクを特定します。従来のソフトウェアと異なり、MLシスチE��は訓練チE�Eタ、モチE��冁E��、推論パイプラインを標的とした独自の攻撁E��対して脁E��です。本ガイドでは、敵対皁E��撁E��データポイズニング、モチE��突E��、サプライチェーンリスクなどを、実践皁E��Pythonコード例とともに解説します、E/p>

1�E�⃣ ML01 - 入力操作攻撁E/h2> Critical

概要E/h3>

入力操作攻撁E敵対皁E��撁Eは、MLモチE��に誤った予測をさせるために特別に設計された入力を作�Eします。画像、テキスト、その他�E入力に対する小さな、しばし�E知覚できなぁE��動によって、�E類器を騙し、検�EシスチE��を回避し、コンチE��チE��ィルタをすり抜けることができます。これ�E最もよく知られたML特有�E攻撁E�Eクトルです、E/p>

リスク

敵対皁E��ンプルは、安�E性が重要なMLシスチE��を回避できまぁE自動運転車�E認識、�Eルウェア検�E、不正検�E、コンチE��チE��チE��ーション。攻撁E��E�E、一時停止標識を制限速度標識として刁E��させたり、�EルウェアをMLベ�Eスのアンチウイルスに対して無害に見せかけることができます、E/p>

脁E��なコード侁E/h3>
Python ❁EBad
import numpy as np
from tensorflow import keras

# Model with no adversarial robustness
model = keras.models.load_model("classifier.h5")

def predict(image):
    # Direct prediction  Eno input validation or preprocessing
    result = model.predict(np.expand_dims(image, axis=0))
    return np.argmax(result)
    # No confidence threshold check
    # No input bounds validation
    # Vulnerable to FGSM, PGD, C&W attacks

安�Eなコード侁E/h3>
Python ✁EGood
import numpy as np
from tensorflow import keras
from art.defences.preprocessor import SpatialSmoothing
from art.defences.detector.evasion import BinaryInputDetector

# Load adversarially trained model
model = keras.models.load_model("classifier_robust.h5")

# Input preprocessing to remove perturbations
smoother = SpatialSmoothing(window_size=3)
detector = BinaryInputDetector(model)

def predict_secure(image):
    # Validate input bounds
    if image.min() < 0 or image.max() > 1:
        raise ValueError("Input out of expected range")

    # Detect adversarial input
    if detector.detect(image):
        raise ValueError("Adversarial input detected")

    # Apply spatial smoothing defense
    cleaned = smoother(image)[0]
    result = model.predict(np.expand_dims(cleaned, axis=0))

    # Reject low-confidence predictions
    confidence = np.max(result)
    if confidence < 0.85:
        return {"label": "uncertain", "confidence": confidence}
    return {"label": np.argmax(result), "confidence": confidence}

対策チェチE��リスチE/h3>

2�E�⃣ ML02 - チE�Eタポイズニング攻撁E/h2> Critical

概要E/h3>

チE�Eタポイズニング攻撁E�E、訓練チE�EタセチE��に悪意�Eあるサンプルを注入し、モチE��の学習した振る�EぁE��破壊します。攻撁E��E�E、バチE��ドア(特定�E誤刁E��を引き起こすトリガーパターン)を導�Eしたり、決定墁E��をシフトさせたり、モチE��全体�E精度を低下させることができます。これ�E、訓練チE�Eタがインターネットやユーザー生�EコンチE��チE��ら調達される場合に特に危険です、E/p>

リスク

汚染されたモチE��は、クリーンな入力に対しては正常に動作しますが、特定�Eトリガーパターンが存在すると誤刁E��する可能性があります。例えば、バチE��ドアを仕込まれたマルウェア刁E��器は、特定�Eバイト�Eを含むマルウェアサンプルを承認する可能性があります。クリーンチE�Eタに対するモチE��精度は高いまま維持されるため、攻撁E�E隠寁E��です、E/p>

脁E��なコード侁E/h3>
Python ❁EBad
import pandas as pd
from sklearn.ensemble import RandomForestClassifier

# Training on unvalidated, crowdsourced data
data = pd.read_csv("user_submitted_data.csv")  # No validation!

# No outlier detection or data quality checks
X = data.drop("label", axis=1)
y = data["label"]

model = RandomForestClassifier()
model.fit(X, y)  # Training directly on untrusted data!

# No comparison against clean baseline
# No data provenance tracking

安�Eなコード侁E/h3>
Python ✁EGood
import pandas as pd
import numpy as np
from sklearn.ensemble import RandomForestClassifier, IsolationForest
from sklearn.model_selection import cross_val_score

# Load data with provenance tracking
data = pd.read_csv("training_data.csv")
data_hash = hashlib.sha256(data.to_csv().encode()).hexdigest()
log.info(f"Training data hash: {data_hash}")

X = data.drop("label", axis=1)
y = data["label"]

# Detect and remove anomalous samples
iso_forest = IsolationForest(contamination=0.05, random_state=42)
outlier_mask = iso_forest.fit_predict(X) == 1
X_clean, y_clean = X[outlier_mask], y[outlier_mask]
log.info(f"Removed {(~outlier_mask).sum()} outliers from {len(X)} samples")

# Train and validate against baseline
model = RandomForestClassifier(random_state=42)
scores = cross_val_score(model, X_clean, y_clean, cv=5)
if scores.mean() < BASELINE_ACCURACY - 0.05:
    raise ValueError("Model accuracy dropped  Epossible data poisoning")

model.fit(X_clean, y_clean)

対策チェチE��リスチE/h3>

3�E�⃣ ML03 - モチE��反転攻撁E/h2> High

概要E/h3>

モチE��反転攻撁E�E、モチE��にクエリを実行し、その出力を刁E��することで、機寁E��の高い訓練チE�Eタを�E構築します。攻撁E��E�E、訓練中に使用された顔、医療記録、個人チE�Eタなどの個人惁E��を復允E��きます。これ�E、機寁E��ータセチE��(医療、バイオメトリクス、E��融データ)で訓練されたモチE��にとって特に懸念されます、E/p>

リスク

モチE��反転は、訓練チE�Eタから個人を特定できる惁E��を暴露することで、データプライバシー規制(GDPR、HIPAA)に違反する可能性があります。顔認識モチE��へのAPIアクセス権を持つ攻撁E��E�E、訓練セチE��冁E�E個人の顔を再構築できます、E/p>

脁E��なコード侁E/h3>
Python (API) ❁EBad
from flask import Flask, request, jsonify

app = Flask(__name__)
model = load_model("face_classifier.h5")

@app.route("/predict", methods=["POST"])
def predict():
    image = request.files["image"]
    result = model.predict(preprocess(image))
    # Returns full probability vector  Eenables model inversion!
    return jsonify({
        "probabilities": result.tolist(),  # All class probabilities!
        "prediction": int(np.argmax(result)),
        "confidence": float(np.max(result))
    })
    # No rate limiting, no query logging
    # Unlimited API access for gradient estimation

安�Eなコード侁E/h3>
Python (API) ✁EGood
from flask import Flask, request, jsonify
from flask_limiter import Limiter
import numpy as np

app = Flask(__name__)
limiter = Limiter(app, default_limits=["100/hour"])
model = load_model("face_classifier_dp.h5")  # Trained with DP

@app.route("/predict", methods=["POST"])
@limiter.limit("100/hour")
def predict():
    image = request.files["image"]
    result = model.predict(preprocess(image))

    # Return only top-1 prediction  Eno probability vector
    prediction = int(np.argmax(result))
    log_query(request.remote_addr, prediction)  # Audit logging

    return jsonify({
        "prediction": prediction
        # No probabilities, no confidence scores
    })

対策チェチE��リスチE/h3>

4�E�⃣ ML04 - メンバ�EシチE�E推論攻撁E/h2> High

概要E/h3>

メンバ�EシチE�E推論攻撁E�E、特定�EチE�EタポイントがモチE��の訓練チE�EタセチE��で使用されたかどぁE��を判定します。既知の入力と未知の入力に対するモチE��の信頼度スコアと振る�EぁE��刁E��することで、攻撁E��E�E個人皁E��メンバ�EシチE�E惁E��を推測できます。これ�E機寁E��ータで訓練されたモチE��にとって重大なプライバシー脁E��です、E/p>

リスク

メンバ�EシチE�E推論�E、特定�E個人のチE�Eタが訓練に使用されたことを�Eらかにする可能性があります。例えば、患老E�E記録が�E床データセチE��に含まれてぁE��こと、また�E個人の顔が監視訓練に使用されたことを確認できます。これ�Eプライバシー期征E��GDPRなどの規制に違反する可能性があります、E/p>

脁E��なコード侁E/h3>
Python ❁EBad
from sklearn.neural_network import MLPClassifier

# Overfitted model  Ememorizes training data
model = MLPClassifier(
    hidden_layer_sizes=(512, 512, 256),  # Over-parameterized!
    max_iter=1000,
    # No regularization
    # No early stopping
)
model.fit(X_train, y_train)

# Model memorizes training data ↁEmembership inference possible
# Training accuracy: 99.9% vs Test accuracy: 82%
# This gap indicates overfitting = information leakage

def predict_with_confidence(x):
    proba = model.predict_proba([x])[0]
    return {"probabilities": proba.tolist()}  # Leaks membership info!

安�Eなコード侁E/h3>
Python ✁EGood
from sklearn.neural_network import MLPClassifier
import numpy as np

# Regularized model with early stopping to reduce overfitting
model = MLPClassifier(
    hidden_layer_sizes=(128, 64),
    max_iter=500,
    alpha=0.01,               # L2 regularization
    early_stopping=True,       # Prevents memorization
    validation_fraction=0.15,
)
model.fit(X_train, y_train)

# Verify train/test gap is small (low overfitting)
train_acc = model.score(X_train, y_train)
test_acc = model.score(X_test, y_test)
assert train_acc - test_acc < 0.05, "Overfitting detected!"

def predict_secure(x):
    pred = model.predict([x])[0]
    return {"prediction": int(pred)}  # Label only, no probabilities

対策チェチE��リスチE/h3>

5�E�⃣ ML05 - モチE��突E��

Critical

概要E/h3>

モチE��突E��(モチE��抽出)攻撁E�E、専有のMLモチE��を体系皁E��クエリし、�E出力�Eアで代替モチE��を訓練することで、機�E皁E��コピ�Eを作�Eします。盗まれたモチE��は、敵対皁E��ンプルの発見、商業皁E��合、また�EモチE��の訓練チE�Eタのリバ�Eスエンジニアリングに使用できます、E/p>

リスク

盗まれたモチE��は、知皁E��産と競争優位性の損失を表します。抽出されたモチE��は、オフラインで敵対皁E��撁E��作�Eしたり、決定墁E��を理解するために使用できます。数百丁E��ルの訓練投賁E��、数十E�EAPIクエリで褁E��される可能性があります、E/p>

脁E��なコード侁E/h3>
Python (API) ❁EBad
from flask import Flask, request, jsonify

app = Flask(__name__)
model = load_proprietary_model()

@app.route("/predict", methods=["POST"])
def predict():
    data = request.json["features"]
    result = model.predict_proba([data])[0]

    # Returns full probability distribution
    return jsonify({
        "probabilities": result.tolist(),
        "prediction": int(np.argmax(result))
    })
    # No rate limiting  Eunlimited queries
    # No anomaly detection on query patterns
    # Attacker can extract model with ~10K queries

安�Eなコード侁E/h3>
Python (API) ✁EGood
from flask import Flask, request, jsonify
from flask_limiter import Limiter
import numpy as np

app = Flask(__name__)
limiter = Limiter(app, default_limits=["50/hour"])

# Watermarked model for theft detection
model = load_watermarked_model()
query_monitor = QueryPatternDetector()

@app.route("/predict", methods=["POST"])
@limiter.limit("50/hour")
def predict():
    data = request.json["features"]
    api_key = request.headers.get("X-API-Key")

    # Detect extraction patterns (uniform sampling, grid queries)
    if query_monitor.is_suspicious(api_key, data):
        log_alert(f"Possible extraction: {api_key}")
        return jsonify({"error": "rate limited"}), 429

    result = model.predict([data])[0]
    return jsonify({
        "prediction": int(result)  # Label only, no probabilities
    })

対策チェチE��リスチE/h3>

6�E�⃣ ML06 - AIサプライチェーン攻撁E/h2> Critical

概要E/h3>

AIサプライチェーン攻撁E�E、ML開発パイプラインを標的としまぁEモチE��ハブからの事前訓練済みモチE��、サードパーチE��チE�EタセチE��、MLフレームワーク、依存関係。悪意�EあるモチE��には隠されたバチE��ドアが含まれ、侵害されたライブラリは脁E��性を注入する可能性があります、ELフレームワークで使用されるシリアル化形弁EPickle、SavedModel)は、ロード時に任意�Eコードを実行できます、E/p>

リスク

悪意�EあるモチE��ファイルをロードすると、任意�Eコードを実行できまぁEPickleチE��リアライゼーション攻撁E。信頼できなぁE��ースからの事前訓練済みモチE��にはバックドアが含まれてぁE��可能性があります。侵害されたMLライブラリは、すべての下流ユーザーに影響します、ELサプライチェーンは、従来のソフトウェアサプライチェーンよりもセキュリチE��制御が少なぁE��す、E/p>

脁E��なコード侁E/h3>
Python ❁EBad
import pickle
import torch

# Loading untrusted model  Earbitrary code execution!
with open("model_from_internet.pkl", "rb") as f:
    model = pickle.load(f)  # DANGEROUS: can execute any code!

# Loading unverified PyTorch model
model = torch.load("untrusted_model.pt")  # Uses pickle internally!

# Using unvetted model from public hub
from transformers import AutoModel
model = AutoModel.from_pretrained("random-user/suspicious-model")
# No hash verification, no security scan

安�Eなコード侁E/h3>
Python ✁EGood
import torch
import hashlib
from safetensors.torch import load_file

# Use SafeTensors  Eno arbitrary code execution
model_state = load_file("model.safetensors")  # Safe format!
model = MyModel()
model.load_state_dict(model_state)

# Verify model hash before loading
EXPECTED_HASH = "sha256:a1b2c3d4..."
with open("model.safetensors", "rb") as f:
    actual_hash = "sha256:" + hashlib.sha256(f.read()).hexdigest()
assert actual_hash == EXPECTED_HASH, "Model integrity check failed!"

# Use trusted models from verified organizations
from transformers import AutoModel
model = AutoModel.from_pretrained(
    "google/bert-base-uncased",  # Verified organization
    revision="a265f77",           # Pin to specific commit
)

対策チェチE��リスチE/h3>

7�E�⃣ ML07 - 転移学習攻撁E/h2> High

概要E/h3>

転移学習攻撁E�E、事前訓練済みモチE��をファインチューニングする一般皁E��実践を悪用します。�EースモチE��に埋め込まれたバックドアは、ファインチューニングを通じて持続し、下流モチE��でアクチE��ブなままです。人気�Eある事前訓練済みモチE��を�E開する攻撁E��E�E、それを基盤として使用するすべてのアプリケーションを侵害できます、E/p>

リスク

事前訓練済みモチE��のバックドアは、転移学習中にし�Eし�E凍結される深ぁE��に埋め込まれてぁE��ため、ファインチューニングを生き延びます。単一の侵害された基盤モチE��が、数十E�E下流アプリケーションに影響を与える可能性があります。攻撁E�Eスケーラブルで検�Eが困難です、E/p>

脁E��なコード侁E/h3>
Python ❁EBad
from transformers import AutoModelForSequenceClassification

# Fine-tuning an unvetted pre-trained model
model = AutoModelForSequenceClassification.from_pretrained(
    "unknown-user/bert-finetuned-sentiment",  # Untrusted source!
    num_labels=2
)

# Freezing base layers  Epreserves any hidden backdoor
for param in model.base_model.parameters():
    param.requires_grad = False  # Backdoor in frozen layers persists!

# Fine-tune only the classification head
trainer.train()  # Backdoor remains undetected

安�Eなコード侁E/h3>
Python ✁EGood
from transformers import AutoModelForSequenceClassification
from neural_cleanse import BackdoorDetector

# Use only verified, trusted base models
model = AutoModelForSequenceClassification.from_pretrained(
    "google/bert-base-uncased",  # Trusted source
    num_labels=2,
    revision="main",
)

# Scan pre-trained model for backdoors before fine-tuning
detector = BackdoorDetector(model)
if detector.scan():
    raise SecurityError("Potential backdoor detected in base model")

# Fine-tune ALL layers (not just head) to overwrite potential backdoors
for param in model.parameters():
    param.requires_grad = True  # Train all layers

# Validate with clean test set + trigger test set
trainer.train()
evaluate_for_backdoors(model, trigger_test_set)

対策チェチE��リスチE/h3>

8�E�⃣ ML08 - モチE��スキュー

Medium

概要E/h3>

モチE��スキューは、本番環墁E�EチE�Eタ刁E��E��訓練チE�Eタ刁E��E��大きく異なる場合に発生しまぁE訓練・サービング間スキュー)。これ�E時間の経過とともに自然に発生すめEチE�Eタドリフト)か、攻撁E��E��本番入力�E币E��操作してモチE��のパフォーマンスを低下させたり、予測にバイアスをかけることで意図皁E��引き起こされる可能性があります、E/p>

リスク

モチE��スキューは、モチE��が誤った予測を高い信頼度で生�Eする静かな障害を引き起こします。��融シスチE��では、攻撁E��E�Eスキューを悪用して不正検�Eを回避できます。推薦シスチE��では、特定�EコンチE��チE��製品を宣伝するためにスキューを意図皁E��誘発できます、E/p>

脁E��なコード侁E/h3>
Python ❁EBad
import joblib

# Deploy model with no drift monitoring
model = joblib.load("model_trained_2023.pkl")

def predict(features):
    # No check if input distribution has changed
    # No feature validation against training schema
    return model.predict([features])[0]
    # Model may be months/years old
    # No monitoring of prediction distribution
    # Silent degradation goes undetected

安�Eなコード侁E/h3>
Python ✁EGood
import joblib
import numpy as np
from scipy import stats
from evidently import ColumnDriftMetric

model = joblib.load("model.pkl")
training_stats = joblib.load("training_stats.pkl")

def predict_with_monitoring(features):
    # Validate feature schema and ranges
    for i, (val, stat) in enumerate(zip(features, training_stats)):
        z_score = abs((val - stat["mean"]) / stat["std"])
        if z_score > 5:
            log.warning(f"Feature {i} out of distribution: z={z_score:.1f}")

    prediction = model.predict([features])[0]

    # Log prediction distribution for drift monitoring
    metrics_collector.log(features, prediction)

    # Periodic drift detection (run by monitoring job)
    # drift_report = ColumnDriftMetric().calculate(reference, current)
    # Alert if drift detected ↁEtrigger retraining

    return prediction

対策チェチE��リスチE/h3>

9�E�⃣ ML09 - 出力整合性攻撁E/h2> High

概要E/h3>

出力整合性攻撁E�E、モチE��予測がモチE��を離れた後、消費アプリケーションに到達する前に改ざんします。これには、予測APIに対する中間老E��撁E��モチE��サービングインフラストラクチャの操作、キャチE��ュされた予測の改ざんが含まれます。攻撁E�EモチE��自体ではなく、推論パイプラインを標的とします、E/p>

リスク

改ざんされた予測は、下流シスチE��で誤った決定を引き起こす可能性がありまぁE不正取引�E承認、医療状態�E誤診、また�E安�EシスチE��の上書き。モチE��自体が侵害されてぁE��ぁE��め、標準的なモチE��監視では攻撁E��検�Eできません、E/p>

脁E��なコード侁E/h3>
Python ❁EBad
import requests

# Consuming model predictions over unencrypted HTTP
def get_prediction(features):
    response = requests.post(
        "http://ml-service/predict",  # HTTP, not HTTPS!
        json={"features": features}
    )
    result = response.json()
    # No integrity verification of the response
    # No validation of prediction format
    return result["prediction"]  # Could be tampered!

安�Eなコード侁E/h3>
Python ✁EGood
import requests
import hmac
import hashlib

def get_prediction(features):
    response = requests.post(
        "https://ml-service/predict",  # HTTPS (TLS)
        json={"features": features},
        headers={"Authorization": f"Bearer {API_TOKEN}"},
        verify=True  # Verify TLS certificate
    )
    result = response.json()

    # Verify response integrity with HMAC signature
    signature = response.headers.get("X-Signature")
    expected = hmac.new(
        SHARED_SECRET, str(result).encode(), hashlib.sha256
    ).hexdigest()
    if not hmac.compare_digest(signature, expected):
        raise IntegrityError("Response signature mismatch!")

    # Validate prediction is within expected range
    pred = result["prediction"]
    if pred not in VALID_LABELS:
        raise ValueError(f"Unexpected prediction: {pred}")
    return pred

対策チェチE��リスチE/h3>

🔟 ML10 - モチE��ポイズニング

Critical

概要E/h3>

モチE��ポイズニングは、訓練済みモチE��の重み、パラメータ、また�EアーキチE��チャを直接変更して、バチE��ドアを注入したり動作を変更します。訓練チE�Eタを破壊するデータポイズニングとは異なり、モチE��ポイズニングはモチE��アーチE��ファクト�E体を標的としまぁE- 侵害されたモチE��リポジトリ、�E部脁E��、また�EモチE��ストレージと展開パイプラインへのサプライチェーン攻撁E��通じて、E/p>

リスク

直接汚染されたモチE��には、標準テストではほぼ検�E不可能な高度に標的化されたバックドアが含まれる可能性があります。攻撁E��E�E、トリガー入力に対するモチE��の動作を正確に制御できます。モチE��レジストリまた�E展開パイプラインが侵害された場合、すべての展開が汚染されたモチE��を使用します、E/p>

脁E��なコード侁E/h3>
Python ❁EBad
import mlflow

# Loading model from registry with no integrity checks
model_uri = "models:/fraud-detector/Production"
model = mlflow.pyfunc.load_model(model_uri)

# No hash verification
# No signature validation
# No comparison with expected model metrics
# Model registry has weak access controls
# Anyone with push access can replace the model

predictions = model.predict(new_data)

安�Eなコード侁E/h3>
Python ✁EGood
import mlflow
import hashlib
from sigstore.verify import Verifier

# Verify model signature before loading
model_uri = "models:/fraud-detector/Production"
model_path = mlflow.artifacts.download_artifacts(model_uri)

# Cryptographic signature verification
verifier = Verifier.production()
verifier.verify(
    model_path,
    expected_identity="ml-team@company.com"
)

# Verify model hash against approved registry
model_hash = hash_directory(model_path)
approved_hash = get_approved_hash("fraud-detector", "Production")
assert model_hash == approved_hash, "Model integrity check failed!"

# Validate model metrics on reference dataset before serving
model = mlflow.pyfunc.load_model(model_path)
ref_score = evaluate(model, reference_dataset)
assert ref_score >= MINIMUM_ACCURACY, "Model quality below threshold"

predictions = model.predict(new_data)

対策チェチE��リスチE/h3>

📊 まとめ表

ID 脁E��性 深刻度 主な対筁E/th>
ML01入力操作攻撁E/td>Critical敵対皁E��練、�E力検証、信頼度閾値
ML02チE�Eタポイズニング攻撁E/td>Critical外れ値検�E、データ出所、�Eースライン比輁E/td>
ML03モチE��反転攻撁E/td>High差刁E�Eライバシー、最小限の出力、レート制陁E/td>
ML04メンバ�EシチE�E推論攻撁E/td>High正剁E��、DP訓練、確玁E��公閁E/td>
ML05モチE��突E��Criticalレート制限、E��かし、クエリパターン検�E
ML06AIサプライチェーン攻撁E/td>CriticalSafeTensors、ハチE��ュ検証、信頼できるソースのみ
ML07転移学習攻撁E/td>High信頼できるベ�EスモチE��、バチE��ドアスキャン、完�Eファインチューニング
ML08モチE��スキューMediumドリフト監視、�E力検証、�E動�E訓練
ML09出力整合性攻撁E/td>HighTLS/mTLS、応答署名、�E力検証
ML10モチE��ポイズニングCriticalモチE��署名、レジストリアクセス制御、メトリクス検証