Version Description
- Added a daily automatic scan
- Added alerts across the admin section when vulnerable or outdated files are found
- Fixed issue with updating timthumb src file
Download this release
Release Info
Developer | peterebutler |
Plugin | Timthumb Vulnerability Scanner |
Version | 1.5 |
Comparing to | |
See all releases |
Code changes from version 1.43 to 1.5
- cg-tvs-admin-panel-display.php +38 -4
- cg-tvs-timthumb-latest.txt +62 -43
- class-cg-tvs-plugin.php +54 -6
- readme.txt +8 -3
- timthumb-vulnerability-scanner.php +10 -1
cg-tvs-admin-panel-display.php
CHANGED
@@ -1,7 +1,38 @@
|
|
1 |
<div class="wrap">
|
2 |
<h2>Timthumb Scanner</h2>
|
3 |
-
|
4 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5 |
<h3 class="hndle">1. Scan</h3>
|
6 |
<form action="" method="post">
|
7 |
<input type="hidden" name="cg-tvs-action" value="scan">
|
@@ -79,6 +110,11 @@
|
|
79 |
<?php endif; ?>
|
80 |
|
81 |
</div>
|
|
|
|
|
|
|
|
|
|
|
82 |
<div style="float:right;width:33%;">
|
83 |
<div class="postbox metabox-holder" style="padding-top:0px">
|
84 |
<h3 class="hndle" style="text-align:center"><a href="http://codegarage.com/"><img src="<?php echo WP_PLUGIN_URL; ?>/<?php echo basename( dirname( __FILE__ ) ); ?>/locker_logo.png"></a></h3>
|
@@ -101,8 +137,6 @@
|
|
101 |
font-size:14px;
|
102 |
width:90%;
|
103 |
margin-bottom:10px; }
|
104 |
-
/* Add your own MailChimp form style overrides in your site stylesheet or in this style block.
|
105 |
-
We recommend moving this block and the preceding CSS link to the HEAD of your HTML file. */
|
106 |
</style>
|
107 |
<div id="mc_embed_signup">
|
108 |
<form action="http://codegarage.us1.list-manage1.com/subscribe/post?u=18eaf7659266bae84144eef88&id=0029c09237" method="post" id="mc-embedded-subscribe-form" name="mc-embedded-subscribe-form" class="validate" target="_blank">
|
1 |
<div class="wrap">
|
2 |
<h2>Timthumb Scanner</h2>
|
3 |
+
<ul class="subsubsub">
|
4 |
+
<li><a href="tools.php?page=cg-timthumb-scanner" <?php if($_GET['tab'] != 'options'): ?>class="current"<?php endif; ?>>Scan for Issues</a> | </li>
|
5 |
+
<li><a href="tools.php?page=cg-timthumb-scanner&tab=options" <?php if($_GET['tab'] == 'options'): ?>class="current"<?php endif; ?>>Options</a></li>
|
6 |
+
</ul>
|
7 |
+
<?php
|
8 |
+
switch($_GET['tab']){
|
9 |
+
case 'options':
|
10 |
+
?>
|
11 |
+
<div style="width:65%;min-width:500px;float:left;clear:both;">
|
12 |
+
<div class="postbox metabox-holder">
|
13 |
+
<h3>Options</h3>
|
14 |
+
<form action="" method="post">
|
15 |
+
<input type="hidden" name="cg-tvs-action" value="update-options">
|
16 |
+
<?php wp_nonce_field( 'update_tvs_options'); ?>
|
17 |
+
<table class="form-table">
|
18 |
+
<tr>
|
19 |
+
<th><label for="scan-daily">Automatically run this scan daily</label></th>
|
20 |
+
<td><input id="scan-daily" name="scan-daily" type="checkbox" <?php if($this->scan_daily):?> checked="checked"<?php endif; ?>></td>
|
21 |
+
</tr>
|
22 |
+
<tr>
|
23 |
+
<th><input type="submit" class="button-primary"></th>
|
24 |
+
</tr>
|
25 |
+
</table>
|
26 |
+
</form>
|
27 |
+
</div>
|
28 |
+
</div>
|
29 |
+
<?php
|
30 |
+
break;
|
31 |
+
case 'scan':
|
32 |
+
default:
|
33 |
+
?>
|
34 |
+
<div style="width:65%;min-width:500px;float:left;clear:both;">
|
35 |
+
<div class="postbox metabox-holder">
|
36 |
<h3 class="hndle">1. Scan</h3>
|
37 |
<form action="" method="post">
|
38 |
<input type="hidden" name="cg-tvs-action" value="scan">
|
110 |
<?php endif; ?>
|
111 |
|
112 |
</div>
|
113 |
+
<?php
|
114 |
+
break;
|
115 |
+
} ?>
|
116 |
+
|
117 |
+
|
118 |
<div style="float:right;width:33%;">
|
119 |
<div class="postbox metabox-holder" style="padding-top:0px">
|
120 |
<h3 class="hndle" style="text-align:center"><a href="http://codegarage.com/"><img src="<?php echo WP_PLUGIN_URL; ?>/<?php echo basename( dirname( __FILE__ ) ); ?>/locker_logo.png"></a></h3>
|
137 |
font-size:14px;
|
138 |
width:90%;
|
139 |
margin-bottom:10px; }
|
|
|
|
|
140 |
</style>
|
141 |
<div id="mc_embed_signup">
|
142 |
<form action="http://codegarage.us1.list-manage1.com/subscribe/post?u=18eaf7659266bae84144eef88&id=0029c09237" method="post" id="mc-embedded-subscribe-form" name="mc-embedded-subscribe-form" class="validate" target="_blank">
|
cg-tvs-timthumb-latest.txt
CHANGED
@@ -9,45 +9,54 @@
|
|
9 |
*
|
10 |
* Examples and documentation available on the project homepage
|
11 |
* http://www.binarymoon.co.uk/projects/timthumb/
|
|
|
|
|
12 |
*/
|
13 |
|
14 |
/*
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
a new version of timthumb.
|
21 |
-
|
22 |
*/
|
23 |
-
define ('VERSION', '2.8.
|
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') )
|
27 |
-
if(! defined('DEBUG_LEVEL') )
|
28 |
-
if(! defined('MEMORY_LIMIT') )
|
29 |
-
if(! defined('BLOCK_EXTERNAL_LEECHERS') ) define ('BLOCK_EXTERNAL_LEECHERS', false);
|
30 |
|
31 |
//Image fetching and caching
|
32 |
-
if(! defined('ALLOW_EXTERNAL') )
|
33 |
-
if(! defined('ALLOW_ALL_EXTERNAL_SITES') ) define ('ALLOW_ALL_EXTERNAL_SITES', false);
|
34 |
-
if(! defined('FILE_CACHE_ENABLED') ) define ('FILE_CACHE_ENABLED', TRUE);
|
35 |
if(! defined('FILE_CACHE_TIME_BETWEEN_CLEANS')) define ('FILE_CACHE_TIME_BETWEEN_CLEANS', 86400); // How often the cache is cleaned
|
36 |
-
|
37 |
-
if(! defined('
|
38 |
-
if(! defined('
|
39 |
-
if(! defined('
|
40 |
-
if(! defined('
|
41 |
-
if(! defined('
|
|
|
|
|
|
|
42 |
//Browser caching
|
43 |
-
if(! defined('BROWSER_CACHE_MAX_AGE') ) define ('BROWSER_CACHE_MAX_AGE', 864000);
|
44 |
-
if(! defined('BROWSER_CACHE_DISABLE') ) define ('BROWSER_CACHE_DISABLE', false);
|
45 |
|
46 |
//Image size and defaults
|
47 |
-
if(! defined('MAX_WIDTH') ) define ('MAX_WIDTH', 1500);
|
48 |
-
if(! defined('MAX_HEIGHT') ) define ('MAX_HEIGHT', 1500);
|
49 |
-
if(! defined('NOT_FOUND_IMAGE') ) define ('NOT_FOUND_IMAGE', '');
|
50 |
-
if(! defined('ERROR_IMAGE') ) define ('ERROR_IMAGE', '');
|
|
|
|
|
|
|
|
|
|
|
|
|
51 |
|
52 |
//Image compression is enabled if either of these point to valid paths
|
53 |
|
@@ -115,6 +124,7 @@ if(! defined('WEBSHOT_XVFB_RUNNING') ) define ('WEBSHOT_XVFB_RUNNING', false);
|
|
115 |
if(! isset($ALLOWED_SITES)){
|
116 |
$ALLOWED_SITES = array (
|
117 |
'flickr.com',
|
|
|
118 |
'picasa.com',
|
119 |
'img.youtube.com',
|
120 |
'upload.wikimedia.org',
|
@@ -187,7 +197,7 @@ class timthumb {
|
|
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();
|
@@ -246,9 +256,11 @@ class timthumb {
|
|
246 |
}
|
247 |
}
|
248 |
|
249 |
-
$cachePrefix = ($this->isURL ? '
|
250 |
if($this->isURL){
|
251 |
-
$
|
|
|
|
|
252 |
} else {
|
253 |
$this->localImage = $this->getLocalImagePath($this->src);
|
254 |
if(! $this->localImage){
|
@@ -260,7 +272,7 @@ class timthumb {
|
|
260 |
$this->debug(1, "Local image path is {$this->localImage}");
|
261 |
$this->localImageMTime = @filemtime($this->localImage);
|
262 |
//We include the mtime of the local file in case in changes on disk.
|
263 |
-
$this->cachefile = $this->cacheDirectory . '/' . $cachePrefix . md5($this->salt . $this->localImageMTime . $_SERVER ['QUERY_STRING'] . $this->fileCacheVersion) . FILE_CACHE_SUFFIX;
|
264 |
}
|
265 |
$this->debug(2, "Cache file is: " . $this->cachefile);
|
266 |
|
@@ -438,6 +450,9 @@ class timthumb {
|
|
438 |
}
|
439 |
}
|
440 |
protected function cleanCache(){
|
|
|
|
|
|
|
441 |
$this->debug(3, "cleanCache() called");
|
442 |
$lastCleanFile = $this->cacheDirectory . '/timthumb_cacheLastCleanTime.touch';
|
443 |
|
@@ -499,15 +514,15 @@ class timthumb {
|
|
499 |
);
|
500 |
}
|
501 |
|
502 |
-
// get standard input properties
|
503 |
$new_width = (int) abs ($this->param('w', 0));
|
504 |
$new_height = (int) abs ($this->param('h', 0));
|
505 |
-
$zoom_crop = (int) $this->param('zc',
|
506 |
-
$quality = (int) abs ($this->param('q',
|
507 |
$align = $this->cropTop ? 't' : $this->param('a', 'c');
|
508 |
-
$filters = $this->param('f',
|
509 |
-
$sharpen = (bool) $this->param('s',
|
510 |
-
$canvas_color = $this->param('cc',
|
511 |
|
512 |
// set default width and height if neither are set already
|
513 |
if ($new_width == 0 && $new_height == 0) {
|
@@ -797,6 +812,9 @@ class timthumb {
|
|
797 |
}
|
798 |
protected function calcDocRoot(){
|
799 |
$docRoot = @$_SERVER['DOCUMENT_ROOT'];
|
|
|
|
|
|
|
800 |
if(!isset($docRoot)){
|
801 |
$this->debug(3, "DOCUMENT_ROOT is not set. This is probably windows. Starting search 1.");
|
802 |
if(isset($_SERVER['SCRIPT_FILENAME'])){
|
@@ -818,7 +836,6 @@ class timthumb {
|
|
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,7 +850,7 @@ class timthumb {
|
|
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, $
|
837 |
return $real;
|
838 |
} else {
|
839 |
$this->debug(1, "Security block: The file specified occurs outside the document root.");
|
@@ -845,7 +862,7 @@ class timthumb {
|
|
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, $
|
849 |
return $absolute;
|
850 |
} else {
|
851 |
$this->debug(1, "Security block: The file specified occurs outside the document root.");
|
@@ -868,7 +885,7 @@ class timthumb {
|
|
868 |
if(file_exists($base . $src)){
|
869 |
$this->debug(3, "Found file as: " . $base . $src);
|
870 |
$real = realpath($base . $src);
|
871 |
-
if(stripos($real, $
|
872 |
return $real;
|
873 |
} else {
|
874 |
$this->debug(1, "Security block: The file specified occurs outside the document root.");
|
@@ -1043,7 +1060,6 @@ class timthumb {
|
|
1043 |
}
|
1044 |
protected function openImage($mimeType, $src){
|
1045 |
switch ($mimeType) {
|
1046 |
-
case 'image/jpg': //This isn't a valid mime type so we should probably remove it
|
1047 |
case 'image/jpeg':
|
1048 |
$image = imagecreatefromjpeg ($src);
|
1049 |
break;
|
@@ -1055,6 +1071,9 @@ class timthumb {
|
|
1055 |
case 'image/gif':
|
1056 |
$image = imagecreatefromgif ($src);
|
1057 |
break;
|
|
|
|
|
|
|
1058 |
}
|
1059 |
|
1060 |
return $image;
|
@@ -1201,4 +1220,4 @@ class timthumb {
|
|
1201 |
protected function is404(){
|
1202 |
return $this->is404;
|
1203 |
}
|
1204 |
-
}
|
9 |
*
|
10 |
* Examples and documentation available on the project homepage
|
11 |
* http://www.binarymoon.co.uk/projects/timthumb/
|
12 |
+
*
|
13 |
+
* $Rev$
|
14 |
*/
|
15 |
|
16 |
/*
|
17 |
+
* --- TimThumb CONFIGURATION ---
|
18 |
+
* To edit the configs it is best to create a file called timthumb-config.php
|
19 |
+
* and define variables you want to customize in there. It will automatically be
|
20 |
+
* loaded by timthumb. This will save you having to re-edit these variables
|
21 |
+
* everytime you download a new version
|
|
|
|
|
22 |
*/
|
23 |
+
define ('VERSION', '2.8.5'); // 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.
|
30 |
|
31 |
//Image fetching and caching
|
32 |
+
if(! defined('ALLOW_EXTERNAL') ) define ('ALLOW_EXTERNAL', TRUE); // Allow image fetching from external websites. Will check against ALLOWED_SITES if ALLOW_ALL_EXTERNAL_SITES is false
|
33 |
+
if(! defined('ALLOW_ALL_EXTERNAL_SITES') ) define ('ALLOW_ALL_EXTERNAL_SITES', false); // Less secure.
|
34 |
+
if(! defined('FILE_CACHE_ENABLED') ) define ('FILE_CACHE_ENABLED', TRUE); // Should we store resized/modified images on disk to speed things up?
|
35 |
if(! defined('FILE_CACHE_TIME_BETWEEN_CLEANS')) define ('FILE_CACHE_TIME_BETWEEN_CLEANS', 86400); // How often the cache is cleaned
|
36 |
+
|
37 |
+
if(! defined('FILE_CACHE_MAX_FILE_AGE') ) define ('FILE_CACHE_MAX_FILE_AGE', 86400); // How old does a file have to be to be deleted from the cache
|
38 |
+
if(! defined('FILE_CACHE_SUFFIX') ) define ('FILE_CACHE_SUFFIX', '.timthumb.txt'); // What to put at the end of all files in the cache directory so we can identify them
|
39 |
+
if(! defined('FILE_CACHE_PREFIX') ) define ('FILE_CACHE_PREFIX', 'timthumb'); // What to put at the end of all files in the cache directory so we can identify them
|
40 |
+
if(! defined('FILE_CACHE_DIRECTORY') ) define ('FILE_CACHE_DIRECTORY', './cache'); // Directory where images are cached. Left blank it will use the system temporary directory (which is better for security)
|
41 |
+
if(! defined('MAX_FILE_SIZE') ) define ('MAX_FILE_SIZE', 10485760); // 10 Megs is 10485760. This is the max internal or external file size that we'll process.
|
42 |
+
if(! defined('CURL_TIMEOUT') ) define ('CURL_TIMEOUT', 20); // Timeout duration for Curl. This only applies if you have Curl installed and aren't using PHP's default URL fetching mechanism.
|
43 |
+
if(! defined('WAIT_BETWEEN_FETCH_ERRORS') ) define ('WAIT_BETWEEN_FETCH_ERRORS', 3600); //Time to wait between errors fetching remote file
|
44 |
+
|
45 |
//Browser caching
|
46 |
+
if(! defined('BROWSER_CACHE_MAX_AGE') ) define ('BROWSER_CACHE_MAX_AGE', 864000); // Time to cache in the browser
|
47 |
+
if(! defined('BROWSER_CACHE_DISABLE') ) define ('BROWSER_CACHE_DISABLE', false); // Use for testing if you want to disable all browser caching
|
48 |
|
49 |
//Image size and defaults
|
50 |
+
if(! defined('MAX_WIDTH') ) define ('MAX_WIDTH', 1500); // Maximum image width
|
51 |
+
if(! defined('MAX_HEIGHT') ) define ('MAX_HEIGHT', 1500); // Maximum image height
|
52 |
+
if(! defined('NOT_FOUND_IMAGE') ) define ('NOT_FOUND_IMAGE', ''); // Image to serve if any 404 occurs
|
53 |
+
if(! defined('ERROR_IMAGE') ) define ('ERROR_IMAGE', ''); // Image to serve if an error occurs instead of showing error message
|
54 |
+
if(! defined('DEFAULT_Q') ) define ('DEFAULT_Q', 90); // Default image quality. Allows overrid in timthumb-config.php
|
55 |
+
if(! defined('DEFAULT_ZC') ) define ('DEFAULT_ZC', 1); // Default zoom/crop setting. Allows overrid in timthumb-config.php
|
56 |
+
if(! defined('DEFAULT_F') ) define ('DEFAULT_F', ''); // Default image filters. Allows overrid in timthumb-config.php
|
57 |
+
if(! defined('DEFAULT_S') ) define ('DEFAULT_S', 0); // Default sharpen value. Allows overrid in timthumb-config.php
|
58 |
+
if(! defined('DEFAULT_CC') ) define ('DEFAULT_CC', 'ffffff'); // Default canvas colour. Allows overrid in timthumb-config.php
|
59 |
+
|
60 |
|
61 |
//Image compression is enabled if either of these point to valid paths
|
62 |
|
124 |
if(! isset($ALLOWED_SITES)){
|
125 |
$ALLOWED_SITES = array (
|
126 |
'flickr.com',
|
127 |
+
'staticflickr.com',
|
128 |
'picasa.com',
|
129 |
'img.youtube.com',
|
130 |
'upload.wikimedia.org',
|
197 |
}
|
198 |
$this->cacheDirectory = FILE_CACHE_DIRECTORY;
|
199 |
if (!touch($this->cacheDirectory . '/index.html')) {
|
200 |
+
$this->error("Could note create the index.html file - to fix this create an empty file named index.html file in the cache directory.");
|
201 |
}
|
202 |
} else {
|
203 |
$this->cacheDirectory = sys_get_temp_dir();
|
256 |
}
|
257 |
}
|
258 |
|
259 |
+
$cachePrefix = ($this->isURL ? '_ext_' : '_int_');
|
260 |
if($this->isURL){
|
261 |
+
$arr = explode('&', $_SERVER ['QUERY_STRING']);
|
262 |
+
asort($arr);
|
263 |
+
$this->cachefile = $this->cacheDirectory . '/' . FILE_CACHE_PREFIX . $cachePrefix . md5($this->salt . implode('', $arr) . $this->fileCacheVersion) . FILE_CACHE_SUFFIX;
|
264 |
} else {
|
265 |
$this->localImage = $this->getLocalImagePath($this->src);
|
266 |
if(! $this->localImage){
|
272 |
$this->debug(1, "Local image path is {$this->localImage}");
|
273 |
$this->localImageMTime = @filemtime($this->localImage);
|
274 |
//We include the mtime of the local file in case in changes on disk.
|
275 |
+
$this->cachefile = $this->cacheDirectory . '/' . FILE_CACHE_PREFIX . $cachePrefix . md5($this->salt . $this->localImageMTime . $_SERVER ['QUERY_STRING'] . $this->fileCacheVersion) . FILE_CACHE_SUFFIX;
|
276 |
}
|
277 |
$this->debug(2, "Cache file is: " . $this->cachefile);
|
278 |
|
450 |
}
|
451 |
}
|
452 |
protected function cleanCache(){
|
453 |
+
if (FILE_CACHE_TIME_BETWEEN_CLEANS < 0) {
|
454 |
+
return;
|
455 |
+
}
|
456 |
$this->debug(3, "cleanCache() called");
|
457 |
$lastCleanFile = $this->cacheDirectory . '/timthumb_cacheLastCleanTime.touch';
|
458 |
|
514 |
);
|
515 |
}
|
516 |
|
517 |
+
// get standard input properties
|
518 |
$new_width = (int) abs ($this->param('w', 0));
|
519 |
$new_height = (int) abs ($this->param('h', 0));
|
520 |
+
$zoom_crop = (int) $this->param('zc', DEFAULT_ZC);
|
521 |
+
$quality = (int) abs ($this->param('q', DEFAULT_Q));
|
522 |
$align = $this->cropTop ? 't' : $this->param('a', 'c');
|
523 |
+
$filters = $this->param('f', DEFAULT_F);
|
524 |
+
$sharpen = (bool) $this->param('s', DEFAULT_S);
|
525 |
+
$canvas_color = $this->param('cc', DEFAULT_CC);
|
526 |
|
527 |
// set default width and height if neither are set already
|
528 |
if ($new_width == 0 && $new_height == 0) {
|
812 |
}
|
813 |
protected function calcDocRoot(){
|
814 |
$docRoot = @$_SERVER['DOCUMENT_ROOT'];
|
815 |
+
if (defined('LOCAL_FILE_BASE_DIRECTORY')) {
|
816 |
+
$docRoot = LOCAL_FILE_BASE_DIRECTORY;
|
817 |
+
}
|
818 |
if(!isset($docRoot)){
|
819 |
$this->debug(3, "DOCUMENT_ROOT is not set. This is probably windows. Starting search 1.");
|
820 |
if(isset($_SERVER['SCRIPT_FILENAME'])){
|
836 |
}
|
837 |
protected function getLocalImagePath($src){
|
838 |
$src = preg_replace('/^\//', '', $src); //strip off the leading '/'
|
|
|
839 |
if(! $this->docRoot){
|
840 |
$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.");
|
841 |
//We don't support serving images outside the current dir if we don't have a doc root for security reasons.
|
850 |
if(file_exists ($this->docRoot . '/' . $src)) {
|
851 |
$this->debug(3, "Found file as " . $this->docRoot . '/' . $src);
|
852 |
$real = realpath($this->docRoot . '/' . $src);
|
853 |
+
if(stripos($real, $this->docRoot) == 0){
|
854 |
return $real;
|
855 |
} else {
|
856 |
$this->debug(1, "Security block: The file specified occurs outside the document root.");
|
862 |
if($absolute && file_exists($absolute)){ //realpath does file_exists check, so can probably skip the exists check here
|
863 |
$this->debug(3, "Found absolute path: $absolute");
|
864 |
if(! $this->docRoot){ $this->sanityFail("docRoot not set when checking absolute path."); }
|
865 |
+
if(stripos($absolute, $this->docRoot) == 0){
|
866 |
return $absolute;
|
867 |
} else {
|
868 |
$this->debug(1, "Security block: The file specified occurs outside the document root.");
|
885 |
if(file_exists($base . $src)){
|
886 |
$this->debug(3, "Found file as: " . $base . $src);
|
887 |
$real = realpath($base . $src);
|
888 |
+
if(stripos($real, $this->docRoot) == 0){
|
889 |
return $real;
|
890 |
} else {
|
891 |
$this->debug(1, "Security block: The file specified occurs outside the document root.");
|
1060 |
}
|
1061 |
protected function openImage($mimeType, $src){
|
1062 |
switch ($mimeType) {
|
|
|
1063 |
case 'image/jpeg':
|
1064 |
$image = imagecreatefromjpeg ($src);
|
1065 |
break;
|
1071 |
case 'image/gif':
|
1072 |
$image = imagecreatefromgif ($src);
|
1073 |
break;
|
1074 |
+
|
1075 |
+
default:
|
1076 |
+
$this->error("Unrecognised mimeType");
|
1077 |
}
|
1078 |
|
1079 |
return $image;
|
1220 |
protected function is404(){
|
1221 |
return $this->is404;
|
1222 |
}
|
1223 |
+
}
|
class-cg-tvs-plugin.php
CHANGED
@@ -5,6 +5,7 @@ class CG_TVS_Plugin{
|
|
5 |
var $script_latest_version;
|
6 |
var $script_safe_version;
|
7 |
var $last_version_check;
|
|
|
8 |
|
9 |
var $last_scan;
|
10 |
var $script_instances;
|
@@ -13,8 +14,13 @@ class CG_TVS_Plugin{
|
|
13 |
var $plugin_base;
|
14 |
|
15 |
var $current_timthumb_src_version;
|
|
|
16 |
|
17 |
function init(){
|
|
|
|
|
|
|
|
|
18 |
$storage_array = get_option( 'cg_tvs_data' );
|
19 |
if(is_array($storage_array)){
|
20 |
$this->script_latest_version = $storage_array['script_latest_version'];
|
@@ -24,9 +30,12 @@ class CG_TVS_Plugin{
|
|
24 |
$this->script_instances = $storage_array['script_instances'];
|
25 |
$this->suspicious_files = $storage_array['suspicious_files'];
|
26 |
$this->last_scan = $storage_array['last_scan'];
|
|
|
|
|
|
|
27 |
|
28 |
}else{
|
29 |
-
$this->script_latest_version = '2.8.
|
30 |
$this->script_safe_version = '2.8.2';
|
31 |
|
32 |
$this->last_version_check = 0;
|
@@ -34,6 +43,11 @@ class CG_TVS_Plugin{
|
|
34 |
$this->script_instances = array();
|
35 |
$this->suspicious_files = array();
|
36 |
$this->last_scan = 0;
|
|
|
|
|
|
|
|
|
|
|
37 |
$this->save();
|
38 |
}
|
39 |
if($this->last_version_check < time()-86400){
|
@@ -41,8 +55,12 @@ class CG_TVS_Plugin{
|
|
41 |
$this->save();
|
42 |
}
|
43 |
$this->plugin_base_dir = trailingslashit(dirname(__FILE__));
|
44 |
-
|
45 |
-
|
|
|
|
|
|
|
|
|
46 |
}
|
47 |
}
|
48 |
|
@@ -53,12 +71,14 @@ class CG_TVS_Plugin{
|
|
53 |
|
54 |
function activate(){
|
55 |
$this->init();
|
|
|
56 |
delete_option( 'cg_tvs_last_checked' );
|
57 |
delete_option( 'cg_tvs_vulnerable_files' );
|
58 |
delete_option( 'cg_tvs_safe_files' );
|
59 |
}
|
60 |
|
61 |
function deactivate(){
|
|
|
62 |
delete_option( 'cg_tvs_data' );
|
63 |
}
|
64 |
|
@@ -89,6 +109,12 @@ class CG_TVS_Plugin{
|
|
89 |
$this->last_scan = time();
|
90 |
$this->script_instances = $scanner->instances;
|
91 |
$this->suspicious_files = $scanner->suspicious_files;
|
|
|
|
|
|
|
|
|
|
|
|
|
92 |
$this->show_message('Scan completed.');
|
93 |
$this->save();
|
94 |
}
|
@@ -202,13 +228,18 @@ class CG_TVS_Plugin{
|
|
202 |
$storage_array['script_instances'] = $this->script_instances;
|
203 |
$storage_array['suspicious_files'] = $this->suspicious_files;
|
204 |
$storage_array['last_scan'] = $this->last_scan;
|
|
|
205 |
|
|
|
206 |
update_option( 'cg_tvs_data', $storage_array );
|
207 |
|
208 |
}
|
209 |
|
210 |
function show_message( $message, $error = false )
|
211 |
{
|
|
|
|
|
|
|
212 |
if ($error) {
|
213 |
echo '<div id="message" class="error">';
|
214 |
}
|
@@ -223,8 +254,11 @@ class CG_TVS_Plugin{
|
|
223 |
if ( ! current_user_can( 'manage_options' ) ) {
|
224 |
wp_die( __( 'You do not have sufficient permissions to access this page.' ) );
|
225 |
}
|
226 |
-
|
227 |
-
|
|
|
|
|
|
|
228 |
if ( isset( $_REQUEST['cg-tvs-action'] ) ) {
|
229 |
switch ( $_REQUEST['cg-tvs-action'] ) {
|
230 |
case 'scan':
|
@@ -232,7 +266,7 @@ class CG_TVS_Plugin{
|
|
232 |
break;
|
233 |
case 'fix':
|
234 |
$this->get_timthumb_src_version();
|
235 |
-
if($this->get_version_float($this->current_timthumb_src_version) < $this->script_latest_version){
|
236 |
$this->download_new_timthumb_src();
|
237 |
}
|
238 |
if ( wp_verify_nonce( $_POST['_wpnonce'], 'fix_timthumb_files' ) ) {
|
@@ -256,6 +290,20 @@ class CG_TVS_Plugin{
|
|
256 |
}
|
257 |
}
|
258 |
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
259 |
}
|
260 |
}
|
261 |
|
5 |
var $script_latest_version;
|
6 |
var $script_safe_version;
|
7 |
var $last_version_check;
|
8 |
+
var $scan_daily;
|
9 |
|
10 |
var $last_scan;
|
11 |
var $script_instances;
|
14 |
var $plugin_base;
|
15 |
|
16 |
var $current_timthumb_src_version;
|
17 |
+
var $on_admin_page = false;
|
18 |
|
19 |
function init(){
|
20 |
+
global $pagenow;
|
21 |
+
if($pagenow == 'tools.php' && $_GET['page'] == 'cg-timthumb-scanner'){
|
22 |
+
$this->on_admin_page = true;
|
23 |
+
}
|
24 |
$storage_array = get_option( 'cg_tvs_data' );
|
25 |
if(is_array($storage_array)){
|
26 |
$this->script_latest_version = $storage_array['script_latest_version'];
|
30 |
$this->script_instances = $storage_array['script_instances'];
|
31 |
$this->suspicious_files = $storage_array['suspicious_files'];
|
32 |
$this->last_scan = $storage_array['last_scan'];
|
33 |
+
$this->scan_daily = $storage_array['scan_daily'];
|
34 |
+
|
35 |
+
$this->scan_summary = $storage_array['scan_summary'];
|
36 |
|
37 |
}else{
|
38 |
+
$this->script_latest_version = '2.8.5';
|
39 |
$this->script_safe_version = '2.8.2';
|
40 |
|
41 |
$this->last_version_check = 0;
|
43 |
$this->script_instances = array();
|
44 |
$this->suspicious_files = array();
|
45 |
$this->last_scan = 0;
|
46 |
+
$this->scan_daily = true;
|
47 |
+
$this->scan_summary['Vulnerable'] = 0;
|
48 |
+
$this->scan_summary['Outdated'] = 0;
|
49 |
+
$this->scan_summary['Up to Date'] = 0;
|
50 |
+
|
51 |
$this->save();
|
52 |
}
|
53 |
if($this->last_version_check < time()-86400){
|
55 |
$this->save();
|
56 |
}
|
57 |
$this->plugin_base_dir = trailingslashit(dirname(__FILE__));
|
58 |
+
|
59 |
+
if( $this->scan_summary['Outdated'] > 0 && !$this->on_admin_page ){
|
60 |
+
$this->show_message( $this->scan_summary['Outdated']." outdated Timthumb "._n('file', 'files', $this->scan_summary['Outdated'])." found. <a href=\"tools.php?page=cg-timthumb-scanner\">Fix "._n('it', 'them', $this->scan_summary['Outdated'])." here</a>.", $error = false );
|
61 |
+
}
|
62 |
+
if( $this->scan_summary['Vulnerable'] > 0 && !$this->on_admin_page ){
|
63 |
+
$this->show_message( $this->scan_summary['Vulnerable']." vulnerable Timthumb "._n('file', 'files', $this->scan_summary['Vulnerable'])." found. <a href=\"tools.php?page=cg-timthumb-scanner\">Fix "._n('it', 'them', $this->scan_summary['Vulnerable'])." here</a>.", $error = true );
|
64 |
}
|
65 |
}
|
66 |
|
71 |
|
72 |
function activate(){
|
73 |
$this->init();
|
74 |
+
// Clear out older version data
|
75 |
delete_option( 'cg_tvs_last_checked' );
|
76 |
delete_option( 'cg_tvs_vulnerable_files' );
|
77 |
delete_option( 'cg_tvs_safe_files' );
|
78 |
}
|
79 |
|
80 |
function deactivate(){
|
81 |
+
wp_clear_scheduled_hook('cg_tvs_daily_scan');
|
82 |
delete_option( 'cg_tvs_data' );
|
83 |
}
|
84 |
|
109 |
$this->last_scan = time();
|
110 |
$this->script_instances = $scanner->instances;
|
111 |
$this->suspicious_files = $scanner->suspicious_files;
|
112 |
+
$this->scan_summary['Vulnerable'] = 0;
|
113 |
+
$this->scan_summary['Outdated'] = 0;
|
114 |
+
$this->scan_summary['Up to Date'] = 0;
|
115 |
+
foreach($scanner->instances as $file){
|
116 |
+
$this->scan_summary[$this->get_version_status($file['version'])]++;
|
117 |
+
}
|
118 |
$this->show_message('Scan completed.');
|
119 |
$this->save();
|
120 |
}
|
228 |
$storage_array['script_instances'] = $this->script_instances;
|
229 |
$storage_array['suspicious_files'] = $this->suspicious_files;
|
230 |
$storage_array['last_scan'] = $this->last_scan;
|
231 |
+
$storage_array['scan_daily'] = $this->scan_daily;
|
232 |
|
233 |
+
$storage_array['scan_summary'] = $this->scan_summary;
|
234 |
update_option( 'cg_tvs_data', $storage_array );
|
235 |
|
236 |
}
|
237 |
|
238 |
function show_message( $message, $error = false )
|
239 |
{
|
240 |
+
if(DOING_CRON === TRUE){
|
241 |
+
return;
|
242 |
+
}
|
243 |
if ($error) {
|
244 |
echo '<div id="message" class="error">';
|
245 |
}
|
254 |
if ( ! current_user_can( 'manage_options' ) ) {
|
255 |
wp_die( __( 'You do not have sufficient permissions to access this page.' ) );
|
256 |
}
|
257 |
+
|
258 |
+
if(!is_writeable($this->plugin_base_dir)){
|
259 |
+
$this->show_message('The plugin directory (at '.$this->plugin_base_dir.') is not writeable. Because of this, we can\'t download an updated copy of timthumb to use. Try changing permissions on this directory to 755 (or in certain cases, 777)', 'error');
|
260 |
+
}
|
261 |
+
|
262 |
if ( isset( $_REQUEST['cg-tvs-action'] ) ) {
|
263 |
switch ( $_REQUEST['cg-tvs-action'] ) {
|
264 |
case 'scan':
|
266 |
break;
|
267 |
case 'fix':
|
268 |
$this->get_timthumb_src_version();
|
269 |
+
if($this->get_version_float($this->current_timthumb_src_version) < $this->get_version_float($this->script_latest_version)){
|
270 |
$this->download_new_timthumb_src();
|
271 |
}
|
272 |
if ( wp_verify_nonce( $_POST['_wpnonce'], 'fix_timthumb_files' ) ) {
|
290 |
}
|
291 |
}
|
292 |
break;
|
293 |
+
case 'update-options':
|
294 |
+
$nonce = $_POST['_wpnonce'];
|
295 |
+
if ( wp_verify_nonce( $nonce, 'update_tvs_options' ) ) {
|
296 |
+
if($_POST['scan-daily']){
|
297 |
+
$this->scan_daily = true;
|
298 |
+
if ( !wp_next_scheduled( 'cg_tvs_daily_scan' ) ) {
|
299 |
+
wp_schedule_event(time(), 'daily', 'cg_tvs_daily_scan');
|
300 |
+
}
|
301 |
+
}else{
|
302 |
+
$this->scan_daily = false;
|
303 |
+
wp_clear_scheduled_hook('cg_tvs_daily_scan');
|
304 |
+
}
|
305 |
+
}
|
306 |
+
break;
|
307 |
}
|
308 |
}
|
309 |
|
readme.txt
CHANGED
@@ -1,8 +1,8 @@
|
|
1 |
=== Timthumb Vulnerability Scanner ===
|
2 |
Contributors: peterebutler
|
3 |
-
Tags: security, scanning, timthumb, hack
|
4 |
Requires at least: 3.0
|
5 |
-
Tested up to: 3.
|
6 |
Stable tag: trunk
|
7 |
|
8 |
Scans your wp-content directory for vulnerable instances of timthumb.php, and optionally upgrades them to a safe version.
|
@@ -13,7 +13,7 @@ The recent Timthumb.php vulnerability (discussed [here](http://markmaunder.com/2
|
|
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 |
|
@@ -47,6 +47,11 @@ If you've already been hacked, all is not lost - there are people out there who
|
|
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.
|
1 |
=== Timthumb Vulnerability Scanner ===
|
2 |
Contributors: peterebutler
|
3 |
+
Tags: security, scanning, timthumb, hack, vulnerability
|
4 |
Requires at least: 3.0
|
5 |
+
Tested up to: 3.3.1
|
6 |
Stable tag: trunk
|
7 |
|
8 |
Scans your wp-content directory for vulnerable instances of timthumb.php, and optionally upgrades them to a safe version.
|
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. Scans are run daily (unless you disable them via the options link on the scanner page) via wp-cron to keep up with any new plugins or themes you've installed.
|
17 |
|
18 |
More info at [CodeGarage](http://codegarage.com/blog/2011/09/wordpress-timthumb-vulnerability-scanner-plugin/).
|
19 |
|
47 |
|
48 |
== Changelog ==
|
49 |
|
50 |
+
= 1.5 =
|
51 |
+
* Added a daily automatic scan
|
52 |
+
* Added alerts across the admin section when vulnerable or outdated files are found
|
53 |
+
* Fixed issue with updating timthumb src file
|
54 |
+
|
55 |
= 1.4 =
|
56 |
* Largely rewrote codebase to clean up code.
|
57 |
* Added functionality to download latest version of timthumb rather than relying on static version included in plugin.
|
timthumb-vulnerability-scanner.php
CHANGED
@@ -4,13 +4,22 @@ 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.
|
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 |
add_action( 'admin_menu', array($CG_TVS_Plugin, 'add_menus' ) );
|
15 |
register_activation_hook( __FILE__, array($CG_TVS_Plugin, 'activate' ) );
|
16 |
register_deactivation_hook( __FILE__, array($CG_TVS_Plugin, 'deactivate' ) );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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.5
|
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->init();
|
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' ) );
|
18 |
+
|
19 |
+
// For automatic daily scans
|
20 |
+
add_action('cg_tvs_daily_scan', 'cg_tvs_daily_scan');
|
21 |
+
|
22 |
+
function cg_tvs_daily_scan() {
|
23 |
+
global $CG_TVS_Plugin;
|
24 |
+
$CG_TVS_Plugin->scan();
|
25 |
+
}
|