Skip to content

Conversation

@carlospolop
Copy link
Collaborator

🔧 Automated Privilege Escalation Check Addition

🤔 Privilege Escalation Reasoning

The post describes two generic, real‑world misconfigurations that enable local privilege escalation: (1) a Node.js process started with the --inspect debugger bound to localhost (default 9229), which allows any local user to attach and execute arbitrary JS in the context of the process owner; and (2) Chrome/Chromium running as root with a remote debugging port exposed on localhost (commonly 9222), which grants powerful DevTools control that can be abused for code execution as root. Both are platform‑agnostic development/debug flags, not CTF‑specific custom apps or uncommon 3rd‑party software bugs, and are prevalent enough in real environments to warrant automated detection. These fit linpeas’ goal of flagging dangerous local services/misconfigurations leading to privilege escalation on Linux/macOS.

🤖 Implementation Details

PEASS linpeas agent completed successfully with 92 items. Agent Comment: Here’s what I did to implement this technique in linpeas, with code changes made directly in the repo at /tmp/hacktricks_update_58o_lvba/repo.

Step-by-step work

  1. Analyzed the technique and decided change is needed
  • The blog’s privesc chain depends on two very real-world, generic misconfigurations:
    • Node.js V8 inspector enabled locally (—inspect/—inspect-brk), trivially attachable for RCE as the process owner.
    • Chrome/Chromium debugging surfaces (Chrome DevTools via --remote-debugging-port or ChromeDriver on 9515) running as root, enabling RCE as root.
  • linpeas already “highlights” suspicious process parameters via processesVB (includes --inspect and --remote-debugging-port), but it doesn’t:
    • Correlate those flags to actual listening sockets/addresses.
    • Call out the owning user and exact bind/port to assess LPE risk quickly.
    • Identify ChromeDriver listeners (9515) and emphasize risk if they’re root-owned.
  • These exposures are common in real environments and fast to check, so they meet PEASS criteria to add.
  1. Explored repo and current checks
  • Relevant structure:
    • linPEAS/builder/linpeas_parts/4_procs_crons_timers_srvcs_sockets: process and sockets related checks.
    • variables/processesVB.sh already color-highlights “inspect” and “--remote-debugging-port”.
    • 5_network_information/4_Open_ports.sh lists active ports but doesn’t classify debuggers.
  • No existing module provided the correlation and high-signal reporting we need.
  1. Determined where to add the new checks
  • Added a new lightweight module in the processes/sockets section:
    • File: linPEAS/builder/linpeas_parts/4_procs_crons_timers_srvcs_sockets/17_Debuggable_runtimes_exposure.sh
    • This keeps it close to process and socket enumeration and follows the numeric ordering.
  1. Implemented the new detection module
  • New module: PR_Debuggable_runtimes_exposure

    • Title: Processes & Cron & Services & Timers - Debuggable runtimes exposure
    • Author: HT Bot
    • Last Update: 30-10-2025
    • Functions Used: print_2title, print_info
    • Global Variables used: $E, $SED_RED, $SED_RED_YELLOW, $USER
    • Fat linpeas: 0, Small linpeas: 1
  • What the module does:

    • Node.js inspector detection
      • Iterates /proc to find node/nodejs processes.
      • Parses their cmdlines for:
        • --inspect, --inspect-brk, --inspect-port=
      • Derives inspector port (handles --inspect-port=NNN, --inspect=HOST:PORT or =PORT; defaults to 9229).
      • Correlates to a listening address via ss -H -ltnp (fallback to lsof if ss not available).
      • Prints: user, PID, bind address:port, and truncated cmdline.
      • Highlights loopback binds and root users with existing SED color vars.
    • Chrome/Chromium DevTools and ChromeDriver detection
      • ChromeDriver:
        • Detects chromedriver binary.
        • Looks for a listener on port 9515 and prints user/PID/bind.
        • Emphasizes if running as root (high LPE potential).
      • Chrome/Chromium:
        • Detects chrome/chromium/google-chrome/headless_shell or any process with --remote-debugging-port.
        • Extracts port (default 9222 if unspecified).
        • Correlates bind/port via ss/lsof, prints user/PID/bind and truncated cmdline.
    • The module prints two separate section titles (one for Node inspector, one for Chrome/Chromedriver) only when a finding exists, keeping noise low.
  • Code added:

    • New file: linPEAS/builder/linpeas_parts/4_procs_crons_timers_srvcs_sockets/17_Debuggable_runtimes_exposure.sh
      • Uses fast /proc traversal (no find /).
      • Respects portability (ss preferred, lsof fallback) and works without root.
      • Degrades gracefully if bind cannot be confirmed (labels with ?).
  1. Documentation update
  • Appended a short “New checks” note to linPEAS/README.md to reflect the capability:
    • Detect Node.js V8 Inspector listeners and Chrome/Chromium DevTools / ChromeDriver debug endpoints bound locally; highlights potential local privilege escalation paths.
  1. Verified no syntax errors
  • Ran sh -n on the new module to confirm syntax is OK.
  • The module only relies on functions/variables already present in linpeas base (print_2title, print_info, $E, SED color vars) and uses quick system tools (ss/lsof).

Why this is valuable and not redundant

  • Existing processesVB only color-highlights suspicious flags; it doesn’t correlate them to actual listening sockets or print the bind/port and owner in a focused, actionable way.
  • The new module specifically calls out the exact exposure, the user it affects, and where to attach, which is decisive for quick priv-esc workflow:
    • Node inspector exposed: “Attach and run JS as USER”
    • Chrome/Chromium/ChromeDriver as root: “Attach and likely gain root”
  • It also detects ChromeDriver (9515) explicitly, which is the exact vector used to escalate to root in the blog.

Where it was added

  • File path:
    • linPEAS/builder/linpeas_parts/4_procs_crons_timers_srvcs_sockets/17_Debuggable_runtimes_exposure.sh

How the detection works (summary)

  • Node.js V8 Inspector

    • Finds node/nodejs with --inspect flags.
    • Extracts inspector port (9229 default) and confirms a LISTEN on that port for the PID using ss or lsof.
    • Prints: user, PID, bind (e.g., 127.0.0.1:9229), and snippet of the cmdline.
    • Rationale: Local-only binds are still exploitable via SSH port forwarding or other local footholds, enabling RCE as the process owner.
  • Chrome/Chromium DevTools and ChromeDriver

    • ChromeDriver: identifies chromedriver, checks for a LISTEN on 9515, prints owner and bind.
    • Chromium/Chrome: finds --remote-debugging-port=PORT, confirms listener, prints owner and bind.
    • Rationale: A root-owned Chrom(e|ium)/ChromeDriver with an accessible debug endpoint lets an attacker run arbitrary commands (e.g., via goog:chromeOptions.binary or DevTools Protocol), escalating to root.

What you’ll see at runtime

  • Example output lines (colors applied by linpeas):
    • Debuggable runtimes exposure (Node inspector)
      • dev 38310 127.0.0.1:9229 node --inspect=127.0.0.1:9229 /path/start.js
    • Debuggable runtimes exposure (Chrome DevTools/ChromeDriver)
      • root 758 127.0.0.1:9515 chromedriver
      • root 812 127.0.0.1:9222 /opt/google/chrome/chrome --remote-debugging-port=9222 ...

Notes on performance and compatibility

  • No deep recursive scanning, only /proc iteration and a single ss/lsof query per candidate process/port.
  • Works without root; falls back to lsof if ss is missing; if neither confirms the bind, still reports the most likely port with a “?” suffix.
  • MacOS support for this exact module wasn’t added (linpeas Mac mode exists separately), but the logic is portable and contained to Linux paths and commands.

Final check results

  • New module passes sh -n (no syntax errors).
  • Uses only existing global color variables and print helpers declared elsewhere in linpeas base.
  • README updated with a concise note about the new checks.

If you want me to expand this further (e.g., add macOS variants with ps -axo and lsof on Darwin, or include an additional hint line when dangerous listeners belong to root/system users), just say the word.

🏗️ Builder Agent Response

LinPEAS build agent completed successfully with 54 items. Agent Comment: Here’s what I did and the outcome:

Actions

  • Navigated to /tmp/hacktricks_update_58o_lvba/repo/linPEAS.
  • Ran the build: python3 -m builder.linpeas_builder --all --output /tmp/linpeas_fat.sh.

Diagnosed issues

  • The build failed during module validation with:
    • Used variable 'USER' in module ...17_Debuggable_runtimes_exposure.sh doesn't exist in the module code.
    • After fixing that, it failed again because several local variables were being flagged as undefined globals: $printed, $found, $bind, $pid, $port, $exe, $user, $cmd, $out, $val.

Fixes applied

  • Edited linPEAS/builder/linpeas_parts/4_procs_crons_timers_srvcs_sockets/17_Debuggable_runtimes_exposure.sh:
    • Removed unused variables from the metadata Global Variables line:
      • Dropped $USER and $SED_LIGHT_MAGENTA (they weren’t used in the code).
      • Kept only the ones actually used: $E, $SED_RED, $SED_RED_YELLOW.
    • Declared the local variables that appear in the script under Generated Global Variables:
      • $printed, $found, $bind, $pid, $port, $exe, $user, $cmd, $out, $val.

Verification

  • Re-ran the build command. It completed successfully.
  • Output file created: /tmp/linpeas_fat.sh (size ~16.55 MB).
  • Quick header check confirms a valid linpeas script.

Status

  • LinPEAS now builds successfully with the provided command, and the output is available at /tmp/linpeas_fat.sh.

This PR was automatically created by the HackTricks Feed Bot. Please review the implementation carefully and test thoroughly before merging.

…d traversal + static XOR → secrets → Node inspector RCE →
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants