Skip to main content
Version: 2.8

โš™๏ธ Configuration

๐Ÿ”ง Reaction Configuration

Configure reactions within Jibril's detection recipes. Reactions are defined in YAML files (the Alchemies) and integrated into the broader detection system.

๐Ÿ“‹ Basic Structureโ€‹

Reactions are configured as part of detection recipes. Here's the basic structure:

- kind: recipe_identifier
name: recipe_name
enabled: true
version: 1.0
description: Description of what this recipe detects

# Detection configuration
breed: detection_type
mechanism: detection_mechanism
tactic: mitre_tactic
technique: mitre_technique
subtechnique: mitre_subtechnique
importance: severity_level

# Detection criteria (varies by type)
# ... detection-specific configuration ...

# Reactions configuration
reactions:
- format: js # or "shell"
code: |
# JavaScript function here
- format: shell
code: |
# Shell script here

Reaction Configuration Optionsโ€‹

format (required)โ€‹

Specifies the execution format for the reaction code.

Valid values:

  • js: JavaScript execution using V8 engine (recommended)
  • shell: Shell script execution using /bin/sh

Example:

reactions:
- format: js
code: |
function process(data) {
Info("JavaScript reaction");
}
- format: shell
code: |
echo "Shell reaction"

code (required)โ€‹

Contains the actual reaction code to execute.

For JavaScript reactions:

  • Must contain a process(data) function
  • Function receives the complete event data as a parameter
  • Has access to all helper functions and global variables

For Shell reactions:

  • Can be any valid shell script
  • Event data is provided via REACTION_DATA environment variable as JSON

JavaScript Example:

reactions:
- format: js
code: |
      function process(data) {
// Access global variables
Info("Event type: " + kind);
Info("Recipe name: " + name);
Info("Event UUID: " + uuid);

// Process the event data
if (data.process) {
Warn("Process: " + data.process.cmd);
}

// Take action
let result = NetBlockIp();
if (result === 0) {
Info("Network blocked successfully");
}
}

Shell Example:

reactions:
- format: shell
code: |
      #!/bin/bash

# Parse event data
PROCESS_CMD=$(echo "$REACTION_DATA" | jq -r '.process.cmd')
FILE_PATH=$(echo "$REACTION_DATA" | jq -r '.file.file // "N/A"')

echo "Shell reaction triggered"
echo "Process: $PROCESS_CMD"
echo "File: $FILE_PATH"

# Log to system log
logger "Jibril reaction: $PROCESS_CMD accessed $FILE_PATH"

Integration with Detection Typesโ€‹

File Access Reactionsโ€‹

File access reactions receive detailed information about file operations.

- kind: passwd_usage
name: passwd_usage
enabled: false
version: 1.0
description: Passwd related command usage
documentation: |
https://garnet.gitbook.io/jibril/detections/3_3_execution/passwd_usage
breed: file_access
mechanism: execution
tactic: persistence
technique: account_manipulation
subtechnique: local_account
importance: high
times:
- kind: times_per_parent_proc
max: 2
- kind: times_per_parent_exe
max: 4
- kind: times_per_full_ancestry
max: 4
arbitrary: []
file_actions:
- execve
file_actions_how: any
bases:
- dir: /etc
base: passwd
reactions:
- format: js
code: |
        function process(data) {
Info("Password file accessed!");
Info("File: " + data.file.file);
Info("Actions: " + data.file.actions.join(", "));
Info("Process: " + data.process.cmd);
Info("User ID: " + data.process.uid);

// Terminate suspicious access
if (data.process.uid !== 0) {
Warn("Non-root access to passwd file - terminating");
KillCurrent();
}
}

Process Execution Reactionsโ€‹

Execution reactions monitor process creation and can access ancestry information.

- kind: net_suspicious_tool_exec
name: net_suspicious_tool_exec_critical
enabled: false
version: 1.0
description: Network suspicious tool execution detected (with IP address argument)
documentation: |
https://garnet.gitbook.io/jibril/detections/3_3_execution/net_suspicious_tool_exec
breed: file_access
mechanism: execution
tactic: discovery
technique: network_service_discovery
subtechnique: none
importance: critical
times:
- kind: times_per_parent_proc
max: 2
- kind: times_per_parent_exe
max: 4
- kind: times_per_full_ancestry
max: 4
arbitrary:
- how: OR
which: irrelevant
items:
- what: args
which: pertinent
# Match if IPv4 or IPv6 addresses appear in the command arguments.
pattern: ([^\w|\.](\b25[0-5]|\b2[0-4][0-9]|\b[01]?[0-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}([^\w|\.]|$)|[^\w|\.](([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))([^\w|\.]|$))
file_actions:
- execve
file_actions_how: any
bases:
- base: nc # TCP/UDP client/listener.
- base: ncat # Nmap's TCP/UDP client/listener.
reactions:
# yaml-embedded-languages: javascript
- format: js
code: |
        function process(data) {
Error("REVERSE SHELL DETECTED!");
Info("Command: " + data.process.cmd);
Info("PID: " + data.process.pid);
Info("Parent PID: " + data.process.ppid);

// Log the full process ancestry
if (data.base.background.ancestry) {
Info("Process ancestry:");
for (let i = 0; i < data.base.background.ancestry.length; i++) {
let ancestor = data.base.background.ancestry[i];
Info(" " + ancestor.pid + ": " + ancestor.cmd);
}
}

// Immediate containment
let killResult = KillCurrent();
let blockResult = NetBlockIp();

if (killResult === 0 && blockResult === 0) {
Info("Reverse shell contained successfully");
}
}

Network Activity Reactionsโ€‹

Network reactions can access flow information and remote connection details.

- kind: malicious_network
name: malicious_network_01
enabled: false
version: 1.0
description: Access to malicious domains
documentation: not available
breed: remote_domains
mechanism: network_peers
tactic: command_and_control
technique: application_layer_protocol
subtechnique: web_protocols
importance: critical
times:
- kind: times_per_proc
max: 2
- kind: times_per_exe
max: 4
- kind: times_per_full_ancestry
max: 4
arbitrary: []
flow_actions:
- ingress
- egress
flow_actions_how: any
remote_domains_type: suffix
remote_domains:
- onion
reactions:
- format: js
code: |
        function process(data) {
Warn("Tor connection detected");

// Extract network flow information
if (data.background && data.background.flows) {
Info("Network flows detected:");
let flows = data.background.flows;

if (flows.protocols) {
for (let protocol of flows.protocols) {
Info("Protocol: " + protocol.name);

if (protocol.pairs) {
for (let pair of protocol.pairs) {
if (pair.nodes && pair.nodes.remote) {
Info("Remote: " + pair.nodes.remote.address);
if (pair.nodes.remote.names) {
Info("Domains: " + pair.nodes.remote.names.join(", "));
}
}
}
}
}
}
}

// Block the connection
let result = NetBlockDomain();
if (result === 0) {
Info("Tor domains blocked successfully");

// Log to security incident database
DataSet("tor_blocks_" + new Date().toDateString(),
String(parseInt(DataGet("tor_blocks_" + new Date().toDateString()) || "0") + 1));
}
}

Multiple Reactionsโ€‹

You can define multiple reactions for a single detection recipe. They will execute in parallel:

- kind: comprehensive_response
name: multi_reaction_example
enabled: true
breed: file_access
mechanism: file_access
tactic: mitre_tactic
technique: mitre_technique
subtechnique: mitre_sub_technique
importance: high
bases:
- dir: /etc/ssh
file_actions:
- write
reactions:
# Reaction 1: Immediate logging
- format: js
code: |
# JavaScript function here

# Reaction 2: Network containment
- format: js
code: |
# JavaScript function here

# Reaction 3: Evidence collection
- format: js
code: |
# JavaScript function here

# Reaction 4: System backup (shell script)
- format: shell
code: |
# Shell script here

Debugging and Troubleshootingโ€‹

Logging for Debuggingโ€‹

Use comprehensive logging to debug reaction issues:

reactions:
- format: js
code: |
      function process(data) {
Info("=== REACTION DEBUG START ===");
Info("Kind: " + kind);
Info("Name: " + name);
Info("UUID: " + uuid);

// Log data structure
Info("Data keys: " + Object.keys(data).join(", "));

if (data.process) {
Info("Process PID: " + data.process.pid);
Info("Process CMD: " + data.process.cmd);
}

// Test helper functions
let testResult = DataSet("debug_test", "success");
Info("DataSet test result: " + testResult);

let retrieved = DataGet("debug_test");
Info("DataGet test result: " + retrieved);

Info("=== REACTION DEBUG END ===");
}

Error Handlingโ€‹

Implement proper error handling:

reactions:
- format: js
code: |
      function process(data) {
try {
// Main reaction logic
let result = NetBlockIp();
if (result !== 0) {
Error("Failed to block IP: " + Errno());
}

// File operations with error checking
let writeResult = WriteFile("/tmp/reaction.log", "test");
if (writeResult !== 0) {
Error("Failed to write file: " + Errno());
}

} catch (error) {
Error("Reaction error: " + error.toString());
}
}

Testing Reactionsโ€‹

Test Configurationโ€‹

Create test reactions with disabled state:

- kind: test_reaction
name: my_test_reaction
enabled: false # Start disabled for testing
version: 1.0
description: Test reaction for development
breed: file_access
mechanism: file_access
importance: low

bases:
- dir: /tmp/test
base: trigger.txt
file_actions:
- unlink

reactions:
- format: js
code: |
# JavaScript function here
        function process(data) {
Info("=== TEST REACTION ===");
Info("All systems operational");

// Test all helper functions safely
DataSet("test", "success");
let value = DataGet("test");
Info("Data store test: " + (value === "success" ? "PASS" : "FAIL"));

DataDelete("test");
Info("=== TEST COMPLETE ===");
}

Gradual Deploymentโ€‹

  1. Test Environment: Deploy with enabled: false first
  2. Limited Scope: Start with specific file patterns or processes
  3. Monitoring: Watch logs carefully for unexpected behavior
  4. Gradual Expansion: Slowly expand scope and enable more reactions
  5. Production: Only deploy fully tested reactions to production

This configuration guide provides the foundation for creating powerful, secure, and maintainable reactions within the Jibril security system.