> For the complete documentation index, see [llms.txt](https://kruknight.gitbook.io/daemon-of-hacking/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://kruknight.gitbook.io/daemon-of-hacking/writeups/cyctf-2024/vending-machine.md).

# Vending Machine

## **Challenge Overview**

Upon accessing the challenge, we’re greeted by a straightforward page featuring an image of a vending machine and a text input field.&#x20;

<figure><img src="/files/PenmquA5b5kF07rKiL3v" alt=""><figcaption></figcaption></figure>

My first instinct was to examine the page source, where I discovered a JavaScript file named `script.js`.

```
// script.js
async function handleSubmit(event) {
    event.preventDefault(); // Prevent the default form submission

    const input = document.getElementById('product-input').value;
    const output = document.getElementById('output');
    const item = document.getElementById('item');

    // Simple product check and image mapping
    const products = {
        chips: "assets/chips.png",
        soda: "assets/soda.png",
        candy: "assets/candy.png",
        juice: "assets/juice.png"
    };
 setTimeout(async () => {
            // Wait for PHP response
            const response = await sendProduct(input);
            output.innerHTML = response; // Show PHP response
            item.style.transform = "translateY(0)"; // Reset position for next drop
            setTimeout(() => item.style.display = "none", 1000); // Hide item after a second
        }, 2000); // Time it takes to drop the item
    
	
	if (products[input.toLowerCase()]) {
        output.innerHTML = `Dropping ${input}... ðŸ¥³`;
        
        // Show item and animate drop
        item.style.display = "block"; // Show the item
        item.innerHTML = `<img src="${products[input.toLowerCase()]}" alt="${input}">`; // Set image source
        
        // Move item up to simulate dropping down
        item.style.transform = "translateY(-60px)"; // Move up to simulate dropping down
        
       
    } 

    // Clear input field
    document.getElementById('product-input').value = '';
}

// Function to send product to PHP and return response
async function sendProduct(product) {
    const response = await fetch('drop-item.php', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded',
        },
        body: `product=${encodeURIComponent(product)}` // Send product name
    });

    if (response.ok) {
        const responseData = await response.text(); // Get the response text
        return responseData; // Return response to be displayed
    } else {
        return "Error communicating with the server."; // Handle errors
    }
}
```

The function `sendProduct` particularly stood out, as it sends a request to `drop-item.php` with the user input as a parameter. After testing various inputs, I noticed it only accepted specific products (chips, soda, candy, juice) and filtered out most special characters and spaces. However,

## &#x20;Finding a Way In

When I attempted certain shell commands, such as <mark style="color:red;">`ls`</mark>, the application returned a message indicating it was “not allowed.”

<figure><img src="/files/aVBfgm7x2w66Xtkv7j4o" alt=""><figcaption></figcaption></figure>

I tried different commands that list directory contents. When I tested the <mark style="color:red;">`dir`</mark> command, it unexpectedly worked, revealing the directory contents. Among the files listed was one called <mark style="color:red;">`entrypoint.sh`</mark>

<figure><img src="/files/T7bRa7MaljBfefIAgwXQ" alt=""><figcaption></figcaption></figure>

Upon inspecting <mark style="color:red;">`entrypoint.sh`</mark>, I noticed it reads the flag from an environment variable named `FLAG` and stores it in a file located at <mark style="color:red;">`/home/apache/flag`</mark> with permissions set to allow reading.

<figure><img src="/files/wAj0G8P0jW4rCkRTeRPj" alt=""><figcaption></figcaption></figure>

To retrieve the value, I used <mark style="color:red;">`printenv`</mark> to list all environment variables. Sure enough, this revealed the hidden flag at the end.

<figure><img src="/files/FV31wsL3S4NK7CG5GXPw" alt=""><figcaption></figcaption></figure>

```
FLAG=CYCTF{_vJVo_yhwh76u-3yZ1Pp_Ex4SDGFacx0J7zhGPpIFd1cYeSj7s-h1doBOVPfH4Uq5h_bhtKmDnu98b4IqVZTbo8cdg9cSprylxscgesLcUrN3g}
```
