Skip to content

Shell Auditing (Bash / Zsh)

Relevant source files

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

The Shell Auditing probes in eCapture provide a mechanism for real-time command-line auditing of bash and zsh sessions. By hooking into the shell's line-editing and command execution functions via eBPF uprobes and uretprobes, eCapture captures every command entered by users, including the username, process ID (PID), and the command's return value (exit status). This is particularly useful for security auditing, compliance monitoring, and detecting unauthorized lateral movement within a system.

Implementation Overview

eCapture implements shell auditing through two distinct probes: bash and zsh. While both utilize similar eBPF techniques, they target different internal functions based on the shell's architecture.

Bash Auditing Principle

Bash uses the readline library for command input. eCapture hooks the readline function (or rl_line_buffer) to capture the command string. To associate commands with their results, it also hooks execute_command to capture the return value.

Zsh Auditing Principle

Zsh auditing targets the Zsh Line Editor (ZLE).

Data Flow Diagram

The following diagram illustrates how a command entered in a shell travels from the user space into the eBPF kernel program and back to eCapture's output.

Shell Command Capture Pipeline

Sources: kern/bash_kern.c:42-64, kern/bash_kern.c:65-100, internal/probe/bash/bash_probe.go:171-209

Technical Detail: Bash Probe

The Bash probe manages the state of commands because the command string and the return value are captured at different execution points.

Kernel Logic

In bash_kern.c, the event struct stores the context of the command: kern/bash_kern.c:17-24

c
struct event {
    u32 type;
    u32 pid;
    u32 uid;
    u8 line[MAX_DATA_SIZE_BASH];
    u32 retval;
    char comm[TASK_COMM_LEN];
};
  1. Readline Hook: When readline returns, the kernel program reads the command string from the return register (PT_REGS_RC) and stores it in the events_t hash map, keyed by the PID kern/bash_kern.c:58-60.
  2. Retval Hook: When execute_command returns, the program looks up the existing event in events_t using the PID, attaches the return value, and sends the completed event to userspace via a perf buffer kern/bash_kern.c:77-97.

Userspace Handling

The handleEvent function in bash_probe.go manages multi-line command accumulation and filters output based on the user-provided error number (--errnumber) internal/probe/bash/bash_probe.go:171-209.

Sources: kern/bash_kern.c:17-100, internal/probe/bash/bash_probe.go:171-209

CLI Usage and Configuration

The shell probes are invoked via the bash and zsh subcommands.

Command Options

FlagDescriptionDefault
--bashPath to the bash binary.Auto-detected
--zshPath to the zsh binary.Auto-detected
--readlinesoPath to libreadline.so if bash is dynamically linked.Auto-detected
-e, --errnumberOnly show commands with this exit code.128 (Show all)

Example Commands

Capture all bash commands:

bash
ecapture bash

Capture only failed bash commands (where exit code is non-zero, e.g., 1):

bash
ecapture bash -e 1

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

Code Entity Mapping

The following diagram maps the logical auditing components to their specific implementation classes and files.

Component to Code Entity Map

Sources: internal/probe/bash/bash_probe.go:39-49, internal/probe/zsh/zsh_probe.go:37-44, cli/cmd/bash.go:24-33, kern/bash_kern.c:42-65

Output Format

The output provides a structured view of the shell activity:

  • PID: Process ID of the shell.
  • UID: User ID of the person executing the command.
  • Comm: The process name (usually bash or zsh).
  • Retval: The exit status of the command.
  • Line: The actual command string executed.

This data is processed through the EventProcessor and can be directed to standard output, a file, or streamed via WebSocket using eCaptureQ internal/probe/bash/bash_probe.go:171-209.

Sources: kern/bash_kern.c:17-24, internal/probe/bash/bash_probe.go:171-209

Shell Auditing (Bash / Zsh) has loaded