TimThumb.php Overview: Understanding the Deprecated Image Script
What is TimThumb?
TimThumb is a PHP script originally developed to dynamically resize, crop, and cache images on websites. It gained significant popularity in the late 2000s and early 2010s, particularly among WordPress theme developers, as it provided an easy way to generate optimized thumbnails without requiring complex image processing setup.
For the migration deep-dive and related security topics, see Migrating Away from TimThumb — Security Guide, assert_quiet_eval in PHP — Malware, and ElFinder XSS Vulnerability.
Key Features
Despite its deprecated status, understanding TimThumb's original features helps explain its popularity:
| Feature | Description |
|---|---|
| Dynamic Image Resizing | Resize images to specified dimensions (width, height) on-the-fly via URL parameters. |
| Cropping | Crop images to fit specific aspect ratios using the zoom crop parameter. |
| Caching System | Store resized images in a cache directory to improve performance on subsequent requests. |
| External Image Support | Could resize images from external URLs, though this feature introduced significant security risks. |
| Simple Implementation | Required only a single PHP file and basic server configuration to start using. |
Why TimThumb is Deprecated
1. Critical Security Issues
TimThumb has multiple well-documented security vulnerabilities:
- Remote Code Execution: Vulnerabilities allowed attackers to upload and execute malicious PHP files.
- External URL Exploits: The ability to fetch images from external URLs could be abused to perform server-side request forgery (SSRF) attacks.
- Path Traversal: Insufficient input validation allowed attackers to access files outside intended directories.
2. Performance Concerns
- Server Load: Dynamically generating images for every request created significant CPU load on busy websites.
- No Modern Optimizations: Lacks support for modern image formats like WebP or AVIF, and doesn't implement efficient compression algorithms.
3. Maintenance Stopped
The script has not received official updates or security patches since approximately 2011. The original developers have abandoned the project, and no one maintains a secure version.
Recommended Alternatives
Instead of using TimThumb, choose from these modern, secure, and well-maintained alternatives:
| Solution | Best For | Implementation |
|---|---|---|
| WordPress Core Functions | WordPress websites | Use built-in functions: the_post_thumbnail(), add_image_size() |
| Intervention Image | Custom PHP applications | composer require intervention/image - Modern library with good security practices |
| Cloud CDN Services | High-traffic production sites | Cloudinary, Imgix, or ImageKit for edge processing and optimization |
| PHP GD/Imagick | Simple custom scripts | PHP's native image processing extensions with proper security validation |
Example: WordPress Native Image Handling
// Add custom image sizes in functions.php
add_image_size('custom-thumbnail', 300, 200, true);
// Display in templates
<?php the_post_thumbnail('custom-thumbnail'); ?>
Example: Intervention Image Library
// Install via Composer
composer require intervention/image
// Basic usage
use Intervention\Image\ImageManager;
$manager = new ImageManager(['driver' => 'gd']);
$image = $manager->make('path/to/image.jpg')
->resize(300, 200)
->save('path/to/output.jpg');
TimThumb Configuration (If You Must Use It)
Download and Installation
The last archived version of TimThumb can be found on GitHub, but be aware this is unmaintained software:
# Download (not recommended)
wget https://github.com/timthumb/timthumb/archive/refs/heads/master.zip
# Basic setup
mkdir cache
chmod 755 cache
chmod 777 cache # Required for web server write access
Basic Usage Syntax
<img src="timthumb.php?src=path/to/image.jpg&w=300&h=200&zc=1" alt="Thumbnail">
| Parameter | Description | Example |
|---|---|---|
| src | Path to the source image | src=images/photo.jpg |
| w | Width in pixels | w=300 |
| h | Height in pixels | h=200 |
| zc | Zoom crop (1=enabled, 0=disabled) | zc=1 |
| q | Image quality (0-100) | q=85 |
Security Hardening (Minimal Recommendations)
If you absolutely must run TimThumb temporarily, implement these restrictions:
- Disable external images in the script configuration:
define('ALLOW_EXTERNAL', false); - Restrict allowed domains if external images are necessary:
define('ALLOW_EXTERNAL', true); define('ALLOW_ALL_EXTERNAL_SITES', false); define('ALLOWED_SITES', ['https://yourdomain.com']); - Secure the cache directory with .htaccess:
# In cache/.htaccess Order deny,allow Deny from all - Limit file types to common image formats only.
How to Migrate Away from TimThumb
Migration Steps
- Identify Usage: Search your codebase for TimThumb references:
grep -r "timthumb" /path/to/website/ grep -r "timthumb.php" /path/to/website/ - Choose Replacement: Select an alternative based on your platform (WordPress, custom PHP, etc.)
- Update Image References: Replace TimThumb URLs with your new solution.
- Generate Resized Images: Create all necessary thumbnail sizes.
- Set Up Redirects for old URLs (optional):
# In .htaccess RewriteEngine On RewriteRule ^timthumb\.php$ /image-unavailable.jpg [L,R=301] - Remove TimThumb: Delete the timthumb.php file and cache directory.
Example: Basic PHP GD Replacement Script
<?php
// secure-image-resizer.php - A more secure basic replacement
header('Content-Type: image/jpeg');
// Get and validate parameters
$src = isset($_GET['src']) ? $_GET['src'] : '';
$width = isset($_GET['w']) ? (int)$_GET['w'] : 0;
$height = isset($_GET['h']) ? (int)$_GET['h'] : 0;
// Security validations
if(empty($src) || $width <= 0 || $height <= 0 ||
$width > 2000 || $height > 2000 ||
strpos($src, '..') !== false) {
http_response_code(400);
exit;
}
// Only allow local images
$image_path = __DIR__ . '/' . ltrim($src, '/');
if(!file_exists($image_path)) {
http_response_code(404);
exit;
}
// Process image
$image = imagecreatefromjpeg($image_path);
$resized = imagescale($image, $width, $height);
imagejpeg($resized, null, 85);
// Cleanup
imagedestroy($image);
imagedestroy($resized);
?>


