Skip to content

Instantly share code, notes, and snippets.

@marcus-downing
Last active August 29, 2015 14:23
Show Gist options
  • Save marcus-downing/30f1fbb6272e1dc839f0 to your computer and use it in GitHub Desktop.
Save marcus-downing/30f1fbb6272e1dc839f0 to your computer and use it in GitHub Desktop.
Plugin Security Scanner
<?php
/**
* Plugin Name: Plugin Security Scanner
* Plugin URI: http://www.glenscott.co.uk/plugin-security-scanner/
* Description: This plugin determines whether any of your plugins have security vulnerabilities. It does this by looking up details in the WPScan Vulnerability Database.
* Version: 1.1.9
* Author: Glen Scott
* Author URI: http://www.glenscott.co.uk
* License: GPL2
*/
/* Copyright 2015 Glen Scott (email : [email protected])
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License, version 2, as
published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
defined( 'ABSPATH' ) or die( 'No script kiddies please!' );
if ( ! class_exists( 'WP_Http' ) ) {
include_once( ABSPATH . WPINC. '/class-http.php' );
}
// Check if get_plugins() function exists. This is required on the front end of the
// site, since it is in a file that is normally only loaded in the admin.
if ( ! function_exists( 'get_plugins' ) ) {
require_once ABSPATH . 'wp-admin/includes/plugin.php';
}
/** Step 2 (from text above). */
add_action( 'admin_menu', 'plugin_security_scanner_menu' );
/** Step 1. */
function plugin_security_scanner_menu() {
add_management_page(
__('Plugin Security Scanner', 'plugin_security_scanner'),
__('Plugin Security Scanner', 'plugin_security_scanner'),
'manage_options', 'plugin-security-scanner', 'plugin_security_scanner_options' );
}
function plugin_security_scanner_get_vulnerabilities($schedule) {
$request = new WP_Http;
$vulnerabilities = array();
foreach ( get_plugins() as $name => $details ) {
// get unique name
if ( preg_match( '|(.+)/|', $name, $matches ) ) {
$result = $request->request( 'https://wpvulndb.com/api/v1/plugins/' . $matches[1] );
if ( $result['body'] ) {
$plugin = json_decode( $result['body'] );
if ( isset( $plugin->plugin->vulnerabilities ) ) {
foreach ( $plugin->plugin->vulnerabilities as $vuln ) {
if ( !isset($vuln->fixed_in) ||
version_compare( $details['Version'], $vuln->fixed_in, '<' ) ) {
$vulnerabilities[$name][] = $vuln;
}
}
}
}
}
}
do_action('plugin_security_scanner_vulnerabilities', $vulnerabilities, $schedule);
return $vulnerabilities;
}
/** Step 3. */
function plugin_security_scanner_options() {
if ( ! current_user_can( 'manage_options' ) ) {
wp_die( __( 'You do not have sufficient permissions to access this page.' ) );
}
echo '<div class="wrap">';
echo '<h2>' . __('Plugin Security Scanner', 'plugin_security_scanner') . '</h2>';
flush();
$vulnerabilities = plugin_security_scanner_get_vulnerabilities('options');
if (!empty($vulnerabilities)) {
$plugins = get_plugins();
$vulnerability_count = 0;
foreach ($vulnerabilities as $name => $plugin_vulnerabilities) {
$plugin = $plugins[$name];
echo "<h3>".__($plugin['Name'])."</h3>\n";
foreach ($plugin_vulnerabilities as $vuln) {
echo '<p><strong>' .
__('Vulnerability found', 'plugin_security_scanner') .
':</strong> ' . esc_html( $vuln->title ) .
' -- <a href="' . esc_url( 'https://wpvulndb.com/vulnerabilities/' . $vuln->id ) .
'" target="_blank">' . __('View details', 'plugin_security_scanner') . '</a></p>';
$vulnerability_count++;
}
}
echo '<p>' . sprintf( _n(
'Scan completed: %s vulnerability found.',
'Scan completed: %s vulnerabilities found.',
$vulnerability_count, 'plugin_security_scanner'), '<strong>'.$vulnerability_count.'</strong>' ) .
'</p>';
} else {
echo '<p>'.__('No vulnerabilities found', 'plugin_security_scanner').'</p>';
}
echo '</div>';
}
// scheduled email to admin
register_activation_hook( __FILE__, 'plugin_security_scanner_activation' );
/**
* On activation, set a time, frequency and name of an action hook to be scheduled.
*/
function plugin_security_scanner_activation() {
wp_schedule_event( time(), 'daily', 'plugin_security_scanner_daily_event_hook' );
}
add_action( 'plugin_security_scanner_daily_event_hook', 'plugin_security_scanner_do_this_daily' );
add_action( 'plugin_security_scanner_vulnerabilities', 'plugin_security_scanner_daily_email', 2 );
/**
* On the scheduled action hook, run the function.
*/
function plugin_security_scanner_do_this_daily() {
plugin_security_scanner_get_vulnerabilities('daily');
}
/**
* Default action: send an email to the site admin
*/
function plugin_security_scanner_daily_email($vulnerabilities, $schedule) {
$admin_email = get_option( 'admin_email' );
if ( $admin_email && $schedule == 'daily' && !empty($vulnerabilities)) {
$mail_body = '';
foreach ($vulnerabilities as $name => $plugin_vulnerabilities) {
foreach ($plugin_vulnerabilities as $vuln) {
$mail_body .= 'Vulnerability found: ' . $vuln->title . "\n";
}
}
// if vulns, email admin
$msg = sprintf(_n(
'Scan completed: %s vulnerability found.',
'Scan completed: %s vulnerabilities found.',
$vulnerability_count, 'plugin_security_scanner'), $vulnerability_count);
$mail_body .= "\n\n" . $msg . "\n";
$date = date_i18n( get_option( 'date_format' ) );
$mail_subject = get_bloginfo() . sprintf(__(' Plugin Security Scan %s', 'plugin_security_scanner'), $date );
wp_mail( $admin_email, $mail_subject, $mail_body );
}
}
register_deactivation_hook( __FILE__, 'prefix_deactivation' );
/**
* On deactivation, remove all functions from the scheduled action hook.
*/
function prefix_deactivation() {
wp_clear_scheduled_hook( 'plugin_security_scanner_daily_event_hook' );
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment