Skip to content

Conversation

@carlospolop
Copy link
Collaborator

🔧 Automated Privilege Escalation Check Addition

🤔 Privilege Escalation Reasoning

The blog describes a cloud-side local privilege escalation pattern that is both realistic and widely applicable in production: abusing EC2 Instance Metadata Service (IMDS) from containers on ECS‑on‑EC2 to obtain higher-privilege credentials and pivot. While this is not a classic OS-level privesc (kernel, setuid, sudo, etc.), from the perspective of a foothold inside a Linux container/host it is a straightforward, automatable step to escalate effective privileges in the environment.

Key techniques that are generic and not CTF-specific:

  1. IMDS credential theft from inside containers (ECS on EC2)

    • From any compromised ECS task on EC2, an attacker can query:
      • http://169.254.169.254/latest/meta-data/iam/security-credentials/ → list available instance profile names, then
      • http://169.254.169.254/latest/meta-data/iam/security-credentials/{InstanceProfileName} → obtain host-level EC2 instance profile credentials.
    • These credentials typically have broader permissions than the task role, and are usable immediately via AWS APIs, enabling privilege escalation from the container to higher-privileged AWS identities (enumerate ECS, S3, STS AssumeRole, etc.).
    • This is a common, well-known class of cloud privesc, not relying on custom binaries or niche software.
  2. Network-mode–dependent IMDS reachability (awsvpc / host / bridge)

    • The research shows that even when IMDSv2 with hop limit 1 is enforced at the instance level, IMDS may still be reachable from containers:
      • awsvpc mode: IMDS reachable (single hop).
      • host mode: IMDS reachable (shares host network namespace).
      • bridge mode: typically blocked by hop limit 1, because Docker bridge adds an extra hop, unless additional iptables rules exist or are misconfigured.
    • For an automated local enumeration tool like linpeas, this means: do not assume IMDS is blocked merely because hop limit = 1; always probe actual reachability from within the container/host.
  3. Detection of hardening that blocks IMDS
    While mainly defensive guidance, these are also useful checks for an attacker-focused privesc enumerator to understand why IMDS is inaccessible:

    • In awsvpc mode, IMDS can be blocked via ECS agent configuration on the Linux host:
      • /etc/ecs/ecs.config with ECS_AWSVPC_BLOCK_IMDS=true.
    • In bridge networking, IMDS might be blocked by iptables rules in the DOCKER-USER chain such as:
      • --in-interface docker+ --destination 169.254.169.254/32 --jump DROP.
    • In host network mode, IMDS exposure vs. task-roles is influenced by ECS_ENABLE_TASK_IAM_ROLE_NETWORK_HOST.
  4. ECScape-style agent impersonation (conceptual)

    • The post references ECScape: after obtaining instance-profile credentials via IMDS, the attacker impersonates the ECS agent to the control plane (over the ECS WebSocket protocol) and receives credentials for all tasks on that host.
    • Implementing agent-impersonation is out of scope for linpeas, but discovering that you can reach IMDS and obtain an EC2 instance profile from a container is a crucial precursor and is directly automatable.

Why this fits linpeas:

  • linpeas already aims to detect commonly exploitable local misconfigurations and environment-linked escalation paths on Linux, including cloud metadata access (in some forks/variants).
  • ECS-on-EC2 is extremely common in real-world environments; IMDS abuse is a mainstream technique and not tied to special CTF-only binaries.
  • The technique is not about a specific old-vulnerable package version; instead it leverages the standard AWS metadata interface, which is ubiquitous.

Why not winpeas / macOS:

  • The blog and described techniques are specific to Linux-based ECS container instances and Docker networking modes on EC2. There is no Windows- or macOS-specific local privesc described.

Therefore, the post does contain a realistic, reusable privilege escalation pattern (cloud-side) that linpeas could meaningfully enumerate and highlight for Linux systems running inside AWS.

🤖 Implementation Details

PEASS linpeas agent completed successfully with 70 items. Agent Comment: Summary of additions

  • Added a dedicated ECS-on-EC2 IMDS exposure module (linPEAS/builder/linpeas_parts/3_cloud/16_AWS_ECS_IMDS.sh) to capture the blog’s privilege-escalation vector where ECS tasks can pivot to host- or cross-task IAM credentials via IMDS.
  • The module auto-runs whenever ECS task indicators or ECS agent files are present. It surfaces ECS LaunchType and NetworkMode straight from the ECS task metadata so operators can immediately see whether they are in awsvpc, bridge, or host networking—the exact modes the blog shows behave differently with hop-limit hardening.

Detection logic implemented

  • Performs a lightweight IMDS reachability probe using IMDSv2 semantics (token PUT + IAM role listing). Successful token retrieval is flagged as a high-risk finding and shows any instance-profile role names exposed. Failure paths distinguish between unreachable metadata (consistent with hop-limit or firewalling) versus HTTP responses, mirroring the mitigation gaps highlighted in the post.
  • Reads /etc/ecs/ecs.config when available and explains the impact of ECS_AWSVPC_BLOCK_IMDS and ECS_ENABLE_TASK_IAM_ROLE_NETWORK_HOST, making it clear whether awsvpc or host-mode tasks are actually blocked from metadata as recommended in the article.
  • Inspects the DOCKER-USER iptables chain (or reports why it can’t) to show whether bridge-mode protections like the documented --in-interface docker+ --destination 169.254.169.254/32 --jump DROP rule are in place.
  • Provides contextual hints (AWS_EXECUTION_ENV, LaunchType, NetworkMode) so users can directly map the runtime to the awsvpc/bridge/host behaviors described in the research.

Testing

  • bash -n linPEAS/builder/linpeas_parts/3_cloud/16_AWS_ECS_IMDS.sh

No additional documentation updates were required because the new module is self-documenting via its metadata header and console output.

🏗️ Builder Agent Response

LinPEAS build agent completed successfully with 50 items. Agent Comment: LinPEAS now builds cleanly. Here’s what I did:

  1. Initial build attempt: Ran python3 -m builder.linpeas_builder --all --output /tmp/linpeas_fat.sh from /tmp/hacktricks_update_d9wq0okm/repo/linPEAS. It failed because the new module 3_cloud/16_AWS_ECS_IMDS.sh referenced several variables that weren’t declared in the module metadata, causing the builder’s sanity checks to abort.

  2. Metadata fix: Updated the module header to enumerate every variable it generates or consumes ($should_check_ecs_imds, $ecs_task_metadata, $launch_type, $network_modes, $imds_tool, $imds_token, $imds_roles, $first_role, $imds_http_code, $ecs_block_line, $ecs_host_line, $iptables_cmd, $docker_rules, $aws_exec_env). This aligns with the LinPEAS module syntax requirements so the builder can track variable provenance.

  3. Environment variable handling: Replaced the direct use of $AWS_EXECUTION_ENV with aws_exec_env=$(printenv AWS_EXECUTION_ENV 2>/dev/null) and documented $aws_exec_env as a generated variable. This prevents the builder from looking for an external module that “defines” AWS_EXECUTION_ENV, while still surfacing the information at runtime.

  4. Verification build: Re-ran the build command (timeout 300 s). The build completed successfully, finishing all internal steps and writing the assembled script to /tmp/linpeas_fat.sh.

No further errors occurred, so LinPEAS is ready. Let me know if you need additional tweaks or want the generated script copied elsewhere.


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

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