checksec

repository·main·Indexed 25 days ago

https://github.com/slimm609/checksec

A high-performance security auditing tool written in Go for verifying security properties such as PIE, RELRO, and Canaries in ELF executables and Linux kernel configurations. It supports scanning individual files, directories, running processes, and offline cross-compiled filesystems. Features include FORTIFY_SOURCE testing, kernel configuration scanning, and flexible output formats including JSON, YAML, XML, and CSV.

Tokens
9.5K
Snippets
31
Records
64
Agent score
78%

What's inside checksec

  1. Overview of checksec capabilities

    main

    The checksec tool inspects security properties of ELF executables, running processes, and the Linux kernel. It detects protections such as:

    • RELRO (Relocation Read-Only)
    • Stack Canaries
    • NX (No-Execute)
    • PIE (Position Independent Executable)
    • CFI (Control-Flow Integrity)
    • FORTIFY_SOURCE
    • RPATH/RUNPATH
  2. How kernel hardening features are detected

    main

    The checksec kernel command detects kernel features by reading the kernel configuration from the first available source in this order:

    1. /proc/config.gz
    2. /boot/config-$(uname -r)
    3. A specific config file provided by the user.

    Each feature is mapped to one or more CONFIG_* options. The verdict for each feature is displayed as follows:

    ValueColorMeaning
    EnabledgreenThe hardening option is on.
    DisabledredThe option is off or absent.

    Each row includes a Type (either Kernel Config or SELinux for SELinux boot settings) and a human-readable description.

  3. Distinguish between Unknown and N/A statuses

    main

    It is important to distinguish between Unknown (yellow) and N/A (italic), as they represent different scenarios:

    • Unknown (yellow): The check was performed, but the binary lacked sufficient information to reach a verdict. This is an indeterminate state, not necessarily a failure. For example, FORTIFY Lvl might be Unknown if the binary was built without annobin notes, meaning checksec cannot prove the level but won't guess. Other checks that may report Unknown include CFI, Stack Clash, and GLIBCXX assertions.
    • N/A (italic): The mitigation is meaningless for this specific binary type. For example, a W^X segment check reports N/A for relocatable object files (.o) because they lack loadable segments.
  4. Platform compatibility for checksec

    main

    checksec is primarily designed for ELF binaries and the Linux kernel.

    • macOS/BSD: It does not work on Mach-O binaries or macOS/BSD kernels.
    • BSD: While checksec may run on some BSD systems, these platforms are not officially supported.
  5. Interpret checksec output status and colors

    main

    Every check in checksec produces a value (the descriptive text, e.g., Full RELRO) and a status that determines the color of the output. The status is the fastest way to assess a binary's security posture.

    Color Legend

    Status (JSON/XML/YAML)Meaning
    greenGood. The mitigation is present and effective.
    yellowWarning. Partial protection, or checksec could not determine the state.
    redBad. The mitigation is missing/disabled, or an error occurred reading the binary.
    unsetInformational. Neutral facts (e.g., counts, DSO, active sanitizer set).
    italicNot applicable. The check does not apply to this specific binary type.

    In terminal output, these map to ANSI colors. In machine-readable formats (json, xml, yaml), they appear as the literal status strings listed above. You can control color output using the --color always|never flag.

  6. Understand FORTIFY source checks

    main

    The _FORTIFY_SOURCE mechanism replaces unbounded libc calls (like memcpy, sprintf, strcpy) with bounds-checked variants (like __memcpy_chk) when the compiler can infer buffer sizes.

    checksec reports this using two different methods:

    1. FORTIFY (Key: fortify_source): This is a symbol-based check that works on any binary. It compares the binary's imported libc functions against a set of fortifiable functions to see if any fortified (*_chk) variants are actually used.
    2. FORTIFY Lvl (Key: fortify_level): This is a metadata-based check that requires an annobin-enabled toolchain (e.g., RHEL/Fedora). It reads the specific fortification level recorded in the binary's compiler notes. If annobin is not used, this will report Unknown.

    To enable fortification in GCC, you must use optimization (-O1 or higher):

    gcc -O2 -D_FORTIFY_SOURCE=2     # or =3 for stricter checks (glibc 2.34+)
  7. Understand Seccomp process checks

    main

    Seccomp (Secure Computing mode) restricts the syscalls a process may use to protect against a compromised process making arbitrary syscalls.

    Detection: checksec detects Seccomp by reading the Seccomp field from /proc/<pid>/status.

    Values and Meanings:

    • Strict (green): Strict mode — only read/write/exit/sigreturn are allowed.
    • Filter (green): A BPF seccomp filter is installed.
    • Disabled (red): No seccomp restriction.
    • Unknown (yellow): The status could not be read or parsed.

    Implementation: Seccomp is a runtime property applied by the program itself (via prctl/seccomp()) or by a sandbox/container runtime (e.g., Docker's default profile or using --security-opt seccomp=profile.json). Because it is a runtime property, it is only available when scanning a process (checksec proc) and has no meaning for on-disk files (checksec file).

  8. Remediate RPATH and RUNPATH security risks

    main

    Both RPATH and RUNPATH can be used for library-injection/hijacking if they contain unsafe paths.

    Detection Keys: rpath and runpath.

    Security Guidance:

    • Best Practice: Prefer having no RPATH/RUNPATH at all.
    • If required: Use a trusted absolute path.
    • Avoid: Relative paths, empty paths, $ORIGIN, or world-writable directories.
    • Preference: Use RUNPATH over RPATH by using the linker flag -Wl,--enable-new-dtags.
  9. Strip Symbols from binaries

    main

    Stripping symbols protects against information leakage that aids reverse engineering and exploit development.

    Detection Key: symbols (used in JSON/YAML output and --fail-if gating).

    How to enable:

    • Strip existing binary: strip -s ./myapp
    • Strip at link time: gcc -s ...
    strip -s ./myapp        # strip an existing binary
    gcc -s ...              # strip at link time
  10. Implement CI gating with --fail-if

    main

    To use checksec as a build or CI gate, use the --fail-if <keys> flag. This flag accepts a comma-separated list of check keys (e.g., relro, canary, pie, nx, cfi). If any of the specified checks do not have a green status, checksec will exit with a non-zero exit code, failing the pipeline.

    Note: The keys correspond to the JSON/YAML keys found in the report.

    # Fail the pipeline unless the binary has RELRO, a stack canary, and PIE
    checksec file ./myapp --fail-if=relro,canary,pie
  11. Inspect cross-compiled or offline filesystems

    main

    checksec can inspect a target's filesystem offline, but you must account for two specific requirements:

    1. Kernel checks: These require live kernel resources. You must either run checksec on the target system itself or point it at the target's kernel config file.
    2. FORTIFY checks: By default, FORTIFY resolves libc from the running system. For an offline rootfs, you must explicitly point checksec to the target's libc using the --libc flag.

    All other checks work directly against the offline files.

    Example: Inspecting an offline application

    checksec file /mnt/target/usr/bin/app --libc /mnt/target/lib/libc.so.6
    checksec file /mnt/target/usr/bin/app --libc /mnt/target/lib/libc.so.6