Skip to content

Shell Command Auditing

Relevant source files

The following files were used as context for generating this wiki page:

Purpose and Scope

This document describes eCapture's shell command auditing capabilities, which intercept and log commands executed in Bash and Zsh shells for security auditing purposes. The module uses eBPF uprobes to hook into the GNU readline library, capturing command-line input and execution results without requiring shell history files or configuration changes.

This page covers the Bash and Zsh capture modules. For database query auditing, see Database Query Auditing. For general module architecture, see Module System and Lifecycle.


Module Architecture

The shell command auditing system consists of two parallel modules sharing the same underlying architecture: one for Bash and one for Zsh. Both modules hook into the readline library to intercept user input before command execution.

System Components

Sources: cli/cmd/bash.go:1-56, cli/cmd/zsh.go:1-58, user/event/event_bash.go:1-134


Configuration

Bash Module Configuration

The Bash module accepts the following configuration parameters:

ParameterFlagTypeDefaultDescription
Bashpath--bashstringAuto-detect from $SHELLPath to bash executable
Readline--readlinesostringAuto-detect from bash pathPath to readline.so library
ErrNo-e, --errnumberintBashErrnoDefaultFilter commands by exit code

Configuration Structure:

go
// Created via config.NewBashConfig()
type BashConfig struct {
    Bashpath string  // Target bash binary
    Readline string  // libreadline.so path
    ErrNo    int     // Exit code filter
}

Zsh Module Configuration

ParameterFlagTypeDefaultDescription
Zshpath--zshstringAuto-detect from $SHELLPath to zsh executable
ErrNo-e, --errnumberintZshErrnoDefaultFilter commands by exit code

Sources: cli/cmd/bash.go:24-39, cli/cmd/zsh.go:27-41

Command Line Usage

bash
# Basic bash command capture
ecapture bash

# Capture bash commands with custom paths
ecapture bash --bash=/bin/bash --readlineso=/lib/x86_64-linux-gnu/libreadline.so

# Filter by exit code (only show failed commands)
ecapture bash -e 1

# Zsh command capture
ecapture zsh --zsh=/bin/zsh -e 0

Sources: cli/cmd/bash.go:26-33, cli/cmd/zsh.go:30-36


Event Structure

BashEvent Data Layout

Commands captured from the shell are encoded in the BashEvent structure, which mirrors the eBPF kernel-side structure:

Sources: user/event/event_bash.go:26-47

Field Descriptions

FieldTypeSizeDescription
BashTypeuint324 bytesEvent type identifier
Piduint324 bytesProcess ID of shell
Uiduint324 bytesUser ID executing command
Line[256]uint8256 bytesCommand line text (may be partial)
ReturnValueuint324 bytesExit code of command
Comm[16]byte16 bytesProcess name (typically "bash" or "zsh")
AllLinesstringVariableAggregated full command (for multi-chunk commands)

Maximum Data Size: Commands longer than 256 bytes are captured in multiple events and reassembled using the AllLines field.

Sources: user/event/event_bash.go:37-47


Event Processing Pipeline

Data Flow from Shell to Output

Sources: user/event/event_bash.go:49-80, cli/cmd/bash.go:38

UUID-Based Event Correlation

Each command execution generates a unique identifier for event grouping:

UUID Format: {Pid}_{Uid}_{Comm}

Example: 1234_1000_bash

This UUID enables:

  • Correlation of multi-chunk command captures
  • Grouping of related events from the same shell session
  • Proper event ordering in the event worker pipeline

Sources: user/event/event_bash.go:123-125


Exit Code Filtering

The shell auditing modules support filtering by command exit codes, allowing users to focus on specific execution outcomes.

Filter Configuration

Sources: cli/cmd/bash.go:38, cli/cmd/zsh.go:40

Common Use Cases

ErrNo ValueUse CaseDescription
0Successful commandsAudit commands that completed successfully
1Failed commandsDetect failed execution attempts
127Command not foundIdentify typos or missing binaries
126Permission deniedTrack permission issues
DefaultAll commandsComprehensive audit trail

Output Format

Text Output Structure

The BashEvent.String() method formats captured commands for console display:

PID:1234, UID:1000, 	Comm:bash, 	Retvalue:0, 	Line:
ls -la /etc/passwd

Format Template: PID:%d, UID:%d, \tComm:%s, \tRetvalue:%d, \tLine:\n%s

Color Coding: Output uses the standard color scheme from user/event/event_bash.go:72-75, though the specific colors depend on terminal support.

Sources: user/event/event_bash.go:72-75

Hex Output Mode

When running with --hex flag, commands are displayed in hexadecimal format via StringHex():

PID:1234, UID:1000, 	Comm:bash, 	Retvalue:0, 	Line:
0000    6C 73 20 2D 6C 61    ls -la

Sources: user/event/event_bash.go:77-80


Library Detection and Hooking

Readline Library Resolution

The module employs a multi-step process to locate the readline library:

Sources: cli/cmd/bash.go:36-37

Uprobe Attachment Points

The module attaches to two critical points in the readline library:

Probe TypeFunctionPurpose
Uprobereadline() entryCapture PID, UID, command text buffer
Uretprobereadline() returnCapture exit code after command execution

Note: The actual eBPF program implementation is not shown in the provided files, but the event structure in user/event/event_bash.go:26-47 reflects the data captured at these hook points.


Protobuf Event Serialization

Shell events can be exported via the Protobuf/WebSocket interface for external integrations:

Protobuf Mapping

Special Handling:

  • Bash events do not have network context (SrcIP/DstIP set to 127.0.0.1, ports set to 0)
  • Timestamp uses time.Now().Unix() rather than kernel timestamp
  • Payload contains the full command line text from AllLines

Sources: user/event/event_bash.go:103-117


Event Lifecycle

Event Type Classification

Shell events are classified as TypeModuleData, which routes them through module-specific handling rather than the generic event processor:

go
func (be *BashEvent) Clone() IEventStruct {
    event := new(BashEvent)
    event.eventType = TypeModuleData  // Not TypeEventProcessor
    return event
}

This classification means:

  • Events bypass HTTP protocol parsing
  • No PCAP output generation
  • Direct output to console or log file
  • Module maintains control over formatting

Sources: user/event/event_bash.go:82-86

Multi-Chunk Command Handling

Commands exceeding 256 bytes are captured in multiple events:

  1. First chunk captured when user presses Enter
  2. eBPF program reads up to 256 bytes from readline buffer
  3. Subsequent chunks captured if command continues
  4. User-space code aggregates chunks into AllLines field using UUID correlation

Maximum Command Length: Limited by eBPF program design and event aggregation logic (not visible in provided files, but structure supports unlimited length via AllLines string).

Sources: user/event/event_bash.go:37-47


Integration with Other Modules

Module Factory Registration

Both Bash and Zsh modules are registered with the module factory:

ModuleNameBash  -> MBashProbe  -> BashConfig
ModuleNameZsh   -> MZshProbe   -> ZshConfig

The runModule() function in CLI commands delegates to the factory:

go
func bashCommandFunc(command *cobra.Command, args []string) error {
    return runModule(module.ModuleNameBash, bc)
}

Sources: cli/cmd/bash.go:53-55, cli/cmd/zsh.go:55-57

Shared Infrastructure

Shell modules leverage common eCapture infrastructure:


Security Considerations

Audit Trail Integrity

Shell command auditing provides:

  • Non-bypassable capture: Hooks at library level before history file writes
  • UID tracking: Associates commands with user identities
  • Exit code tracking: Distinguishes successful vs. failed attempts
  • Process correlation: Links commands to specific shell sessions

Privacy Implications

The module captures:

  • All interactive command input (including passwords if typed)
  • Arguments to commands (may contain sensitive data)
  • Working directory context (via process inspection)

Recommendation: Use exit code filtering and secure log storage when deploying in production environments.


Use Cases

Security Auditing

bash
# Monitor all commands executed by specific user
ecapture bash --pid=$(pgrep -u suspicious_user bash)

# Track failed command attempts (potential reconnaissance)
ecapture bash -e 1

Compliance Monitoring

bash
# Capture all successful administrative commands
ecapture bash -e 0 -l /var/log/audit/bash_commands.log

Debugging and Support

bash
# Record all commands during troubleshooting session
ecapture bash > debug_session.log

Intrusion Detection

bash
# Monitor for command-not-found errors (unusual activity)
ecapture bash -e 127

Sources: cli/cmd/bash.go:28-33, user/event/event_bash.go:72-75

Shell Command Auditing has loaded