Timthumb Vulnerability Scanner - Version 1.3

Version Description

  • Updated formatting to conform with WP coding standards, added bulk upgrade feature (Thanks to Jacob Gillespie!).
Download this release

Release Info

Developer peterebutler
Plugin Icon wp plugin Timthumb Vulnerability Scanner
Version 1.3
Comparing to
See all releases

Code changes from version 1.2 to 1.3

cg-tvs-admin-panel.php CHANGED
@@ -1,42 +1,43 @@
1
  <div class="wrap">
2
- <h2>Timthumb Scanner</h2>
3
- <div class="postbox metabox-holder" style="float:right;width:300px;padding-top:0px">
4
- <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>
5
- <div class="inside">
6
- <p><strong>Wish this was already done for you?</strong></p>
7
- <p><a href="http://codegarage.com" target="_blank" >Locker</a> from <a href="http://codegarage.com/" target="_blank" >Code Garage</a> provides rock solid daily backups and hack monitoring and cleanup (for malicious code and vulnerabilities like this one), as well as personal, one on one support when you need it. Plans start at $15/month for 10 sites.</p>
8
- <p style="text-align:center;padding-top:15px;"><a href="http://codegarage.com/" target="_blank" class="button-primary">Click here to learn more</a></p>
9
- </div>
10
- </div>
11
- <div style="margin-right:320px;">
12
- <h4>What's going on here?</h4>
13
- <p>Here's how this works: When you click "Scan", we'll gather a list of all the files in your wp-content directory, and then we'll scan all of the php files looking for the timthumb script. If we find it, we'll scan it to make sure it's at least version 2 - which is the version that fixed the vulnerability. You'll be notified here of any files that need to be updated.</p>
14
- <form action="tools.php?page=cg-timthumb-scanner" method="post">
15
- <input type="hidden" name="cg-action" value="scan">
16
- <button class="button-secondary">Scan!</button>
17
- </form>
18
- <?php if(!empty($message)): ?>
19
- <div id="message" class="updated">
20
- <p><?php echo $message; ?></p>
21
- </div>
22
- <?php endif; ?>
23
- <?php if(get_option('cg_tvs_last_checked')): ?>
24
- <h4>What now?</h4>
25
- <p>We've now scanned all your themes and plugins, and any instances of the timthumb script are listed below. Problem files (timthumb scripts that are older than version 2.0) are in the "Vulnerable" list, and safe files (Newer than 2.0) are listed in the "Safe" list. "Vulnerable" files can be upgraded to the latest version of timthumb by clicking the "Fix" button next to each file.</p>
26
- <table class="form-table">
27
- <tr>
28
- <th scope="row">Last Scanned:</th>
29
- <td><?php echo get_option('cg_tvs_last_checked'); ?></td>
30
- </tr>
31
- <tr>
32
- <th scope="row">Vulnerable Timthumb Files:</th>
33
- <td><?php echo $vulnerable_list_html; ?></td>
34
- </tr>
35
- <tr>
36
- <th scope="row">Safe Timthumb Files:</th>
37
- <td><?php echo $safe_list_html; ?></td>
38
- </tr>
39
- </table>
40
- <?php endif; ?>
41
- </div>
 
42
  </div>
1
  <div class="wrap">
2
+ <h2>Timthumb Scanner</h2>
3
+ <div class="postbox metabox-holder" style="float:right;width:300px;padding-top:0px">
4
+ <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>
5
+ <div class="inside">
6
+ <p><strong>Tired of worrying about your WordPress sites?</strong></p>
7
+ <p><a href="http://codegarage.com" target="_blank" >Locker</a> from <a href="http://codegarage.com/" target="_blank" >Code Garage</a> provides rock solid daily backups and hack monitoring and cleanup (for malicious code and vulnerabilities like this one), as well as personal, one on one support when you need it. Plans start at $15/month for 10 sites.</p>
8
+ <p style="text-align:center;padding-top:15px;"><a href="http://codegarage.com/" target="_blank" class="button-primary">Click here to learn more</a></p>
9
+ </div>
10
+ </div>
11
+ <div style="margin-right:320px;">
12
+ <h4>What's going on here?</h4>
13
+ <p>Here's how this works: When you click "Scan", we'll gather a list of all the files in your wp-content directory, and then we'll scan all of the php files looking for the timthumb script. If we find it, we'll scan it to make sure it's at least version 2 - which is the version that fixed the vulnerability. You'll be notified here of any files that need to be updated.</p>
14
+ <form action="tools.php?page=cg-timthumb-scanner" method="post">
15
+ <input type="hidden" name="cg-action" value="scan">
16
+ <button class="button-secondary">Scan!</button>
17
+ </form>
18
+ <?php if ( get_option( 'cg_tvs_last_checked' ) ): ?>
19
+ <h4>What now?</h4>
20
+ <p>We've now scanned all your themes and plugins, and any instances of the timthumb script are listed below. Problem files (timthumb scripts that are older than version 2.0) are in the "Vulnerable" list, and safe files (Newer than 2.0) are listed in the "Safe" list. "Vulnerable" files can be upgraded to the latest version of timthumb by clicking the "Fix" button next to each file.</p>
21
+ <table class="form-table">
22
+ <tr>
23
+ <th scope="row">Last Scanned:</th>
24
+ <td><?php echo get_option( 'cg_tvs_last_checked' ); ?></td>
25
+ </tr>
26
+ <tr>
27
+ <th scope="row">Vulnerable Timthumb Files:</th>
28
+ <td><?php echo $vulnerable_list_html; ?></td>
29
+ </tr>
30
+ <?php if(count($vulnerable_files)>1): ?>
31
+ <tr>
32
+ <th scope="row"></th>
33
+ <td><a href="<?php echo wp_nonce_url( 'tools.php?page=cg-timthumb-scanner&cg-action=fixall', 'fix_all_timthumb_files'); ?>" onclick="return confirm('Are you sure you want to fix ALL of the found files? This can't easily be undone. I'd suggest you make a backup of your wp-content directory before proceeding.')" class="button" style="margin-left:23px;">Fix All <?php echo count($vulnerable_files); ?> Vulnerable Files</a> <strong>Warning:</strong> Make sure you want ALL of the files fixed!</td>
34
+ </tr>
35
+ <?php endif; ?>
36
+ <tr>
37
+ <th scope="row">Safe Timthumb Files:</th>
38
+ <td><?php echo $safe_list_html; ?></td>
39
+ </tr>
40
+ </table>
41
+ <?php endif; ?>
42
+ </div>
43
  </div>
cg-tvs-filescanner.php CHANGED
@@ -1,101 +1,101 @@
1
  <?php
2
 
3
- class CG_FileScanner{
4
 
5
- public $BaseDir;
6
- public $Errors;
7
- public $Inventory;
8
- public $VulnerableFiles;
9
- public $SafeFiles;
10
-
11
- function __construct($base_dir){
12
- if(is_file($base_dir) || is_dir($base_dir)){
13
- $this->BaseDir = $base_dir;
14
- }else{
15
- die();
16
- }
17
- }
18
-
19
- function generate_inventory(){
20
- $this->Inventory = $this->get_dir_contents($this->BaseDir, true);
21
- }
22
 
23
- function get_dir_contents($path){
24
- $inventory = array();
25
- if(!$dir_handle = @opendir($path)){
26
- $this->Errors[] = "Couldn't open $path";
27
- return false;
28
- }
29
- while($file = readdir($dir_handle)) {
30
- if($file == '.' || $file == '..') continue;
31
- if(is_dir($path.'/'.$file)){
32
- $inventory = array_merge($inventory, $this->get_dir_contents($path.'/'.$file));
33
- }else{
34
- $inventory[] = $path.'/'.$file;
35
- }
36
- }
37
- closedir($dir_handle);
38
- return $inventory;
39
- }
40
-
41
- function file_stat($file){
42
- $file_info['path'] = $file;
43
- if(is_dir($file)){
44
- $file_info['type'] = 'directory';
45
- }else{
46
- $file_info['type'] = 'file';
47
- }
48
 
49
- $file_info['readable'] = is_readable($file);
50
- if($this->Type == 'structure'){
51
- if($file_info['type'] == 'directory'){
52
- $dir_stat = $this->dir_stat($file);
53
- $file_info['mtime'] = $dir_stat['mtime'];
54
- $file_info['child_nodes'] = $dir_stat['child_nodes'];
55
- $file_info['ctime'] = filectime($file);
56
- $file_info['atime'] = fileatime($file);
57
- return $file_info;
58
- }else{
59
- return '';
60
- }
61
- }
62
-
63
- if($this->Type != 'index' && $this->Type != 'structure'){
64
- $file_info['mtime'] = filemtime($file);
65
- $file_info['ctime'] = filectime($file);
66
- $file_info['atime'] = fileatime($file);
67
- $file_info['size'] = filesize($file);
68
- $file_info['hash'] = md5_file($file);
69
- }
70
-
71
- return $file_info;
72
  }
73
 
74
- function scan_inventory(){
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75
  $pattern_1 = "TimThumb script created by Tim McDaniels and Darren Hoyt|TimThumb script created by Ben Gillbanks\, originally created by Tim McDaniels and Darren Hoyt|TimThumb by Ben Gillbanks";
76
- $pattern_2 = "define\s*\(\'VERSION\',\s*\'[23456789]\.[0-9]";
77
-
78
- foreach($this->Inventory as $path){
79
- $path_parts = pathinfo($path);
80
- // Don't scan this plugin's files
81
- if(preg_match("~^".dirname(__FILE__)."~", $path)){
82
- continue;
83
- }
84
- if($path_parts['extension'] == 'php'){
85
- if($file_handle = @fopen($path, "r")){
86
- $contents = @fread($file_handle, filesize($path));
87
- if (preg_match("~$pattern_1~", $contents)){
88
- // We have a timthumb script. Now check to see if it is version 2.0 or greater.
89
- if (!preg_match("~$pattern_2~", $contents)){
90
- $this->VulnerableFiles[] = $path;
91
- }else{
92
- $this->SafeFiles[] = $path;
93
- }
94
- }
95
- }
96
- }
97
- }
98
- }
99
 
100
  }
101
  ?>
1
  <?php
2
 
3
+ class CG_FileScanner {
4
 
5
+ public $BaseDir;
6
+ public $Errors;
7
+ public $Inventory;
8
+ public $VulnerableFiles;
9
+ public $SafeFiles;
 
 
 
 
 
 
 
 
 
 
 
 
10
 
11
+ function __construct( $base_dir ) {
12
+ if ( is_file( $base_dir ) || is_dir( $base_dir ) ) {
13
+ $this->BaseDir = $base_dir;
14
+ } else {
15
+ die();
16
+ }
17
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
 
19
+ function generate_inventory() {
20
+ $this->Inventory = $this->get_dir_contents( $this->BaseDir, true );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
  }
22
 
23
+ function get_dir_contents( $path ) {
24
+ $inventory = array();
25
+ if ( ! $dir_handle = @opendir( $path ) ) {
26
+ $this->Errors[] = "Couldn't open $path";
27
+ return false;
28
+ }
29
+ while ( $file = readdir( $dir_handle ) ) {
30
+ if ( $file == '.' || $file == '..' ) continue;
31
+ if ( is_dir( $path . '/' . $file ) ) {
32
+ $inventory = array_merge( $inventory, $this->get_dir_contents( $path . '/' . $file ) );
33
+ } else {
34
+ $inventory[] = $path . '/' . $file;
35
+ }
36
+ }
37
+ closedir( $dir_handle );
38
+ return $inventory;
39
+ }
40
+
41
+ function file_stat( $file ) {
42
+ $file_info['path'] = $file;
43
+ if( is_dir( $file ) ) {
44
+ $file_info['type'] = 'directory';
45
+ }else{
46
+ $file_info['type'] = 'file';
47
+ }
48
+
49
+ $file_info['readable'] = is_readable( $file );
50
+ if ( $this->Type == 'structure' ) {
51
+ if ( $file_info['type'] == 'directory' ) {
52
+ $dir_stat = $this->dir_stat( $file );
53
+ $file_info['mtime'] = $dir_stat['mtime'];
54
+ $file_info['child_nodes'] = $dir_stat['child_nodes'];
55
+ $file_info['ctime'] = filectime( $file );
56
+ $file_info['atime'] = fileatime( $file );
57
+ return $file_info;
58
+ } else {
59
+ return '';
60
+ }
61
+ }
62
+
63
+ if ( $this->Type != 'index' && $this->Type != 'structure' ) {
64
+ $file_info['mtime'] = filemtime( $file );
65
+ $file_info['ctime'] = filectime( $file );
66
+ $file_info['atime'] = fileatime( $file );
67
+ $file_info['size'] = filesize( $file );
68
+ $file_info['hash'] = md5_file( $file );
69
+ }
70
+
71
+ return $file_info;
72
+ }
73
+
74
+ function scan_inventory() {
75
  $pattern_1 = "TimThumb script created by Tim McDaniels and Darren Hoyt|TimThumb script created by Ben Gillbanks\, originally created by Tim McDaniels and Darren Hoyt|TimThumb by Ben Gillbanks";
76
+ $pattern_2 = 'define\s*\(\'VERSION\',\s*\'[23456789]\.[0-9]';
77
+
78
+ foreach( $this->Inventory as $path ) {
79
+ $path_parts = pathinfo( $path );
80
+ // Don't scan this plugin's files
81
+ if( preg_match( '~^' . dirname(__FILE__) . "~", $path ) ) {
82
+ continue;
83
+ }
84
+ if( $path_parts['extension'] == 'php' ) {
85
+ if( $file_handle = @fopen( $path, 'r' ) ) {
86
+ $contents = @fread( $file_handle, filesize( $path ) );
87
+ if ( preg_match( "~$pattern_1~", $contents ) ) {
88
+ // We have a timthumb script. Now check to see if it is version 2.0 or greater.
89
+ if ( ! preg_match( "~$pattern_2~", $contents ) ) {
90
+ $this->VulnerableFiles[] = $path;
91
+ } else {
92
+ $this->SafeFiles[] = $path;
93
+ }
94
+ }
95
+ }
96
+ }
97
+ }
98
+ }
99
 
100
  }
101
  ?>
readme.txt CHANGED
@@ -15,7 +15,7 @@ The Timthumb Vulnerability Scanner plugin will scan your entire wp-content direc
15
 
16
  More info at [CodeGarage](http://codegarage.com/blog/2011/09/wordpress-timthumb-vulnerability-scanner-plugin/).
17
 
18
-
19
  == Installation ==
20
 
21
  1. Upload the `timthumb-vulnerability-scanner to the `/wp-content/plugins/` directory (alternatively, you could use the backend WordPress plugin installer, or install directly from the repository)
@@ -43,6 +43,9 @@ No. This plugin exists to make sure your door is locked, not drag the burglers
43
 
44
  == Changelog ==
45
 
 
 
 
46
  = 1.2 =
47
  * Updated scanner to more reliably find versions of timthumb - avoids conflict with plugin "Category Icons".
48
 
15
 
16
  More info at [CodeGarage](http://codegarage.com/blog/2011/09/wordpress-timthumb-vulnerability-scanner-plugin/).
17
 
18
+ Special thanks to [Jacob Gillespie](http://jacobwg.com/) for help with the bulk upgrade feature.
19
  == Installation ==
20
 
21
  1. Upload the `timthumb-vulnerability-scanner to the `/wp-content/plugins/` directory (alternatively, you could use the backend WordPress plugin installer, or install directly from the repository)
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
+
49
  = 1.2 =
50
  * Updated scanner to more reliably find versions of timthumb - avoids conflict with plugin "Category Icons".
51
 
timthumb-vulnerability-scanner.php CHANGED
@@ -3,8 +3,8 @@
3
  Plugin Name: TimThumb Vulnerability Scanner
4
  Plugin URI: http://codegarage.com/blog/2011/09/wordpress-timthumb-vulnerability-scanner-plugin/
5
  Description: Find all those pesky timthumb.php scripts with vulnerabilities BEFORE you get hacked! Scans your wp-content directory for vulnerable instances of timthumb.php, and optionally upgrades them.
6
- Author: Peter Butler
7
- Version: 1.2
8
  Author URI: http://codegarage.com/
9
  */
10
 
@@ -13,93 +13,128 @@ Author URI: http://codegarage.com/
13
  // = ADMIN MENU =
14
  // ==============
15
 
16
- add_action('admin_menu', 'cg_tvs_scanner_menu');
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
- include_once 'cg-tvs-filescanner.php';
31
- $scanner = new CG_FileScanner(WP_CONTENT_DIR);
32
- $scanner->generate_inventory();
33
- $scanner->scan_inventory();
34
- update_option('cg_tvs_last_checked', date("Y-m-d H:i:s"));
35
- update_option('cg_tvs_vulnerable_files', $scanner->VulnerableFiles);
36
- update_option('cg_tvs_safe_files', $scanner->SafeFiles);
37
- case 'fix':
38
- $nonce = $_GET['_wpnonce'];
39
- if(wp_verify_nonce($nonce, 'fix_timthumb_file')){
40
- $fix_path = urldecode($_GET['file']);
41
- $src_file_path = trailingslashit(dirname(__FILE__)).'cg-tvs-timthumb-latest.txt';
42
- if(FALSE !== $fr = @fopen($src_file_path, 'r')){
43
- $latest_src = fread($fr, filesize($src_file_path));
44
- fclose($fr);
45
- }else{
46
- $message = "CAN'T READ TIMTHUMB SOURCE FILE";
47
- break;
48
- }
49
- if(FALSE !== $fw = @fopen($fix_path, 'w')){
50
- if(fwrite($fw, $latest_src)){
51
- $message = "File <strong>".basename($fix_path)."</strong> at <em>".$fix_path."</em> successfully upgraded.";
52
- }else{
53
- $message = "Unknown file write error.";
54
- }
55
- }else{
56
- $message = "CAN'T OPEN VULNERABLE FILE FOR WRITING";
57
- break;
58
- }
59
- // Re-scan site
60
- include_once 'cg-tvs-filescanner.php';
61
- $scanner = new CG_FileScanner(WP_CONTENT_DIR);
62
- $scanner->generate_inventory();
63
- $scanner->scan_inventory();
64
- update_option('cg_tvs_last_checked', date("Y-m-d H:i:s"));
65
- update_option('cg_tvs_vulnerable_files', $scanner->VulnerableFiles);
66
- update_option('cg_tvs_safe_files', $scanner->SafeFiles);
67
- }
68
- }
69
  }
70
-
71
- $vulnerable_files = get_option('cg_tvs_vulnerable_files');
72
- if(is_array($vulnerable_files) && !empty($vulnerable_files)){
73
- $vulnerable_list_html = "<ol>\n";
74
- foreach($vulnerable_files as $file){
75
- $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>\n";
76
- }
77
- $vulnerable_list_html .= "</ol>\n";
78
- }else{
79
- $vulnerable_list_html = "<span style='color:forestgreen'>No Vulnerabilities Found!</span>";
80
  }
81
-
82
- $safe_files = get_option('cg_tvs_safe_files');
83
- if(is_array($safe_files) && !empty($safe_files)){
84
- $safe_list_html = "<ol>\n";
85
- foreach($safe_files as $file){
86
- $safe_list_html .= "<li><span style='color:forestgreen'>".basename($file)."</span> <small>(found at $file)</small></li>\n";
87
- }
88
- $safe_list_html .= "</ol>\n";
89
- }else{
90
- $safe_list_html = "<span style='color:forestgreen'>No Up to Date Versions Found!</span>";
91
  }
92
  include_once 'cg-tvs-admin-panel.php';
93
  }
94
 
95
- // ================
96
- // = DEACTIVATION =
97
- // ================
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
98
 
99
  register_deactivation_hook( __FILE__, 'cg_tvs_scan_deactivate' );
100
 
101
- function cg_tvs_scan_deactivate(){
102
- delete_option('cg_tvs_last_checked');
103
- delete_option('cg_tvs_vulnerable_files');
104
- delete_option('cg_tvs_safe_files');
105
  }
3
  Plugin Name: TimThumb Vulnerability Scanner
4
  Plugin URI: http://codegarage.com/blog/2011/09/wordpress-timthumb-vulnerability-scanner-plugin/
5
  Description: Find all those pesky timthumb.php scripts with vulnerabilities BEFORE you get hacked! Scans your wp-content directory for vulnerable instances of timthumb.php, and optionally upgrades them.
6
+ Author: Peter Butler</a>, <a href="http://jacobwg.com/">Jacob Gillespie
7
+ Version: 1.3
8
  Author URI: http://codegarage.com/
9
  */
10
 
13
  // = ADMIN MENU =
14
  // ==============
15
 
16
+ add_action( 'admin_menu', 'cg_tvs_scanner_menu' );
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
  }