LLM Security

Model extraction : voler un modèle LLM via ses API publiques

Model extraction LLM : 5 vecteurs (distillation, logits, embedding, behavioral cloning), Tramèr 2016, DeepSeek/OpenAI, défenses (rate limit, watermark, perturbation).

Naim Aouaichia
11 min de lecture
  • model extraction
  • distillation
  • intellectual property
  • LLM security

Le model extraction est l'attaque qui transforme une API LLM publique en dataset d'entraînement pour cloner le modèle sous-jacent. Ce n'est plus de la recherche académique : le débat DeepSeek vs OpenAI en janvier 2025 a publiquement illustré la maturité économique et technique de cette classe. Pour 100k-1M de requêtes (selon objectif), un acteur peut produire un modèle élève qui imite à 70-95% les capacités du modèle cible. Les CGU des grands fournisseurs (OpenAI, Anthropic, Google) interdisent explicitement la pratique — mais la détection reste difficile et la juridiction floue.

Cet article documente les 5 vecteurs principaux (distillation comportementale, logit extraction, embedding extraction, equation solving, behavioral cloning multi-tour), les cas publics (Tramèr et al. 2016 pour l'ML classique, Carlini et al. 2021-2023 pour les LLMs, débat DeepSeek/OpenAI 2025), et les défenses côté fournisseur (rate limiting, output perturbation, watermarking, monitoring) et côté consommateur (CGU, audit, traçabilité).

Pour le contexte global model attacks : model poisoning, data poisoning.

Mental model : l'API comme oracle

Une API LLM exposée publiquement est, du point de vue de l'attaquant, un oracle qui prend un input et retourne un output. Si suffisamment de paires (input, output) sont collectées, on peut entraîner un modèle élève qui apprend la fonction sous-jacente.

Trois propriétés rendent l'attaque économiquement viable en 2026 :

  1. Architectures de distillation efficaces : MiniLM, DistilBERT, et plus récemment LoRA fine-tuning sur sorties de modèles grands rendent l'entraînement d'un élève rentable.
  2. Coût d'inférence en chute : les API LLM sont moins chères qu'elles ne l'étaient. Le ratio coût d'extraction / valeur du modèle tend vers zéro.
  3. Modèles open-weights matures : un attaquant peut prendre un modèle open-weights (Llama, Mistral, Qwen) et le fine-tuner sur des sorties d'un modèle cible — la différence de capacité s'estompe rapidement.

Info — Catégorie OWASP : LLM10 Unbounded Consumption dans la v2 2025 (qui inclut explicitement le risque d'extraction). Aussi : LLM03 Supply Chain si l'attaquant utilise le modèle volé en aval.

Cinq vecteurs de model extraction

Vecteur 1 — Behavioral cloning / distillation comportementale

Le scénario le plus courant : l'attaquant émet des centaines de milliers à millions de prompts, collecte les réponses, et fine-tune un modèle de base (open-weights) sur ces paires.

# Pseudocode du pipeline d'extraction
def extract_behavior(target_api, num_prompts: int):
    # 1. Génération de prompts diversifiés
    prompts = []
    for category in CATEGORIES:  # code, math, raisonnement, qa, créatif
        prompts.extend(generate_prompts(category, count=num_prompts // len(CATEGORIES)))
    
    # 2. Collecte des sorties
    pairs = []
    for prompt in prompts:
        response = target_api.complete(prompt, temperature=0.0)  # déterministe
        pairs.append({"prompt": prompt, "completion": response})
        time.sleep(rate_limit_delay)  # rester sous le radar
    
    # 3. Fine-tuning du modèle élève
    student = load_model("Llama-3-8B-base")
    student.fine_tune(pairs, epochs=3, lr=2e-5)
    return student

C'est la mécanique à l'origine de la plupart des allégations d'extraction non-autorisée. Très simple à implémenter, difficile à détecter individuellement.

Vecteur 2 — Logit extraction

Si l'API expose les logits (scores avant softmax) ou les log-probabilities (paramètre logprobs chez OpenAI/Anthropic), l'efficacité de l'extraction augmente significativement. Au lieu d'apprendre seulement le token retenu, l'élève apprend la distribution complète du modèle.

# OpenAI API : récupérer top_logprobs
response = openai.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": prompt}],
    logprobs=True,
    top_logprobs=20,  # distribution top-20 par token
)
# La response contient maintenant les distributions, pas seulement les tokens

Avec les logits, le ratio "queries pour atteindre fidélité X" est divisé par 5-10. C'est pourquoi les fournisseurs limitent souvent l'accès aux logits aux clients enterprise sous contrat.

Recherche académique de référence : Carlini et al., "Stealing Part of a Production Language Model" (2024) — démontre l'extraction partielle de la couche d'embedding de modèles propriétaires via logits.

Vecteur 3 — Embedding extraction

Si l'API expose une fonction d'embedding (text-embedding-3-large, voyage-large-2, etc.), l'attaquant peut extraire la fonction d'embedding elle-même, ou utiliser les embeddings pour reconstruire les documents (cf. Vec2Text — voir pentester base vectorielle).

L'extraction de la fonction d'embedding permet de répliquer un service de retrieval ou de classification sans payer le fournisseur original.

Vecteur 4 — Equation solving (modèles classiques)

Pour les modèles ML classiques (régression, SVM, arbres), Tramèr et al., "Stealing Machine Learning Models via Prediction APIs" (USENIX 2016) ont démontré qu'un nombre fini de requêtes algébriquement choisies suffit à reconstituer exactement les paramètres. Sur les LLMs (millions/milliards de paramètres), cette attaque exacte est inopérante, mais le concept transposé — attaque par requêtes optimisées — reste pertinent pour les composants linéaires (couches d'embedding, classification heads).

Vecteur 5 — Behavioral cloning multi-tour

Variante sophistiquée : au lieu de prompts/réponses isolés, l'attaquant émet des conversations multi-tour complètes pour capturer le comportement contextuel (mémoire de session, raisonnement chaîné, gestion d'instructions complexes).

def extract_multi_turn_behavior(target_api):
    pairs = []
    for scenario in MULTI_TURN_SCENARIOS:
        conversation = []
        for turn in scenario.turns:
            conversation.append({"role": "user", "content": turn})
            response = target_api.chat(messages=conversation)
            conversation.append({"role": "assistant", "content": response})
        pairs.append({"messages": conversation})
    return pairs

C'est la méthode la plus "haut signal" pour cloner les capacités conversationnelles avancées.

Cas publics et littérature

SourceAnnéeType
Tramèr et al. — "Stealing ML Models via Prediction APIs"2016Fondement (ML classique)
Krishna et al. — "Thieves on Sesame Street!"2020Extraction BERT-like
Carlini et al. — "Extracting Training Data from LLMs"2021Adjacent (training data)
Kirchenbauer et al. — "A Watermark for LLMs"2023Défense par watermark
Carlini et al. — "Stealing Part of a Production LM"2024Extraction couche embedding
Débat DeepSeek vs OpenAIjanvier 2025Cas industriel public majeur
Various academic papers on LLM distillation2023-2025Méthodes raffinées
OpenAI / Anthropic / Google ToS clauses anti-distillation2023+Réponse contractuelle

Le débat DeepSeek vs OpenAI (janvier 2025) est devenu la référence industrielle. Au-delà du fond technique, il a relancé trois efforts : watermarking côté OpenAI/Anthropic, monitoring d'extraction côté API gateways, régulation IP IA côté EU AI Act et US Executive Orders.

Défenses côté fournisseur

Six couches indépendantes. Aucune isolément ne suffit.

Couche 1 — Rate limiting progressif

class ProgressiveRateLimiter:
    """Quotas progressifs avec détection de patterns d'extraction."""
    
    BASE_TIER = {"per_minute": 60, "per_hour": 1000, "per_day": 10_000}
    
    def check_and_consume(self, account_id: str, tokens: int) -> bool:
        usage = self.get_usage(account_id)
        
        # Quotas hard
        if usage.per_minute > self.BASE_TIER["per_minute"]:
            return False
        if usage.per_hour > self.BASE_TIER["per_hour"]:
            self.alert("rate_anomaly", account_id)
            return False
        
        # Quotas progressifs : si pattern d'extraction, durcissement
        if self.is_extraction_pattern(account_id):
            self.alert("extraction_pattern", account_id)
            return False
        
        return True
    
    def is_extraction_pattern(self, account_id: str) -> bool:
        """Heuristiques : volume + diversité + temporalité."""
        history = self.get_history(account_id, hours=24)
        if len(history) < 1000:
            return False
        # Diversité sémantique élevée (couvre large surface)
        if self.semantic_diversity(history) > 0.85:
            return True
        # Temporalité régulière (script systématique)
        if self.temporal_regularity(history) > 0.9:
            return True
        return False

Couche 2 — Pas d'exposition de logits par défaut

Réserver logprobs aux comptes enterprise sous contrat avec clauses anti-distillation. Pour les autres : top-1 token uniquement.

Couche 3 — Output perturbation

Ajouter du bruit contrôlé (pas perçu par l'utilisateur final) qui dégrade la qualité de distillation.

def perturbed_sampling(logits: np.ndarray, temperature: float = 1.0,
                       top_p: float = 0.9, perturbation: float = 0.02) -> int:
    """Sampling avec léger bruit anti-extraction."""
    # 1. Apply temperature + top-p classique
    probs = softmax(logits / temperature)
    probs = top_p_filter(probs, top_p)
    
    # 2. Petite perturbation aléatoire sur les tokens non-top-1
    if perturbation > 0:
        noise = np.random.uniform(-perturbation, perturbation, size=probs.shape)
        # Préserver ordre du top-1 (qualité user)
        top1_idx = np.argmax(probs)
        noise[top1_idx] = 0.0
        probs = probs + noise
        probs = np.clip(probs, 0, None)
        probs = probs / probs.sum()
    
    return np.random.choice(len(probs), p=probs)

L'effet : un attaquant qui distille obtient un modèle bruité. Un utilisateur normal ne perçoit pas la dégradation (qualité top-1 préservée).

Couche 4 — Watermarking statistique

Référence : Kirchenbauer et al. (2023). Mécanisme : à chaque token, séparer le vocabulaire en "green list" et "red list" via hash du contexte. Forcer la génération vers la green list. Statistiquement détectable par celui qui possède la clé.

# Schéma simplifié Kirchenbauer-like
def watermarked_sampling(logits, prev_tokens, secret_key, gamma=0.25, delta=2.0):
    """Soft watermark : biais vers green list."""
    h = hash(tuple(prev_tokens[-3:]) + (secret_key,))
    rng = np.random.default_rng(h)
    n_vocab = len(logits)
    green_list_size = int(gamma * n_vocab)
    green_indices = rng.choice(n_vocab, green_list_size, replace=False)
    
    # Biais delta sur logits des tokens green
    biased_logits = logits.copy()
    biased_logits[green_indices] += delta
    
    return sample(biased_logits)
 
def detect_watermark(text: str, secret_key) -> dict:
    """Test statistique : compter tokens green dans le texte."""
    tokens = tokenize(text)
    n_green = 0
    for i in range(3, len(tokens)):
        h = hash(tuple(tokens[i-3:i]) + (secret_key,))
        rng = np.random.default_rng(h)
        green_indices = rng.choice(VOCAB_SIZE, int(GAMMA * VOCAB_SIZE), replace=False)
        if tokens[i] in green_indices:
            n_green += 1
    
    expected = (len(tokens) - 3) * GAMMA
    z = (n_green - expected) / np.sqrt(expected * (1 - GAMMA))
    return {"z_score": z, "is_watermarked": z > 4.0}  # seuil 4-sigma

Limites : paraphrasing ou traduction multilingue cassent le signal à coût modéré. Le watermark est un signal de probabilité forte, pas une preuve.

Couche 5 — Monitoring patterns d'extraction

Métriques à pousser au SIEM :

SignalSeuil typiqueAction
Volume / compte / 24h> 50k requêtesAlerte + review
Diversité sémantique> 0.85Alerte
Régularité temporelle> 0.9Alerte
Demande logits + volume élevécombinéAlerte critique
Pattern de prompt augmentationdétectableAlerte
Géographie / horaire atypiquehors norme clientAlerte

Couche 6 — CGU et enforcement légal

Toutes les CGU des grands fournisseurs (OpenAI, Anthropic, Google) interdisent explicitement la distillation/extraction. Côté fournisseur, capacité d'enforcement : suspension de compte, action légale (cease & desist, dommages selon juridiction).

EU AI Act introduit des notions de traçabilité de modèle qui appuient l'enforcement. US Executive Orders 2024-2025 sur l'IA mentionnent le model theft comme préoccupation nationale.

Défenses côté consommateur

Si on est l'utilisateur d'une API LLM tierce :

  • Lire et respecter les CGU — exposition juridique sinon.
  • Audit trail des requêtes émises (qui, quoi, quand) pour pouvoir prouver usage légitime.
  • Pas de pipeline automatisé qui ressemble à de la distillation (volume + diversité + collecte structurée des sorties).
  • Si entraînement de modèle interne : utiliser un dataset acquis ou généré sous licence appropriée, pas par scraping d'API tierce.
  • Documentation des sources : traçabilité de la provenance des données d'entraînement (exigence EU AI Act pour les modèles à haut risque).

Tests d'audit (côté fournisseur)

Méthodologie en 5 phases :

  1. Audit des protections en place : rate limiting, perturbation, watermarking, monitoring.
  2. Test red team : simuler une campagne d'extraction (volume contrôlé) et mesurer si elle est détectée.
  3. Test de qualité de watermark : paraphraser des sorties, mesurer si le watermark survit.
  4. Audit de la chaîne d'enforcement : si signal détecté, est-ce que le compte est suspendu rapidement ? Est-ce que le légal est saisi ?
  5. Documentation conformité : traçabilité des décisions, alignment EU AI Act / NIST / sectoriel.

Mapping OWASP LLM Top 10 v2

OWASPLien model extraction
LLM10 Unbounded ConsumptionCatégorie centrale (rebaptisée v2 spécifiquement)
LLM03 Supply ChainModèle volé utilisé en aval
LLM07 System Prompt LeakageAdjacent (extraction de prompts/configs)
LLM02 Sensitive Information DisclosureSi extraction révèle données entraînement

LLM10 a été spécifiquement renommée en v2 2025 (de DoS à Unbounded Consumption) pour mieux capter cette classe d'attaque longue (consommation de ressources sur la durée).

Points clés à retenir

  • Le model extraction est devenu une menace industrielle réelle en 2025-2026. Le débat DeepSeek vs OpenAI (janvier 2025) est le cas public de référence.
  • 5 vecteurs : behavioral cloning (distillation classique), logit extraction, embedding extraction, equation solving (modèles classiques), multi-turn cloning.
  • Coût économique d'extraction d'un modèle frontier : décennies à des heures, devenu accessible (100k-100M requêtes selon objectif).
  • Défense fournisseur en 6 couches : rate limiting progressif, pas de logits par défaut, output perturbation, watermarking statistique (Kirchenbauer 2023), monitoring patterns, CGU + enforcement légal.
  • Limites du watermarking : paraphrasing et traduction cassent le signal. C'est un signal fort, pas une preuve juridique seule.
  • Côté consommateur : respecter les CGU, audit trail, pas de pipeline ressemblant à de la distillation, documentation des sources d'entraînement.
  • OWASP : LLM10 Unbounded Consumption (catégorie centrale, renommée v2 2025 pour capturer cette classe).
  • Test minimum d'audit : red team simulation extraction, paraphrasing du watermark, audit chaîne d'enforcement.

Le model extraction n'est plus un risque théorique de papier académique. C'est un risque économique mesurable, un sujet juridique actif, et un travail défensif continu pour les fournisseurs LLM. Pour les consommateurs, le terrain est dual : ne pas être complice involontairement, ne pas être suspecté à tort.

Questions fréquentes

  • Quelle est la différence entre distillation légitime et model extraction ?
    La distillation est une technique légitime publiquement documentée (Hinton et al. 2015) où on entraîne un modèle élève sur les outputs d'un modèle maître **avec autorisation et accès consenti**. Le model extraction est l'application de cette technique **sans autorisation** sur un modèle accessible via API publique, dans le but de créer un clone fonctionnel pour l'utiliser, le revendre, ou contourner la facturation. Les CGU d'OpenAI, Anthropic, Google interdisent explicitement cette pratique. La distinction est juridique et contractuelle, pas technique — la mécanique sous-jacente est la même.
  • Combien de requêtes faut-il pour extraire un LLM ?
    Variable selon l'objectif et la qualité visée. Les recherches publiques (Tramèr et al. 2016 pour ML classique, papers récents 2023-2025 sur LLMs) montrent : pour cloner un modèle compact à fidélité raisonnable, 100k-1M de requêtes suffisent. Pour atteindre la qualité d'un GPT-4 ou Claude Sonnet, il faut des dizaines à centaines de millions de requêtes — coûteux mais réalisable pour un acteur étatique ou une corporate de taille. Les coûts ont chuté drastiquement avec les progrès des architectures de distillation efficace (DistilBERT-style, MiniLM, etc.) — la barrière n'est plus technique mais économique.
  • Le débat DeepSeek vs OpenAI en janvier 2025, c'était quoi ?
    OpenAI a publiquement accusé DeepSeek (modèle chinois sorti fin 2024 / début 2025) d'avoir été entraîné via distillation non autorisée de ses modèles, en violation des CGU. DeepSeek a contesté. Le débat a illustré (1) à quel point la distillation est devenue accessible, (2) à quel point la détection est difficile sans cooperation des plateformes, (3) le flou juridique sur la propriété intellectuelle de modèles entraînés via API. Aucune décision juridique formelle n'avait tranché à mi-2025. Le sujet a relancé l'effort de watermarking côté OpenAI/Anthropic et la régulation côté EU AI Act.
  • Le watermarking de sorties LLM fonctionne-t-il vraiment ?
    Partiellement. Plusieurs schémas publiés (Kirchenbauer et al. 2023 'A Watermark for LLMs', Aaronson 2022 chez OpenAI) utilisent des modifications statistiques imperceptibles de la distribution de tokens en sortie. Détectable par celui qui possède la clé du watermark, transparent à l'utilisateur. Limites publiques : (1) attaques de paraphrasing détruisent le watermark à coût modéré, (2) traduction multilingue casse le signal, (3) trade-off qualité/robustesse. C'est une couche utile pour la détection a posteriori d'usage non-autorisé, jamais une garantie. Effort de recherche actif en 2025-2026.
  • Comment monitorer les patterns d'extraction sur un service LLM ?
    Cinq signaux. (1) **Volume anormal** par compte/IP : >10k requêtes/jour sur un compte non-enterprise est suspect. (2) **Distribution sémantique large** : un attaquant qui distille balaye largement l'espace des prompts. (3) **Patterns systématiques** : variations méthodiques d'un même type de prompt (échantillonnage). (4) **Demande de logits/probabilités** : si l'API les expose, augmente le rendement de l'extraction. (5) **Géographie + horaire** : connexions atypiques. Action sur signal : rate limit ciblé, output perturbation, alerte légal/SOC. Outils : monitoring API gateway, anomaly detection, fingerprinting.
  • Quelles défenses concrètes contre le model extraction côté fournisseur ?
    Six couches. (1) **Rate limiting** strict par compte/IP, avec quotas progressifs. (2) **Pas d'exposition de logits** sauf cas explicite (entreprise client). (3) **Output perturbation** : ajouter du bruit contrôlé qui n'affecte pas la qualité utilisateur mais dégrade la distillation. (4) **Watermarking** des sorties pour détection a posteriori. (5) **Monitoring patterns** d'extraction en temps réel + alertes. (6) **CGU explicites** interdisant distillation/extraction, applicables juridiquement. Côté **client** : si on consomme un LLM tiers, lire et respecter les CGU — la responsabilité est partagée.

Écrit par

Naim Aouaichia

Expert cybersécurité et fondateur de Zeroday Cyber Academy

Expert cybersécurité avec un master spécialisé et un parcours hybride : développement, DevOps, DevSecOps, SOC, GRC. Fondateur de Hash24Security et Zeroday Cyber Academy. Formateur et créateur de contenu technique sur la cybersécurité appliquée, la sécurité des LLM et le DevSecOps.