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.
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).
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) :
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¶
- L'API valide la demande et charge le binaire de payload et le certificat PFX à partir de la base de données.
- Le mot de passe du certificat est déchiffré du stockage AES-256-GCM.
- Une commande
sign_payloadest 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. - Le relais exécute
osslsigncodepour appliquer la signature Authenticode. - Les octets de payload signés sont renvoyés à l'API via un canal requête/réponse basé sur la corrélation.
- 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.