Skip to content

Processes listening on 127.0.0.1 can also form privilege boundaries. See Network and IPC for how to find listeners. This page examines who can connect to a discovered service and what the service does.

Terminal window
ss -ant
ps auxww | grep -E '<port>|<service>'

A root service on 127.0.0.1, an ordinary user’s development server, a service using a protocol other than HTTP, or an administrative UI can provide a route to privilege escalation or lateral movement.

  • A root administration application performs actions only on localhost. Even if sudo is denied, the action can form a privilege boundary.
  • A listener that does not speak HTTP (such as OPC UA) needs a dedicated client. A failed curl request does not mean the service is unreachable.
  • An administrative UI parameter becomes input to command injection later in the flow.
  • If an embedded HTTP server running as root is configured to execute saved files as scripts, writing to its public directory leads to code execution.
  • A language runtime’s debug port (such as Node inspector on 9229) can provide a way to read files as that process’s user. Record the owning PID, cmdline, and UID.
  • After entry through an external protocol, the next boundaries may be a localhost daemon and a Unix socket. See Unix Sockets and File Descriptors for the socket side.
  • A low-privilege user can connect to the localhost service.
  • The service runs as a more privileged user than the current user.
  • A Web API, custom protocol, file-saving operation, or administrative action passes user-controlled input to a privileged operation.
Terminal window
curl -i --max-time 3 http://127.0.0.1:<PORT>/
nc -vz 127.0.0.1 <PORT>
tr '\0' ' ' < /proc/<PID>/cmdline
ls -l /proc/<PID>/fd
  • Purpose: Check reachability, protocol, running user, and public or working directory.
  • Prerequisites: Avoid overwhelming the service. Do not send large amounts of manually crafted input to an unknown binary protocol.
  • Interpreting output: If HTTP responds, enumerate its routes. If it returns 401, look for credentials. For a custom protocol, look for implementation code or a dedicated client.
  • Troubleshooting: Check tunnel direction, IPv6 binding, Basic auth, cookies, protocol differences, and whether the service is stalled.
  • Alternative: SSH -L, Meterpreter portfwd, socat, or /proc/net/tcp.
  • State changes: curl and nc leave connection logs. POST requests and protocol commands may change state.
  • Confirmed: The current user can connect to <port>, and ps confirms that it runs as <user>.
  • Inferred: Based on the document root or UID, <service> may be able to read the target file.
  • Unverified: The socket owner, authentication method, and actual range of readable files remain unverified.

Listening on localhost means direct external connections are disabled. Connections may still be possible from the same host, an SSH tunnel, or a container’s shared network. Treat services run by root or another user as privilege boundaries.

Trace the processing from input to sink in Trust Boundaries in Custom Code.