Skip to content

Latest commit

 

History

7 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🔒 cisaudit

Linux CIS Hardening Auditor — Pure Bash, Zero Dependencies

Scan your Linux system against the CIS Benchmark in seconds. Get a compliance score, a dark-themed HTML report, and a clear list of exactly what to fix — without installing anything.

CIS Benchmark Pure Bash Platform Checks Tests License Portfolio

What It Does · Quick Start · All Commands · Architecture · Test Suite


Terminal Output — Live Audit on Kali Linux

Terminal output showing PASS/FAIL results with color coding

Colorized terminal output — green PASS, red FAIL, yellow WARN, each with its CIS control ID


HTML Report — Dark Theme Dashboard

Dark-themed HTML compliance report with score gauge

The auto-generated HTML report with compliance score gauge, per-control breakdown, and fix guidance


Baseline Drift Detection

Baseline diff showing IMPROVED and REGRESSION entries

Diff mode — compare two scans over time to track what improved and what regressed


Test Suite Output

Test runner showing 29 passing tests

All 29 automated tests passing — every control has both a PASS and FAIL fixture test


🤔 What Does This Do?

A fresh Linux install is not secure by default. This tool audits your system against 20 CIS Benchmark controls — the same standard used in enterprise SOC 2, PCI DSS, and ISO 27001 compliance programs — and gives you:

Output What you get
Compliance Score A percentage like 26.3% — the share of controls you pass
Per-Control Status ✅ PASS · ❌ FAIL · ⚠️ WARN · ⏭️ SKIP for each of the 20 checks
HTML Report Dark-themed, browser-ready report with a score gauge
JSON Export Machine-readable output for SIEM ingestion or scripting
Baseline Diff Track drift between scans — see [IMPROVED] and [REGRESSION]

No Python. No Ruby. No jq. No internet. Runs on any Linux with Bash 4+.


⚡ Quick Start

1 — Clone / unzip and make executable

unzip cisaudit.zip -d ~/cisaudit
cd ~/cisaudit/cisaudit

chmod +x cisaudit.sh install.sh
chmod +x lib/*.sh controls/*.sh checks/*.sh
chmod +x tests/test_runner.sh tests/test_helpers.sh tests/test_01_initial_setup.sh

2 — Try it instantly (no root needed)

# Demo with fake "secure" system → expect near 100% PASS
bash cisaudit.sh -t testdata/fixtures

# Demo with fake "insecure" system → shows what failures look like
bash cisaudit.sh -t testdata/fixtures_fail

3 — Audit your real system

sudo bash cisaudit.sh

4 — (Optional) Install system-wide

sudo bash install.sh
# Now you can just run: sudo cisaudit

🛠️ All Commands

# ── Basic usage ───────────────────────────────────────────────────────────────
sudo cisaudit                        # Live audit, terminal output
sudo cisaudit --summary              # Summary score only (no per-control rows)
sudo cisaudit --failures-only        # Only show FAIL and WARN controls
sudo cisaudit --no-color             # Disable ANSI color (for piping/logging)

# ── Output formats ────────────────────────────────────────────────────────────
sudo cisaudit -f html -o report.html # Generate dark-themed HTML report
sudo cisaudit -f json -o report.json # Export machine-readable JSON
xdg-open report.html                 # Open HTML report in browser

# ── CIS Levels ────────────────────────────────────────────────────────────────
sudo cisaudit -l 1                   # Only Level 1 controls (basic hardening)
sudo cisaudit -l 2                   # Only Level 2 controls (advanced hardening)

# ── Test mode (no root, no real system) ──────────────────────────────────────
bash cisaudit.sh -t testdata/fixtures       # PASS fixtures — shows 100% healthy
bash cisaudit.sh -t testdata/fixtures_fail  # FAIL fixtures — shows broken config

# ── Baseline and drift detection ─────────────────────────────────────────────
sudo cisaudit -f json --baseline baseline-day1.json  # Save today as baseline
sudo cisaudit --diff baseline-day1.json              # Compare to baseline

# ── Test suite ────────────────────────────────────────────────────────────────
bash tests/test_runner.sh            # Run all 29 automated tests

📋 Controls Covered

All 20 controls are from CIS Benchmark for Linux — Section 1 (Initial Setup).

Control ID What it checks Why it matters
1.1.1.1 cramfs filesystem blocked Prevents hiding malicious files in cramfs images
1.1.1.2 squashfs filesystem blocked Reduces kernel attack surface
1.1.1.3 udf filesystem blocked Prevents mounting suspicious disk images
1.1.2.1 /tmp is a separate partition Isolates temp files from the root filesystem
1.1.2.2 /tmp mounted with nodev Stops device files in /tmp
1.1.2.3 /tmp mounted with nosuid Stops setuid programs running from /tmp
1.1.2.4 /tmp mounted with noexec Blocks script execution in /tmp (common attack vector)
1.1.3.2 /var/tmp mounted with nodev Same isolation for the persistent temp dir
1.1.3.3 /var/tmp mounted with nosuid Same protection for /var/tmp
1.2.1 Package repos configured Ensures security updates can be received
1.2.2 GPG keys configured Verifies packages come from trusted sources
1.3.1 AIDE installed File integrity monitoring agent
1.3.2 AIDE scheduled Ensures AIDE actually runs regularly
1.4.1 GRUB password set Prevents boot-level attacks
1.5.1 ASLR enabled Randomises memory layout to defeat exploits
1.5.2 ptrace restricted Stops processes from spying on each other
1.5.3 Core dumps restricted Prevents sensitive data leaking in crash files
1.5.4 prelink removed Prelink interferes with integrity-checking tools
1.6.1 AppArmor installed Mandatory access control for programs
1.6.2 AppArmor enabled at boot Ensures AppArmor protection starts automatically

🏗️ Architecture

The tool is built around the Registry Pattern — checks are completely separate from the engine that scores them. Adding a new check only touches 2 files.

cisaudit/
│
├── cisaudit.sh              ← Entry point — CLI parsing and orchestration
├── install.sh               ← Installs cisaudit to /usr/local/bin
│
├── lib/                     ← Core engine (no check logic lives here)
│   ├── constants.sh         ← Status codes, colours, section names
│   ├── utils.sh             ← Primitives: read_file(), check_sysctl(), etc.
│   ├── registry.sh          ← In-memory store for control metadata
│   ├── engine.sh            ← Runs all controls, collects results, scores (awk)
│   ├── report_terminal.sh   ← Colorised table output with ANSI codes
│   ├── report_json.sh       ← JSON serialiser (pure Bash, no jq)
│   ├── report_html.sh       ← Self-contained dark-theme HTML report
│   └── baseline.sh          ← Saves / diffs JSON baseline files
│
├── controls/
│   └── registry_data.sh     ← register_control() calls for all 20 controls
│
├── checks/
│   └── 01_initial_setup.sh  ← check_X_X_X() functions — the actual logic
│
├── testdata/
│   ├── fixtures/            ← Mock filesystem: all controls PASS
│   └── fixtures_fail/       ← Mock filesystem: all controls FAIL
│
└── tests/
    ├── test_runner.sh           ← Test harness
    ├── test_helpers.sh          ← assert_status(), assert_pass(), assert_fail()
    └── test_01_initial_setup.sh ← 29 tests — one PASS + one FAIL per control

Data flow

cisaudit.sh
    │
    ├─ loads lib/*.sh              (engine, reporters, utils)
    ├─ loads controls/registry_data.sh    (register_control → registry.sh)
    ├─ loads checks/01_initial_setup.sh   (check functions)
    │
    └─ engine.sh :: run_all_checks()
            │  for each registered control…
            ├─ calls check_X_X_X()  →  returns PASS / FAIL / WARN / SKIP
            └─ stores result in results[] associative array
                    │
                    └─ score_results()  (awk)
                            │
                            └─ report_terminal / report_json / report_html

Adding a new control (only 2 files touched)

# 1. Register it in controls/registry_data.sh
register_control "2.1.1" "1" "Services" "Ensure time synchronisation is in use"

# 2. Implement the check in checks/01_initial_setup.sh
check_2_1_1() {
  systemctl is-enabled chrony &>/dev/null && echo "PASS" || echo "FAIL"
}

That's it. The engine, scorer, and all reporters pick it up automatically.


🧪 Test Suite

Every control has two fixture tests — one for the PASS path, one for the FAIL path.

bash tests/test_runner.sh

Expected output:

━━━ cisaudit Test Suite ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

  Running: test_case_1_1_1_1_fail
    ✓ cramfs should be FAIL when not in modprobe.d
  Running: test_case_1_1_1_1_pass
    ✓ cramfs should be PASS with proper modprobe.d config
  Running: test_case_1_1_1_2_fail
    ✓ squashfs should be FAIL when not blocked
  Running: test_case_1_1_1_2_pass
    ✓ squashfs should be PASS with proper config
  ... (25 more tests)

━━━ Results ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  PASS: 29   FAIL: 0   SKIP: 0

✅ All tests passed!

Tests run against mock filesystem fixtures in testdata/ — no root, no real system required. Perfect for CI pipelines.


📊 Understanding Your Score

Score Meaning
80 – 100% ✅ Well hardened — ready for a production or compliance review
50 – 79% ⚠️ Partially hardened — important controls still need attention
0 – 49% ❌ Default config — system needs significant hardening

A fresh Kali Linux install scores ~25–30%. That is completely expected — Kali is a pen-testing distro, not a hardened server OS. The tool tells you exactly what to fix to raise the score.


💡 Key Concepts

What is the CIS Benchmark?

The Center for Internet Security (CIS) publishes hardening guides for operating systems, cloud providers, and applications. The CIS Linux Benchmark defines hundreds of controls that reduce attack surface. Companies use it as a baseline for SOC 2, PCI DSS, and ISO 27001 audits.

What is ASLR and why does it matter?

Address Space Layout Randomisation places a program's stack, heap, and libraries at random memory addresses each time it runs. Without ASLR, an attacker who finds a buffer overflow can hardcode the address they want to jump to. With ASLR they have to guess — and they'll usually crash the process instead of exploiting it.

What is AppArmor?

A Linux Security Module (LSM) that enforces mandatory access control profiles per program. Even if a process is compromised, AppArmor limits which files it can read, which ports it can open, and which syscalls it can make. Ubuntu and Debian ship it by default.

Why is noexec on /tmp important?

/tmp is world-writable. Attackers who get limited access to a system often upload a shell script or compiled binary to /tmp and try to execute it. The noexec mount option blocks execution from that directory entirely, breaking this common privilege-escalation step.

Why pure Bash? No Python/Ruby/jq?

A hardening tool should work on any Linux system — including minimal containers, systems with no internet access, and fresh installs with no extra packages. Pure Bash is always available. This design also means the tool itself has zero supply-chain dependencies.

What is the Registry Pattern used here?

Check metadata (ID, level, description) is stored separately from check logic (the function that runs it). The engine iterates the registry and calls the matching function by name. Adding a new check means touching exactly 2 files — nothing else changes. This is the same pattern used in plugin systems and rule engines.


🔧 Troubleshooting

Problem Fix
Permission denied on scripts chmod +x cisaudit.sh lib/*.sh checks/*.sh controls/*.sh
command not found: cisaudit Run sudo bash install.sh first
Score is ~26% Normal on Kali — it is not a hardened OS
Some checks show SKIP Those require root — run with sudo cisaudit
HTML report opens blank Re-generate: sudo cisaudit -f html -o report.html
bash: bad array subscript Upgrade to Bash 4+ — check with bash --version

📜 License

MIT — free to use, share, and modify for any purpose.


Student portfolio project demonstrating Linux security hardening, Bash scripting,
and compliance tooling concepts used in real SOC and DevSecOps environments.

Built with 100% pure Bash · Zero runtime dependencies · Runs offline

About

A Bash CLI tool that audits Linux systems against the CIS Benchmark and gives a compliance score with terminal, JSON, and HTML reports.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages