Aller au contenu

Certificats de signature de code

Stentor prend en charge la signature de code Authenticode pour les payloads générées. Les certificats de signature de code sont téléchargés sous forme de fichiers PFX (PKCS#12), stockés avec des mots de passe cryptés dans la base de données et utilisés pour signer les payloads via l'outil osslsigncode du relais. Les payloads signées portent une signature Authenticode valide qui satisfait à Windows SmartScreen, aux politiques de liste blanche des applications et aux invites de confiance des utilisateurs.


Architecture

sequenceDiagram
    participant Operator as Operator
    participant API as Stentor API
    participant DB as PostgreSQL
    participant Relay as Relay (Kali)

    Note over Operator,DB: Certificate Upload
    Operator->>API: POST /certificates (multipart PFX + password)
    API->>API: Parse PFX, extract metadata
    API->>API: Encrypt password (AES-256-GCM)
    API->>DB: Store PFX + encrypted password + metadata
    API-->>Operator: CertificateResponse (no sensitive fields)

    Note over Operator,Relay: Payload Signing
    Operator->>API: POST /sign {payload_id, certificate_id}
    API->>DB: Load payload binary + certificate PFX
    API->>API: Decrypt certificate password
    API->>Relay: sign_payload command (PFX + password + payload)
    Relay->>Relay: osslsigncode sign
    Relay-->>API: Signed payload bytes
    API-->>Operator: {success, signed_size}

Gestion des certificats

Télécharger un certificat

POST /api/v1/certificates

Téléchargez un fichier PFX (PKCS#12) contenant un certificat de signature de code et une clé privée. L'API analyse le PFX pour extraire les métadonnées du certificat (sujet, émetteur, période de validité), crypte le mot de passe avec AES-256-GCM et stocke le tout dans la base de données.

Champs du formulaire :

Champ Type Obligatoire Description
name chaîne Oui Nom lisible du certificat
description chaîne Non Description facultative
pfx_file fichier Oui Fichier PFX (PKCS#12) contenant le certificat et la clé privée
password chaîne Oui Mot de passe protégeant le fichier PFX

Limite de taille : 1 Mo maximum pour le fichier PFX.

curl -s -X POST https://stentor.app/api/v1/certificates \
  -H "Authorization: Bearer $TOKEN" \
  -F "name=Contoso Code Signing" \
  -F "description=EV code signing cert for payload signing" \
  -F "pfx_file=@/path/to/certificate.pfx" \
  -F "password=pfx-password-here"

Réponse (201 créées) :

{
  "id": "b2c3d4e5-...",
  "name": "Contoso Code Signing",
  "description": "EV code signing cert for payload signing",
  "subject": "CN=Contoso Ltd, O=Contoso Ltd, L=Redmond, ST=Washington, C=US",
  "issuer": "CN=DigiCert SHA2 Extended Validation Code Signing CA, OU=www.digicert.com, O=DigiCert Inc, C=US",
  "valid_from": "2025-01-15T00:00:00Z",
  "valid_until": "2027-01-14T23:59:59Z",
  "created_by": "USER_UUID",
  "created_at": "2026-02-21T10:00:00Z"
}

Validation PFX

L'API décode le PFX à l'aide du pkcs12.Decode de Go pour vérifier que le fichier est valide et que le mot de passe est correct avant de le stocker. Les fichiers PFX invalides ou les mots de passe incorrects renvoient une erreur 400 Bad Request avec un message descriptif.

Liste des certificats

GET /api/v1/certificates

Répertoriez tous les certificats stockés. Les champs sensibles (données binaires PFX, mot de passe chiffré) sont exclus de la réponse. Les certificats sont renvoyés dans l'ordre chronologique inverse.

curl -s https://stentor.app/api/v1/certificates \
  -H "Authorization: Bearer $TOKEN"

Champs de réponse :

Champ Type Description
id chaîne UUID du certificat
name chaîne Nom du certificat
description chaîne Description facultative
subject chaîne DN du sujet du certificat
issuer chaîne DN de l'émetteur du certificat
valid_from chaîne Début de validité (ISO 8601)
valid_until chaîne Fin de validité (ISO 8601)
created_by chaîne UUID de l'utilisateur qui a téléchargé
created_at chaîne Horodatage de téléchargement (ISO 8601)

Obtenir un certificat

GET /api/v1/certificates/:id

Récupérez un seul certificat par ID. Même format de réponse que le point de terminaison de la liste (pas de champs sensibles).

curl -s https://stentor.app/api/v1/certificates/CERT_UUID \
  -H "Authorization: Bearer $TOKEN"

Supprimer le certificat

DELETE /api/v1/certificates/:id

Supprimez un certificat et toutes les données associées (binaire PFX, mot de passe chiffré) de la base de données.

curl -s -X DELETE https://stentor.app/api/v1/certificates/CERT_UUID \
  -H "Authorization: Bearer $TOKEN"

Réponse : 204 No Content en cas de succès.


Signature des payloads

POST /api/v1/sign

Signez un payload générée avec un certificat de signature de code stocké. L'opération de signature est effectuée sur le relais à l'aide de osslsigncode, qui prend en charge les signatures Authenticode pour les fichiers PE (EXE/DLL).

Corps de la demande :

Champ Type Obligatoire Description
payload_id chaîne (UUID) Oui UUID de le payload à signer
certificate_id chaîne (UUID) Oui UUID du certificat de signature de code
description chaîne Non Description de la signature Authenticode (apparaît dans les propriétés du fichier)
url chaîne Non URL intégrée dans la signature Authenticode
timestamp_url chaîne Non URL du serveur d'horodatage RFC 3161 pour la contre-signature

Contresignature d'horodatage

Fournir un timestamp_url ajoute un horodatage fiable à la signature, ce qui garantit que la signature reste valide même après l'expiration du certificat. Serveurs d'horodatage courants : http://timestamp.digicert.com, http://timestamp.sectigo.com.

curl -s -X POST https://stentor.app/api/v1/sign \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "payload_id": "PAYLOAD_UUID",
    "certificate_id": "CERT_UUID",
    "description": "Contoso Updater Service",
    "url": "https://contoso.com",
    "timestamp_url": "http://timestamp.digicert.com"
  }'

Réponse (200 OK) :

{
  "success": true,
  "payload_id": "PAYLOAD_UUID",
  "signed_size": 524288
}

Réponses d'erreur :

Statut État
400 Bad Request Champs obligatoires manquants ou UUID invalides
404 Not Found Payload ou certificat introuvable
503 Service Unavailable Aucun relais connecté (la signature nécessite un relais)
504 Gateway Timeout L'opération de signature a expiré (limite de 60 secondes)
500 Internal Server Error La signature a échoué sur le relais (message d'erreur inclus)

Flux de signature

  1. L'API valide la demande et charge le binaire de payload et le certificat PFX à partir de la base de données.
  2. Le mot de passe du certificat est déchiffré du stockage AES-256-GCM.
  3. Une commande sign_payload est envoyée au premier relais connecté avec les octets de payload, les données PFX, le mot de passe déchiffré et les options de signature.
  4. Le relais exécute osslsigncode pour appliquer la signature Authenticode.
  5. Les octets de payload signés sont renvoyés à l'API via un canal requête/réponse basé sur la corrélation.
  6. L'API renvoie le résultat à l'opérateur.

Exigence de relais

La signature nécessite au moins un relais connecté. L'outil osslsigncode s'exécute sur le relais Kali - le serveur API Stentor n'effectue pas de signature directement. Si aucun relais n'est connecté, le point de terminaison renvoie 503 Service Unavailable.


Stockage crypté

Les mots de passe des certificats sont chiffrés au repos à l'aide d'AES-256-GCM avec une clé côté serveur de 32 octets configurée via la variable d'environnement C2_CERTIFICATE_ENCRYPTION_KEY.

Composant Stockage Cryptage
Données binaires PFX certificates.pfx_data (BYTEA) Aucun (octets bruts dans la base de données)
Mot de passe PFX certificates.password_encrypted (BYTEA) AES-256-GCM (nom occasionnel de 12 octets ajouté au début)
Métadonnées du certificat certificates.* Aucun (texte en clair – non sensible)

Le schéma de chiffrement utilise un nom occasionnel aléatoire de 12 octets pour chaque opération de chiffrement. Le nom occasionnel est ajouté au texte chiffré, la valeur stockée est donc [12-byte nonce][ciphertext + GCM tag].

La rotation des clés est prise en charge via l'utilitaire MigrateEncryptedPassword, qui déchiffre avec l'ancienne clé et rechiffre avec une nouvelle clé en utilisant un nouveau nom occasionnel.

Gestion des clés de chiffrement

Le C2_CERTIFICATE_ENCRYPTION_KEY doit faire exactement 32 octets (256 bits). Si la clé est perdue ou modifiée sans migrer les mots de passe existants, tous les certificats stockés deviennent inutilisables (les données PFX sont intactes mais le mot de passe ne peut pas être déchiffré). Conservez la clé en toute sécurité et incluez-la dans vos procédures de sauvegarde.


Considérations OPSEC

Surface de détection

Les payloads signées par code sont beaucoup plus susceptibles de contourner les contrôles d'exécution initiaux, mais le certificat lui-même devient un indicateur de compromission (IOC) si le payload est capturée et analysée.

  • MITRE ATT&CK : T1553.002 (Subvert Trust Controls : signature de code)
Préoccupation Détails
Contournement SmartScreen Les EXE signés contournent l'avertissement SmartScreen « Windows a protégé votre PC ». Les certificats EV garantissent une réputation immédiate. Les certificats standards renforcent la réputation au fil du temps.
Liste blanche des applications Certaines politiques de liste blanche d'applications autorisent l'exécution de binaires signés. La signature avec un certificat d'éditeur de confiance peut contourner ces contrôles.
Certificat du CIO Si un payload signée est capturée, le numéro de série, le sujet et l'empreinte numérique du certificat deviennent des IOC. Les défenseurs peuvent bloquer l'exécution de tous les binaires signés avec ce certificat.
Révocation du certificat Un certificat compromis ou détecté peut être signalé à l'autorité de certification pour révocation. Vérifiez l’état CRL/OCSP avant de vous fier à un certificat pour les opérations en cours.
Persistance de l'horodatage Les payloads contresignées restent fiables même après l'expiration ou la révocation du certificat (en fonction du motif de la révocation). Utilisez toujours un serveur d'horodatage pour les engagements de longue durée.

Sources des certificats

Pour les engagements de l'équipe rouge, les certificats de signature de code peuvent être obtenus auprès de :

  • Achat légitime : Achetez un certificat de signature de code standard ou EV auprès d'une autorité de certification publique. Fournit le signal de confiance le plus fort mais crée une trace écrite.
  • Auto-signé : Générez un certificat auto-signé à des fins de test. Ne contourne pas SmartScreen mais satisfait à certaines politiques de liste blanche d'applications qui vérifient uniquement une chaîne de signature valide.
  • Expiré/volé : Les certificats trouvés pendant la post-exploitation peuvent être extraits et utilisés pour la signature. La contresignature par horodatage étend la convivialité au-delà de l’expiration.