Version Description
- Largely rewrote codebase to clean up code.
- Added functionality to download latest version of timthumb rather than relying on static version included in plugin.
- Added functionality to check if there is a newer version of timthumb available.
- Added scan to find obvious evidence of intrusion using timthumb exploit.
Download this release
Release Info
Developer | peterebutler |
Plugin | Timthumb Vulnerability Scanner |
Version | 1.4 |
Comparing to | |
See all releases |
Code changes from version 1.3 to 1.4
- cg-tvs-timthumb-latest.txt +38 -23
- readme.txt +14 -4
- screenshot-1.png +0 -0
- timthumb-vulnerability-scanner.php +10 -133
cg-tvs-timthumb-latest.txt
CHANGED
@@ -20,10 +20,10 @@
|
|
20 |
a new version of timthumb.
|
21 |
|
22 |
*/
|
23 |
-
define ('VERSION', '2.8'); // Version of this script
|
24 |
-
//Load a config file if it exists. Otherwise, use the values below
|
25 |
-
if( file_exists('timthumb-config.php'))
|
26 |
-
if(! defined(
|
27 |
if(! defined('DEBUG_LEVEL') ) define ('DEBUG_LEVEL', 1); // Debug level 1 is less noisy and 3 is the most noisy
|
28 |
if(! defined('MEMORY_LIMIT') ) define ('MEMORY_LIMIT', '30M'); // Set PHP memory limit
|
29 |
if(! defined('BLOCK_EXTERNAL_LEECHERS') ) define ('BLOCK_EXTERNAL_LEECHERS', false); // If the image or webshot is being loaded on an external site, display a red "No Hotlinking" gif.
|
@@ -114,14 +114,14 @@ if(! defined('WEBSHOT_XVFB_RUNNING') ) define ('WEBSHOT_XVFB_RUNNING', false);
|
|
114 |
// If ALLOW_EXTERNAL is true and ALLOW_ALL_EXTERNAL_SITES is false, then external images will only be fetched from these domains and their subdomains.
|
115 |
if(! isset($ALLOWED_SITES)){
|
116 |
$ALLOWED_SITES = array (
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
);
|
126 |
}
|
127 |
// -------------------------------------------------------------
|
@@ -186,7 +186,9 @@ class timthumb {
|
|
186 |
}
|
187 |
}
|
188 |
$this->cacheDirectory = FILE_CACHE_DIRECTORY;
|
189 |
-
touch($this->cacheDirectory . '/index.html')
|
|
|
|
|
190 |
} else {
|
191 |
$this->cacheDirectory = sys_get_temp_dir();
|
192 |
}
|
@@ -233,7 +235,7 @@ class timthumb {
|
|
233 |
$this->debug(2, "Fetching only from selected external sites is enabled.");
|
234 |
$allowed = false;
|
235 |
foreach($ALLOWED_SITES as $site){
|
236 |
-
if (
|
237 |
$this->debug(3, "URL hostname {$this->url['host']} matches $site so allowing.");
|
238 |
$allowed = true;
|
239 |
}
|
@@ -348,7 +350,7 @@ class timthumb {
|
|
348 |
return false;
|
349 |
} else { //Otherwise serve a 304
|
350 |
$this->debug(3, "File has not been modified since last get, so serving a 304.");
|
351 |
-
header ('
|
352 |
$this->debug(1, "Returning 304 not modified");
|
353 |
return true;
|
354 |
}
|
@@ -407,7 +409,7 @@ class timthumb {
|
|
407 |
$html .= '<li>' . htmlentities($err) . '</li>';
|
408 |
}
|
409 |
$html .= '</ul>';
|
410 |
-
header ('
|
411 |
echo '<h1>A TimThumb error has occured</h1>The following error(s) occured:<br />' . $html . '<br />';
|
412 |
echo '<br />Query String : ' . htmlentities ($_SERVER['QUERY_STRING']);
|
413 |
echo '<br />TimThumb version : ' . VERSION . '</pre>';
|
@@ -442,13 +444,17 @@ class timthumb {
|
|
442 |
//If this is a new timthumb installation we need to create the file
|
443 |
if(! is_file($lastCleanFile)){
|
444 |
$this->debug(1, "File tracking last clean doesn't exist. Creating $lastCleanFile");
|
445 |
-
touch($lastCleanFile)
|
|
|
|
|
446 |
return;
|
447 |
}
|
448 |
if(@filemtime($lastCleanFile) < (time() - FILE_CACHE_TIME_BETWEEN_CLEANS) ){ //Cache was last cleaned more than 1 day ago
|
449 |
$this->debug(1, "Cache was last cleaned more than " . FILE_CACHE_TIME_BETWEEN_CLEANS . " seconds ago. Cleaning now.");
|
450 |
// Very slight race condition here, but worst case we'll have 2 or 3 servers cleaning the cache simultaneously once a day.
|
451 |
-
touch($lastCleanFile)
|
|
|
|
|
452 |
$files = glob($this->cacheDirectory . '/*' . FILE_CACHE_SUFFIX);
|
453 |
$timeAgo = time() - FILE_CACHE_MAX_FILE_AGE;
|
454 |
foreach($files as $file){
|
@@ -812,7 +818,7 @@ class timthumb {
|
|
812 |
}
|
813 |
protected function getLocalImagePath($src){
|
814 |
$src = preg_replace('/^\//', '', $src); //strip off the leading '/'
|
815 |
-
$realDocRoot = realpath($this->docRoot);
|
816 |
if(! $this->docRoot){
|
817 |
$this->debug(3, "We have no document root set, so as a last resort, lets check if the image is in the current dir and serve that.");
|
818 |
//We don't support serving images outside the current dir if we don't have a doc root for security reasons.
|
@@ -827,7 +833,7 @@ class timthumb {
|
|
827 |
if(file_exists ($this->docRoot . '/' . $src)) {
|
828 |
$this->debug(3, "Found file as " . $this->docRoot . '/' . $src);
|
829 |
$real = realpath($this->docRoot . '/' . $src);
|
830 |
-
if(
|
831 |
return $real;
|
832 |
} else {
|
833 |
$this->debug(1, "Security block: The file specified occurs outside the document root.");
|
@@ -839,21 +845,30 @@ class timthumb {
|
|
839 |
if($absolute && file_exists($absolute)){ //realpath does file_exists check, so can probably skip the exists check here
|
840 |
$this->debug(3, "Found absolute path: $absolute");
|
841 |
if(! $this->docRoot){ $this->sanityFail("docRoot not set when checking absolute path."); }
|
842 |
-
if(
|
843 |
return $absolute;
|
844 |
} else {
|
845 |
$this->debug(1, "Security block: The file specified occurs outside the document root.");
|
846 |
//and continue search
|
847 |
}
|
848 |
}
|
|
|
849 |
$base = $this->docRoot;
|
850 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
851 |
$base .= $sub . '/';
|
852 |
$this->debug(3, "Trying file as: " . $base . $src);
|
853 |
if(file_exists($base . $src)){
|
854 |
$this->debug(3, "Found file as: " . $base . $src);
|
855 |
$real = realpath($base . $src);
|
856 |
-
if(
|
857 |
return $real;
|
858 |
} else {
|
859 |
$this->debug(1, "Security block: The file specified occurs outside the document root.");
|
20 |
a new version of timthumb.
|
21 |
|
22 |
*/
|
23 |
+
define ('VERSION', '2.8.2'); // Version of this script
|
24 |
+
//Load a config file if it exists. Otherwise, use the values below
|
25 |
+
if( file_exists(dirname(__FILE__) . '/timthumb-config.php')) require_once('timthumb-config.php');
|
26 |
+
if(! defined('DEBUG_ON') ) define ('DEBUG_ON', false); // Enable debug logging to web server error log (STDERR)
|
27 |
if(! defined('DEBUG_LEVEL') ) define ('DEBUG_LEVEL', 1); // Debug level 1 is less noisy and 3 is the most noisy
|
28 |
if(! defined('MEMORY_LIMIT') ) define ('MEMORY_LIMIT', '30M'); // Set PHP memory limit
|
29 |
if(! defined('BLOCK_EXTERNAL_LEECHERS') ) define ('BLOCK_EXTERNAL_LEECHERS', false); // If the image or webshot is being loaded on an external site, display a red "No Hotlinking" gif.
|
114 |
// If ALLOW_EXTERNAL is true and ALLOW_ALL_EXTERNAL_SITES is false, then external images will only be fetched from these domains and their subdomains.
|
115 |
if(! isset($ALLOWED_SITES)){
|
116 |
$ALLOWED_SITES = array (
|
117 |
+
'flickr.com',
|
118 |
+
'picasa.com',
|
119 |
+
'img.youtube.com',
|
120 |
+
'upload.wikimedia.org',
|
121 |
+
'photobucket.com',
|
122 |
+
'imgur.com',
|
123 |
+
'imageshack.us',
|
124 |
+
'tinypic.com',
|
125 |
);
|
126 |
}
|
127 |
// -------------------------------------------------------------
|
186 |
}
|
187 |
}
|
188 |
$this->cacheDirectory = FILE_CACHE_DIRECTORY;
|
189 |
+
if (!touch($this->cacheDirectory . '/index.html')) {
|
190 |
+
$this->error("Could note create the index.html file.");
|
191 |
+
}
|
192 |
} else {
|
193 |
$this->cacheDirectory = sys_get_temp_dir();
|
194 |
}
|
235 |
$this->debug(2, "Fetching only from selected external sites is enabled.");
|
236 |
$allowed = false;
|
237 |
foreach($ALLOWED_SITES as $site){
|
238 |
+
if ((strtolower(substr($this->url['host'],-strlen($site)-1)) === strtolower(".$site")) || (strtolower($this->url['host'])===strtolower($site))) {
|
239 |
$this->debug(3, "URL hostname {$this->url['host']} matches $site so allowing.");
|
240 |
$allowed = true;
|
241 |
}
|
350 |
return false;
|
351 |
} else { //Otherwise serve a 304
|
352 |
$this->debug(3, "File has not been modified since last get, so serving a 304.");
|
353 |
+
header ($_SERVER['SERVER_PROTOCOL'] . ' 304 Not Modified');
|
354 |
$this->debug(1, "Returning 304 not modified");
|
355 |
return true;
|
356 |
}
|
409 |
$html .= '<li>' . htmlentities($err) . '</li>';
|
410 |
}
|
411 |
$html .= '</ul>';
|
412 |
+
header ($_SERVER['SERVER_PROTOCOL'] . ' 400 Bad Request');
|
413 |
echo '<h1>A TimThumb error has occured</h1>The following error(s) occured:<br />' . $html . '<br />';
|
414 |
echo '<br />Query String : ' . htmlentities ($_SERVER['QUERY_STRING']);
|
415 |
echo '<br />TimThumb version : ' . VERSION . '</pre>';
|
444 |
//If this is a new timthumb installation we need to create the file
|
445 |
if(! is_file($lastCleanFile)){
|
446 |
$this->debug(1, "File tracking last clean doesn't exist. Creating $lastCleanFile");
|
447 |
+
if (!touch($lastCleanFile)) {
|
448 |
+
$this->error("Could note create cache clean timestamp file.");
|
449 |
+
}
|
450 |
return;
|
451 |
}
|
452 |
if(@filemtime($lastCleanFile) < (time() - FILE_CACHE_TIME_BETWEEN_CLEANS) ){ //Cache was last cleaned more than 1 day ago
|
453 |
$this->debug(1, "Cache was last cleaned more than " . FILE_CACHE_TIME_BETWEEN_CLEANS . " seconds ago. Cleaning now.");
|
454 |
// Very slight race condition here, but worst case we'll have 2 or 3 servers cleaning the cache simultaneously once a day.
|
455 |
+
if (!touch($lastCleanFile)) {
|
456 |
+
$this->error("Could note create cache clean timestamp file.");
|
457 |
+
}
|
458 |
$files = glob($this->cacheDirectory . '/*' . FILE_CACHE_SUFFIX);
|
459 |
$timeAgo = time() - FILE_CACHE_MAX_FILE_AGE;
|
460 |
foreach($files as $file){
|
818 |
}
|
819 |
protected function getLocalImagePath($src){
|
820 |
$src = preg_replace('/^\//', '', $src); //strip off the leading '/'
|
821 |
+
$realDocRoot = realpath($this->docRoot);
|
822 |
if(! $this->docRoot){
|
823 |
$this->debug(3, "We have no document root set, so as a last resort, lets check if the image is in the current dir and serve that.");
|
824 |
//We don't support serving images outside the current dir if we don't have a doc root for security reasons.
|
833 |
if(file_exists ($this->docRoot . '/' . $src)) {
|
834 |
$this->debug(3, "Found file as " . $this->docRoot . '/' . $src);
|
835 |
$real = realpath($this->docRoot . '/' . $src);
|
836 |
+
if(stripos($real, $realDocRoot) === 0){
|
837 |
return $real;
|
838 |
} else {
|
839 |
$this->debug(1, "Security block: The file specified occurs outside the document root.");
|
845 |
if($absolute && file_exists($absolute)){ //realpath does file_exists check, so can probably skip the exists check here
|
846 |
$this->debug(3, "Found absolute path: $absolute");
|
847 |
if(! $this->docRoot){ $this->sanityFail("docRoot not set when checking absolute path."); }
|
848 |
+
if(stripos($absolute, $realDocRoot) === 0){
|
849 |
return $absolute;
|
850 |
} else {
|
851 |
$this->debug(1, "Security block: The file specified occurs outside the document root.");
|
852 |
//and continue search
|
853 |
}
|
854 |
}
|
855 |
+
|
856 |
$base = $this->docRoot;
|
857 |
+
|
858 |
+
// account for Windows directory structure
|
859 |
+
if (strstr($_SERVER['SCRIPT_FILENAME'],':')) {
|
860 |
+
$sub_directories = explode('\\', str_replace($this->docRoot, '', $_SERVER['SCRIPT_FILENAME']));
|
861 |
+
} else {
|
862 |
+
$sub_directories = explode('/', str_replace($this->docRoot, '', $_SERVER['SCRIPT_FILENAME']));
|
863 |
+
}
|
864 |
+
|
865 |
+
foreach ($sub_directories as $sub){
|
866 |
$base .= $sub . '/';
|
867 |
$this->debug(3, "Trying file as: " . $base . $src);
|
868 |
if(file_exists($base . $src)){
|
869 |
$this->debug(3, "Found file as: " . $base . $src);
|
870 |
$real = realpath($base . $src);
|
871 |
+
if(stripos($real, $realDocRoot) === 0){
|
872 |
return $real;
|
873 |
} else {
|
874 |
$this->debug(1, "Security block: The file specified occurs outside the document root.");
|
readme.txt
CHANGED
@@ -11,7 +11,9 @@ Scans your wp-content directory for vulnerable instances of timthumb.php, and op
|
|
11 |
|
12 |
The recent Timthumb.php vulnerability (discussed [here](http://markmaunder.com/2011/08/02/technical-details-and-scripts-of-the-wordpress-timthumb-php-hack/)) has left scores of unsuspecting bloggers hacked. It's the perfect combination of not so easy to fix for the technically disinclined, and easy to find and exploit for the malicious - resulting in a disastrous number of compromised sites.
|
13 |
|
14 |
-
The Timthumb Vulnerability Scanner plugin will scan your entire wp-content directory for instances of any outdated and insecure version of the timthumb script, and give you the option to automatically upgrade them with a single click. Doing so will protect you
|
|
|
|
|
15 |
|
16 |
More info at [CodeGarage](http://codegarage.com/blog/2011/09/wordpress-timthumb-vulnerability-scanner-plugin/).
|
17 |
|
@@ -26,7 +28,7 @@ Special thanks to [Jacob Gillespie](http://jacobwg.com/) for help with the bulk
|
|
26 |
|
27 |
= What does this look for specifically? =
|
28 |
|
29 |
-
The scanner checks for instances of timthumb that
|
30 |
|
31 |
= Where does it look for them? =
|
32 |
|
@@ -34,15 +36,23 @@ The entire wp-content directory (even if it's not called wp-content) is scanned,
|
|
34 |
|
35 |
= I think I've already been hacked - will this clean it up? =
|
36 |
|
37 |
-
No. This plugin exists to make sure your door is locked, not drag the burglers out of your house.
|
|
|
|
|
38 |
|
39 |
|
40 |
== Screenshots ==
|
41 |
|
42 |
-
1. After clicking "Scan!", you'll be presented with a list of
|
43 |
|
44 |
== Changelog ==
|
45 |
|
|
|
|
|
|
|
|
|
|
|
|
|
46 |
= 1.3 =
|
47 |
* Updated formatting to conform with WP coding standards, added bulk upgrade feature (Thanks to [Jacob Gillespie](http://jacobwg.com/)!).
|
48 |
|
11 |
|
12 |
The recent Timthumb.php vulnerability (discussed [here](http://markmaunder.com/2011/08/02/technical-details-and-scripts-of-the-wordpress-timthumb-php-hack/)) has left scores of unsuspecting bloggers hacked. It's the perfect combination of not so easy to fix for the technically disinclined, and easy to find and exploit for the malicious - resulting in a disastrous number of compromised sites.
|
13 |
|
14 |
+
The Timthumb Vulnerability Scanner plugin will scan your entire wp-content directory for instances of any outdated and insecure version of the timthumb script, and give you the option to automatically upgrade them with a single click. Doing so will protect you from hackers looking to exploit this particular vulnerability.
|
15 |
+
|
16 |
+
After new, lesser vulnerabilities were found, it became apparent that the plugin needs to be dynamic - able to keep you up to date with the latest version of timthumb, without requiring a plugin upgrade. The plugin now checks for the latest available version of timthumb routinely (each time you visit the scanner page, but no more than once a day), and can download and install the latest version, rather than the one included with the plugin.
|
17 |
|
18 |
More info at [CodeGarage](http://codegarage.com/blog/2011/09/wordpress-timthumb-vulnerability-scanner-plugin/).
|
19 |
|
28 |
|
29 |
= What does this look for specifically? =
|
30 |
|
31 |
+
The scanner checks for all instances of timthumb it can find. It doesn't just check filename - it looks for code inside the file, ensuring that regardless of what a theme or plugin developer has named the file, it will be caught.
|
32 |
|
33 |
= Where does it look for them? =
|
34 |
|
36 |
|
37 |
= I think I've already been hacked - will this clean it up? =
|
38 |
|
39 |
+
No. This plugin exists to make sure your door is locked, not drag the burglers out of your house. It will run some cursory checks to see if a hacker has likely already hit your site, but has no functionality to clean up the problem.
|
40 |
+
|
41 |
+
If you've already been hacked, all is not lost - there are people out there who will clean up your site for a fee. Get in touch here: http://codegarage.com/hack-cleanup
|
42 |
|
43 |
|
44 |
== Screenshots ==
|
45 |
|
46 |
+
1. After clicking "Scan!", you'll be presented with a list of all instances of timthumb on your server. Outdated or Unsafe instances are marked as such. Clicking "Upgrade Selected Files" will update selected files to the latest available version of timthumb available on http://code.google.com/p/timthumb/.
|
47 |
|
48 |
== Changelog ==
|
49 |
|
50 |
+
= 1.4 =
|
51 |
+
* Largely rewrote codebase to clean up code.
|
52 |
+
* Added functionality to download latest version of timthumb rather than relying on static version included in plugin.
|
53 |
+
* Added functionality to check if there is a newer version of timthumb available.
|
54 |
+
* Added scan to find obvious evidence of intrusion using timthumb exploit.
|
55 |
+
|
56 |
= 1.3 =
|
57 |
* Updated formatting to conform with WP coding standards, added bulk upgrade feature (Thanks to [Jacob Gillespie](http://jacobwg.com/)!).
|
58 |
|
screenshot-1.png
CHANGED
Binary file
|
timthumb-vulnerability-scanner.php
CHANGED
@@ -1,140 +1,17 @@
|
|
1 |
<?php
|
2 |
/*
|
3 |
Plugin Name: TimThumb Vulnerability Scanner
|
4 |
-
Plugin URI: http://codegarage.com/blog/2011/09/wordpress-timthumb-vulnerability-scanner-plugin/
|
5 |
-
Description:
|
6 |
-
Author: Peter Butler
|
7 |
-
Version: 1.
|
8 |
Author URI: http://codegarage.com/
|
9 |
*/
|
10 |
|
|
|
11 |
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
function cg_tvs_scanner_menu() {
|
19 |
-
add_management_page( 'Timthumb Scanner', 'Timthumb Scanner', 'manage_options', 'cg-timthumb-scanner', 'cg_timthumb_scanner_panel' );
|
20 |
-
}
|
21 |
-
|
22 |
-
function cg_timthumb_scanner_panel() {
|
23 |
-
if ( ! current_user_can( 'manage_options' ) ) {
|
24 |
-
wp_die( __( 'You do not have sufficient permissions to access this page.' ) );
|
25 |
-
}
|
26 |
-
|
27 |
-
if ( isset( $_REQUEST['cg-action'] ) ) {
|
28 |
-
switch ( $_REQUEST['cg-action'] ) {
|
29 |
-
case 'scan':
|
30 |
-
cg_tvs_scan();
|
31 |
-
break;
|
32 |
-
case 'fix':
|
33 |
-
$nonce = $_GET['_wpnonce'];
|
34 |
-
if ( wp_verify_nonce( $nonce, 'fix_timthumb_file' ) ) {
|
35 |
-
cg_tvs_fix_file( urldecode( $_GET['file'] ) );
|
36 |
-
cg_tvs_scan(); // Re-scan site
|
37 |
-
}
|
38 |
-
break;
|
39 |
-
case 'fixall':
|
40 |
-
$nonce = $_GET['_wpnonce'];
|
41 |
-
if ( wp_verify_nonce( $nonce, 'fix_all_timthumb_files' ) ) {
|
42 |
-
$vulnerable_files = get_option( 'cg_tvs_vulnerable_files' );
|
43 |
-
if ( is_array( $vulnerable_files ) && ! empty( $vulnerable_files ) ) {
|
44 |
-
foreach ( $vulnerable_files as $file ) {
|
45 |
-
cg_tvs_fix_file( $file );
|
46 |
-
}
|
47 |
-
cg_tvs_scan(); // Re-scan site
|
48 |
-
}
|
49 |
-
}
|
50 |
-
break;
|
51 |
-
}
|
52 |
-
}
|
53 |
-
|
54 |
-
$vulnerable_files = get_option( 'cg_tvs_vulnerable_files' );
|
55 |
-
if( is_array( $vulnerable_files ) && ! empty( $vulnerable_files ) ) {
|
56 |
-
$vulnerable_list_html = '<ol>';
|
57 |
-
foreach ( $vulnerable_files as $file ) {
|
58 |
-
$vulnerable_list_html .= '<li><a href="' . wp_nonce_url( 'tools.php?page=cg-timthumb-scanner&cg-action=fix&file=' . urlencode( $file ), 'fix_timthumb_file') . '" class="button-secondary">Fix</a> <span style="color:red">' . basename( $file ) . '</span> <small>(found at ' . $file . ')</small></li>';
|
59 |
-
}
|
60 |
-
$vulnerable_list_html .= '</ol>';
|
61 |
-
} else {
|
62 |
-
$vulnerable_list_html = '<span style="color:forestgreen">No Vulnerabilities Found!</span>';
|
63 |
-
}
|
64 |
-
|
65 |
-
$safe_files = get_option( 'cg_tvs_safe_files' );
|
66 |
-
if(is_array($safe_files) && !empty($safe_files)) {
|
67 |
-
$safe_list_html = '<ol>';
|
68 |
-
foreach($safe_files as $file) {
|
69 |
-
$safe_list_html .= "<li><span style='color:forestgreen'>" . basename( $file ) . "</span> <small>(found at $file)</small></li>\n";
|
70 |
-
}
|
71 |
-
$safe_list_html .= '</ol>';
|
72 |
-
} else {
|
73 |
-
$safe_list_html = '<span style="color:forestgreen">No Up to Date Versions Found!</span>';
|
74 |
-
}
|
75 |
-
include_once 'cg-tvs-admin-panel.php';
|
76 |
-
}
|
77 |
-
|
78 |
-
// ==============
|
79 |
-
// = SCAN FILES =
|
80 |
-
// ==============
|
81 |
-
|
82 |
-
function cg_tvs_scan() {
|
83 |
-
require_once 'cg-tvs-filescanner.php';
|
84 |
-
$scanner = new CG_FileScanner( WP_CONTENT_DIR );
|
85 |
-
$scanner->generate_inventory();
|
86 |
-
$scanner->scan_inventory();
|
87 |
-
update_option( 'cg_tvs_last_checked', date('Y-m-d H:i:s') );
|
88 |
-
update_option( 'cg_tvs_vulnerable_files', $scanner->VulnerableFiles );
|
89 |
-
update_option( 'cg_tvs_safe_files', $scanner->SafeFiles );
|
90 |
-
cg_tsv_show_message('Scan completed.');
|
91 |
-
}
|
92 |
-
|
93 |
-
// ============
|
94 |
-
// = FIX FILE =
|
95 |
-
// ============
|
96 |
-
|
97 |
-
function cg_tvs_fix_file($file, $backup = false ) {
|
98 |
-
$src_file_path = trailingslashit( dirname( __FILE__ ) ) . 'cg-tvs-timthumb-latest.txt';
|
99 |
-
if ( FALSE !== $fr = @fopen( $src_file_path, 'r' ) ) {
|
100 |
-
$latest_src = fread( $fr, filesize( $src_file_path ) );
|
101 |
-
fclose($fr);
|
102 |
-
} else {
|
103 |
-
cg_tsv_show_message( 'CAN\'T READ TIMTHUMB SOURCE FILE', true );
|
104 |
-
return;
|
105 |
-
}
|
106 |
-
if( FALSE !== $fw = @fopen( $file, 'w' ) ) {
|
107 |
-
if ( fwrite( $fw, $latest_src ) ) {
|
108 |
-
cg_tsv_show_message( 'File <strong>' . basename( $file ) . '</strong> at <em>' . $file . '</em> successfully upgraded.' );
|
109 |
-
} else {
|
110 |
-
cg_tsv_show_message( 'Unknown file write error.', true );
|
111 |
-
}
|
112 |
-
} else {
|
113 |
-
cg_tsv_show_message( 'CAN\'T OPEN VULNERABLE FILE FOR WRITING', true );
|
114 |
-
return;
|
115 |
-
}
|
116 |
-
}
|
117 |
-
|
118 |
-
function cg_tsv_show_message( $message, $error = false )
|
119 |
-
{
|
120 |
-
if ($error) {
|
121 |
-
echo '<div id="message" class="error">';
|
122 |
-
}
|
123 |
-
else {
|
124 |
-
echo '<div id="message" class="updated fade">';
|
125 |
-
}
|
126 |
-
|
127 |
-
echo "<p><strong>$message</strong></p></div>";
|
128 |
-
}
|
129 |
-
|
130 |
-
// ================
|
131 |
-
// = DEACTIVATION =
|
132 |
-
// ================
|
133 |
-
|
134 |
-
register_deactivation_hook( __FILE__, 'cg_tvs_scan_deactivate' );
|
135 |
-
|
136 |
-
function cg_tvs_scan_deactivate() {
|
137 |
-
delete_option( 'cg_tvs_last_checked' );
|
138 |
-
delete_option( 'cg_tvs_vulnerable_files' );
|
139 |
-
delete_option( 'cg_tvs_safe_files' );
|
140 |
-
}
|
1 |
<?php
|
2 |
/*
|
3 |
Plugin Name: TimThumb Vulnerability Scanner
|
4 |
+
Plugin URI: http://codegarage.com/blog/2011/09/wordpress-timthumb-vulnerability-scanner-plugin-1.4/
|
5 |
+
Description: Keep your instances of Timthumb up to date and free from vulnerabilities simply. Bonus - checks for obvious signs of compromised sites.
|
6 |
+
Author: Peter Butler
|
7 |
+
Version: 1.4
|
8 |
Author URI: http://codegarage.com/
|
9 |
*/
|
10 |
|
11 |
+
include_once 'class-cg-tvs-plugin.php';
|
12 |
|
13 |
+
$CG_TVS_Plugin = new CG_TVS_Plugin();
|
14 |
+
$CG_TVS_Plugin->get_fresh_data();
|
15 |
+
add_action( 'admin_menu', array($CG_TVS_Plugin, 'add_menus' ) );
|
16 |
+
register_activation_hook( __FILE__, array($CG_TVS_Plugin, 'activate' ) );
|
17 |
+
register_deactivation_hook( __FILE__, array($CG_TVS_Plugin, 'deactivate' ) );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|