Lab Spink : rétablissement d’un pipeline de collecte Splunk

Lab : Spink / Splunk — Basic — Hardening, SIEM, SOC Hôte Windows : EC2AMAZ-4ML8E8Q (10.8.0.100) Indexer Splunk : 10.8.0.101 Résultat : ✅ pipeline entièrement rétabli, validation obtenue à 80/80

Résumé exécutif

L’incident ne provenait pas d’une seule panne. La chaîne de collecte comportait cinq défaillances simultanées : le service SplunkForwarder était arrêté, son mode de démarrage Windows était Disabled, la destination TCP pointait vers une adresse erronée, le chemin du journal applicatif était incorrect et l’index applicatif contenait une faute de frappe.

Après correction, le forwarder a atteint l’état Running, la cible 10.8.0.101:9997 est devenue joignable et Splunk a reçu les quatre flux attendus dans l’index endpoint.

1. Objectif et chaîne de collecte

L’objectif du scénario était de restaurer toute la chaîne suivante :

Journaux Windows + C:\AppLogs\app.log
                │
                ▼
Splunk Universal Forwarder sur EC2AMAZ-4ML8E8Q
                │  TCP 9997
                ▼
Indexer Splunk 10.8.0.101
                │
                ▼
Index endpoint dans Splunk Web
                │
                ▼
Flag verifier sur http://10.8.0.101:5000/flag

Le fichier inputs.conf définit les sources locales, notamment les journaux Windows et les fichiers surveillés. Le fichier outputs.conf définit le groupe de sortie TCP et les indexers destinataires.

1.1 Rôle des ports dans le lab

Les ports utilisés n’avaient pas tous le même rôle. Il était important de ne pas confondre le port de transport des événements avec le port de validation du challenge.

Port Service Rôle dans le scénario Vérification
9997/TCP Réception Splunk Port vers lequel le Universal Forwarder envoie les journaux à l’indexer (défini dans outputs.conf) Test-NetConnection 10.8.0.101 -Port 9997
5000/TCP Vérificateur du lab Service HTTP spécifique au challenge, expose /flag — ce n’est pas le port de collecte Splunk curl.exe http://10.8.0.101:5000/flag
8000/TCP Splunk Web Interface Web pour se connecter à Splunk et exécuter les recherches SPL http://10.8.0.101:8000/
8089/TCP splunkd / management Port de gestion de Splunk ; l’erreur 503 initiale indiquait que ce démon n’était pas disponible Contrôle de 127.0.0.1:8089

Le flux complet peut être représenté ainsi :

EC2AMAZ-4ML8E8Q — 10.8.0.100
        │
        │  Journaux Windows + C:\AppLogs\app.log
        ▼
Splunk Universal Forwarder
        │
        │  TCP 9997 : transport des événements
        ▼
Indexer Splunk — 10.8.0.101
        │
        ├── TCP 8000 : Splunk Web et recherches SPL
        ├── TCP 8089 : gestion interne de splunkd
        └── TCP 5000 : vérificateur du lab et récupération du flag

Ainsi, le test du port 9997 validait le chemin réseau de collecte, tandis que l’appel au port 5000 servait uniquement à demander au vérificateur si toutes les conditions du scénario étaient réunies.

2. État initial observé

Get-Service *Splunk*; Get-ChildItem 'C:\Program Files\SplunkUniversalForwarder\etc\apps' -Directory | Select-Object Name; Test-NetConnection 10.8.0.101 -Port 9997

Sortie pertinente :

Status   Name               DisplayName
------   ----               -----------
Stopped  SplunkForwarder    SplunkForwarder

Name : audit_trail
Name : introspection_generator_addon
Name : learned
Name : search
Name : SplunkUniversalForwarder
Name : splunk_httpinput
Name : splunk_ingest_actions
Name : splunk_internal_metrics

ComputerName     : 10.8.0.101
RemoteAddress    : 10.8.0.101
PingSucceeded    : False
TcpTestSucceeded : True
RemotePort       : 9997
SourceAddress    : 10.8.0.100
InterfaceDescription : TAP-Windows Adapter V9 for OpenVPN Connect
IsAdmin          : True

Cette sortie établissait deux faits importants :

  1. Le forwarder était arrêté.
  2. Le port TCP 9997 était joignable malgré l’échec ICMP (PingSucceeded : False).

💡 Point clé : le ping n’était pas un indicateur suffisant de panne réseau ; le test réellement utile pour la collecte Splunk était TcpTestSucceeded : True sur le port de réception.

Côté Splunk Web, l’interface affichait une erreur 503 Service unavailable et indiquait que le démon splunkd sur 127.0.0.1:8089 n’était pas accessible — une indisponibilité temporaire du service côté indexer, à distinguer de la connectivité TCP du forwarder vers le port 9997.

3. Analyse de la configuration effective

$sf = 'C:\Program Files\SplunkUniversalForwarder'
$files = Get-ChildItem "$sf\etc" -Recurse -File -Include inputs.conf,outputs.conf,server.conf,props.conf
$files | Select-Object -ExpandProperty FullName
foreach ($f in $files) {
    Write-Host "`n===== $($f.FullName) ====="
    Get-Content $f.FullName
}

Fichiers locaux importants :

C:\Program Files\SplunkUniversalForwarder\etc\system\local\inputs.conf
C:\Program Files\SplunkUniversalForwarder\etc\system\local\outputs.conf
C:\Program Files\SplunkUniversalForwarder\etc\system\local\server.conf

3.1 Configuration inputs.conf avant correction

[default]
host = secdojo-endpoint

[WinEventLog://System]
disabled = 0
index = endpoint

[WinEventLog://Application]
disabled = 0
index = endpoint

[WinEventLog://Security]
disabled = 0
index = endpoint

[monitor://C:\AppLogs\application.log]
disabled = 0
index = endpont
sourcetype = secdojo:applog

Les trois stanzas WinEventLog étaient correctes. En revanche, la stanza applicative présentait deux erreurs :

Paramètre Valeur erronée Valeur attendue Conséquence
Chemin surveillé C:\AppLogs\application.log C:\AppLogs\app.log Le fichier réel n’était pas surveillé
Index endpont endpoint Les événements applicatifs n’étaient pas dirigés vers l’index attendu

3.2 Configuration outputs.conf avant correction

[tcpout]
defaultGroup = primary_indexers

[tcpout:primary_indexers]
server = 176.16.128.151:9997

L’endpoint réel du lab était 10.8.0.101. L’adresse 176.16.128.151 était donc incorrecte. Même si un test TCP vers 10.8.0.101:9997 réussissait, le forwarder n’utilisait pas cette adresse tant que outputs.conf restait configuré sur l’ancienne cible.

4. Identification de la panne de service Windows

Première tentative de démarrage :

Start-Service SplunkForwarder
Start-Service : Service 'SplunkForwarder (SplunkForwarder)' cannot be started
...
FullyQualifiedErrorId : CouldNotStartService,Microsoft.PowerShell.Commands.StartServiceCommand

Après correction des fichiers de configuration, le service refusait encore de démarrer. La commande de diagnostic déterminante :

Get-CimInstance Win32_Service -Filter "Name='SplunkForwarder'" |
    Select-Object Name,State,StartMode,StartName,PathName,ExitCode |
    Format-List
Name      : SplunkForwarder
State     : Stopped
StartMode : Disabled
StartName : NT SERVICE\SplunkForwarder
PathName  : "C:\Program Files\SplunkUniversalForwarder\bin\splunkd.exe" service
ExitCode  : 1077

⚠️ Point critique : StartMode : Disabled. Le service pouvait être lancé manuellement dans certaines conditions, mais le gestionnaire de services Windows refusait le démarrage normal.

Tentative complémentaire :

& "$sf\bin\splunk.exe" start --accept-license --answer-yes
Checking mgmt port [8089]: open
Checking conf files for problems...
Done
All installed files intact.
All preliminary checks passed.
Starting splunk server daemon (splunkd)...
SplunkForwarder: Stopped

Les avertissements concernant le proxy HTTP, la clé pass4SymmKey et le certificat Splunk par défaut n’étaient pas la cause bloquante de cet incident. Le diagnostic utile restait le mode de démarrage Windows Disabled.

5. Corrections appliquées

Avant modification, des sauvegardes ont été créées :

$sf = 'C:\Program Files\SplunkUniversalForwarder'
$local = "$sf\etc\system\local"
Copy-Item "$local\inputs.conf" "$local\inputs.conf.bak" -Force
Copy-Item "$local\outputs.conf" "$local\outputs.conf.bak" -Force

5.1 Nouveau inputs.conf

@'
[default]
host = secdojo-endpoint

[WinEventLog://System]
disabled = 0
index = endpoint

[WinEventLog://Application]
disabled = 0
index = endpoint

[WinEventLog://Security]
disabled = 0
index = endpoint

[monitor://C:\AppLogs\app.log]
disabled = 0
index = endpoint
sourcetype = secdojo:applog
'@ | Set-Content "$local\inputs.conf" -Encoding ASCII

5.2 Nouveau outputs.conf

@'
[tcpout]
defaultGroup = primary_indexers

[tcpout:primary_indexers]
server = 10.8.0.101:9997
'@ | Set-Content "$local\outputs.conf" -Encoding ASCII

5.3 Vérification avec btool

& "$sf\bin\splunk.exe" btool inputs list --debug
& "$sf\bin\splunk.exe" btool outputs list --debug

Lignes importantes de la sortie btool :

...\etc\system\local\inputs.conf  [WinEventLog://Application]
...\etc\system\local\inputs.conf  disabled = 0
...\etc\system\local\inputs.conf  index = endpoint

...\etc\system\local\inputs.conf  [WinEventLog://Security]
...\etc\system\local\inputs.conf  disabled = 0
...\etc\system\local\inputs.conf  index = endpoint

...\etc\system\local\inputs.conf  [WinEventLog://System]
...\etc\system\local\inputs.conf  disabled = 0
...\etc\system\local\inputs.conf  index = endpoint

...\etc\system\local\outputs.conf  [tcpout:primary_indexers]
...\etc\system\local\outputs.conf  server = 10.8.0.101:9997

5.4 Réactivation du service Windows

Set-Service -Name SplunkForwarder -StartupType Automatic
Start-Service -Name SplunkForwarder
Start-Sleep 15
WARNING: Waiting for service 'SplunkForwarder (SplunkForwarder)' to start...
WARNING: Waiting for service 'SplunkForwarder (SplunkForwarder)' to start...

Ces avertissements étaient transitoires. Vérification du succès :

Get-CimInstance Win32_Service -Filter "Name='SplunkForwarder'" |
    Select-Object Name,State,StartMode,ExitCode |
    Format-List

& 'C:\Program Files\SplunkUniversalForwarder\bin\splunk.exe' status
Test-NetConnection 10.8.0.101 -Port 9997
Name      : SplunkForwarder
State     : Running
StartMode : Auto
ExitCode  : 0

SplunkForwarder: Running (pid 3080)

ComputerName     : 10.8.0.101
RemoteAddress    : 10.8.0.101
RemotePort       : 9997
SourceAddress    : 10.8.0.100
TcpTestSucceeded : True

Cette sortie prouve que le service était actif, configuré pour démarrer automatiquement et capable d’atteindre le port de réception Splunk.

6. Validation du journal applicatif

Get-Item 'C:\AppLogs\app.log'
Directory: C:\AppLogs

Mode  LastWriteTime          Length    Name
----  -------------          ------    ----
-a---- 08/14/2026 04:35 PM   1193711   app.log

Ajout d’un événement frais :

Add-Content 'C:\AppLogs\app.log' ("SEC_DOJO_RESTORE " + (Get-Date -Format o))

Lors d’une tentative rapprochée, Windows a signalé un verrou temporaire :

Add-Content : The process cannot access the file
'C:\AppLogs\app.log' because it is being used by another process.
FullyQualifiedErrorId : GetContentWriterIOError

ℹ️ Cette erreur était transitoire et compatible avec la lecture active du fichier par le forwarder. Une tentative ultérieure a réussi, et la taille du fichier est passée de 1193711 à 1193936 octets, confirmant l’écriture d’un nouvel événement.

7. Validation dans Splunk

index=endpoint earliest=-30m
| stats count latest(_time) as last by host sourcetype source
| sort - last

La recherche a retourné 374 événements et quatre lignes de flux :

Hôte Sourcetype Source Nombre observé Interprétation
secdojo-endpoint WinEventLog:System WinEventLog:System 198 Journal système Windows reçu
secdojo-endpoint secdojo:applog C:\AppLogs\app.log 10 Journal applicatif reçu avec le bon chemin et le bon sourcetype
secdojo-endpoint WinEventLog:Application WinEventLog:Application 15 Journal applicatif Windows reçu
secdojo-endpoint WinEventLog:Security WinEventLog:Security 151 Journal de sécurité Windows reçu

La somme des quatre compteurs est bien 198 + 10 + 15 + 151 = 374, ce qui correspond au nombre total affiché par Splunk. Cette concordance confirme que les quatre sources attendues étaient présentes dans l’index endpoint.

Recherche complémentaire pour le flag ou les événements de contrôle :

index=endpoint earliest=-24h ("SECDOJO{" OR "SECDOJO" OR "flag")
| table _time host source sourcetype _raw
| sort - _time

💡 Pourquoi un événement frais était nécessaire : le vérificateur du lab n’attendait pas seulement que le service soit démarré. Il exigeait qu’un nouvel événement provenant de C:\AppLogs\app.log traverse toute la chaîne et atteigne index=endpoint avec un timestamp valide. Un événement ancien ou déjà indexé avant la correction n’aurait pas démontré que la chaîne réparée fonctionnait au moment du contrôle.

Le délai d’environ 90 secondes était nécessaire parce que l’ingestion est asynchrone : le forwarder lit le fichier, place l’événement dans ses files internes, l’envoie sur TCP, puis l’indexer le parse et l’indexe.

Après ce délai, la commande suivante a été exécutée contre le service de validation du lab (et non contre le port de collecte Splunk) :

curl.exe http://10.8.0.101:5000/flag

Réponse obtenue :

flag: SECDOJO{3e2a25b276b719f2d995af3ed03b779b}

La capture finale du lab a confirmé :

You have successfully completed Spink
80/80 Points
2 Machines
Basic Difficulty

8. Synthèse des cinq défaillances

# Défaillance Preuve Correction État final
1 Service SplunkForwarder arrêté Status : Stopped Start-Service SplunkForwarder Running
2 Démarrage Windows désactivé StartMode : Disabled Set-Service ... -StartupType Automatic Auto
3 Mauvaise adresse de sortie server = 176.16.128.151:9997 Remplacement par 10.8.0.101:9997 Correcte
4 Mauvais chemin applicatif C:\AppLogs\application.log Remplacement par C:\AppLogs\app.log Correct
5 Faute de frappe dans l’index index = endpont Remplacement par index = endpoint Correct

9. Procédure reproductible condensée

Pour reproduire proprement le diagnostic sur un autre endpoint Splunk Universal Forwarder Windows :

$sf = 'C:\Program Files\SplunkUniversalForwarder'
$local = "$sf\etc\system\local"

Get-Service SplunkForwarder
Test-NetConnection 10.8.0.101 -Port 9997

Get-CimInstance Win32_Service -Filter "Name='SplunkForwarder'" |
    Select-Object Name,State,StartMode,StartName,PathName,ExitCode |
    Format-List

& "$sf\bin\splunk.exe" btool inputs list --debug
& "$sf\bin\splunk.exe" btool outputs list --debug

Set-Service -Name SplunkForwarder -StartupType Automatic
Start-Service -Name SplunkForwarder
Start-Sleep 15

& "$sf\bin\splunk.exe" status
Test-NetConnection 10.8.0.101 -Port 9997
Get-Item 'C:\AppLogs\app.log'

Dans Splunk Web, la validation minimale est :

index=endpoint earliest=-30m
| stats count latest(_time) as last by host sourcetype source
| sort - last

La vérification finale du lab :

curl.exe http://10.8.0.101:5000/flag

10. Conclusion

L’incident a été résolu en suivant la chaîne de collecte de bout en bout plutôt qu’en se limitant à l’interface Splunk. Le test réseau a montré que le port 9997 était accessible ; l’analyse des fichiers locaux a ensuite révélé les erreurs de destination, de chemin et d’index ; enfin, l’inspection du service Windows a mis en évidence le mode de démarrage Disabled.

Après correction des cinq défauts et émission d’un événement applicatif frais, Splunk a reçu les journaux Windows et le journal C:\AppLogs\app.log dans l’index endpoint. Le vérificateur a alors délivré le flag et le lab a été validé à 80/80.

Flag final :

SECDOJO{3e2a25b276b719f2d995af3ed03b779b}

Leçons retenues

  • PingSucceeded : False ne signifie pas forcément une panne réseau — ICMP peut être filtré alors que le port applicatif reste joignable. Toujours se fier à TcpTestSucceeded pour valider un flux de collecte.
  • Une configuration réseau correcte (port joignable) ne garantit pas qu’elle soit effectivement utilisée : outputs.conf doit pointer vers la bonne cible pour que le test réseau ait un sens opérationnel.
  • Le mode de démarrage Windows (StartMode) d’un service est une cause de panne à vérifier séparément de son état courant (State) — un service peut sembler correctement configuré en apparence tout en étant Disabled au niveau du gestionnaire de services.
  • btool est l’outil de référence pour valider la configuration effective de Splunk (après fusion de tous les fichiers .conf), plutôt que de se fier à la lecture d’un seul fichier local.
  • Pour valider une chaîne de bout en bout après correction, il vaut mieux injecter un événement frais avec timestamp que de se fier à des événements déjà présents dans l’index, qui ne prouvent pas que la chaîne réparée fonctionne au moment du contrôle.

Références