Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
umutphp committed Jan 17, 2019
1 parent 796c99c commit 9a8a590
Show file tree
Hide file tree
Showing 7 changed files with 310 additions and 4 deletions.
5 changes: 1 addition & 4 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
composer.phar
/vendor/

# Commit your application's lock file https://getcomposer.org/doc/01-basic-usage.md#commit-your-composer-lock-file-to-version-control
# You may choose to ignore a library lock file http://getcomposer.org/doc/02-libraries.md#lock-file
# composer.lock
/composer.lock
24 changes: 24 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"name": "umutphp/wp-vulnerability-check",
"license": "GNU GENERAL PUBLIC LICENSE",
"description": "Check the WPScan Vulnerability Database via API to identify the security issues on plugins and WordPress installed.",
"authors": [
{
"name": "Umut Işık",
"email": "umutphp@gmail.com"
}
],
"autoload": {
"psr-4": {"UmutPHP\\WPVulnerabilityCheck\\": "src/"}
},
"require": {
"php": ">=5.4.0",
"ext-curl": "*",
"ext-json": "*"
},
"require-dev": {
"phpunit/phpunit": "~4.5",
"jakub-onderka/php-parallel-lint": "~1.0"
},
"bin": ["wp-vulnerability-check"]
}
11 changes: 11 additions & 0 deletions src/ArrayIterator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php
namespace UmutPHP\WPVulnerabilityCheck;

class ArrayIterator extends \ArrayIterator
{
public function getNext()
{
$this->next();
return $this->current();
}
}
115 changes: 115 additions & 0 deletions src/Manager.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
<?php
namespace UmutPHP\WPVulnerabilityCheck;

class Manager
{
CONST WPVULNDB_V3_URL = 'https://wpvulndb.com/api/v3/';
/**
* @param Settings $settings
* @return bool
* @throws Exception\NotExistsPath
*/
public function check(Settings $settings)
{
$plugins = $this->getFilesFromPaths($settings->path, $settings->excluded);

/** @var Result[] $results */
$results = array();
$startTime = microtime(true);
$checkedPlugins = 0;
$vulnerablePlugins = 0;
$results = array();

foreach ($plugins as $plugin) {
try {
$fileResult = $this->checkPlugin($plugin);
$checkedPlugins++;

// Get Vulnerabilities and check the plugin with version
$vulnerablePlugins++;
echo "v"; // For vulnerability
echo "."; // For success
$pluginResult = array('Vulnerability Result');
$results = array_merge($results, $pluginResult);
} catch (Exception\Exception $e) {
echo "f"; // Fail
$pluginResult = array($e->getMessage());
$results = array_merge($results, $pluginResult);
}
}

$runTime = round(microtime(true) - $startTime, 1);

echo PHP_EOL . PHP_EOL;

$message = "Checked $checkedPlugins plugins in $runTime second, ";
if ($vulnerablePlugins === 0) {
$message .= "no vulnerability found.";
} else {
$message .= "some vulnerability(s) in $vulnerablePlugins ";
$message .= ($vulnerablePlugins === 1 ? 'file' : 'files');
}

echo $message . PHP_EOL;

if (!empty($results)) {
$output->writeNewLine();

foreach ($results as $result) {
echo str_repeat('-', 60);
echo $result[0];
echo PHP_EOL;
}

return false;
}

return true;
}

/**
* Check plugin with plugin name via API
*
* @param string $pluginName
* @param Settings $settings
* @return Result[]
* @throws Exception
*/
public function checkPlugin($pluginName, Settings $settings = null)
{
if ($settings === null) {
$settings = new Settings();
}

$results = array();

return $results;
}

/**
* Private function to get the result from the API
*
* @param string $pluginName
* @param string $APIToken
* @return array Array decoded from JSON string
*/
private function get($pluginName, $APIToken) {
$ch = curl_init();
$url = self::WPVULNDB_V3_URL . 'plugins/' . $pluginName;

curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$headers = array(
'Authorization: Token token=' . $APIToken
);

curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$server_output = curl_exec ($ch);

curl_close ($ch);

return json_decode($server_output);
}
}
64 changes: 64 additions & 0 deletions src/Settings.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<?php
namespace UmutPHP\WPVulnerabilityCheck;

class Settings
{
/**
* Full path of the plugin directory to check
* @var string
*/
public $path = '.';

/**
* Dont't check files or directories
* @var array
*/
public $excluded = array();

/**
* Use colors in console output
* @var bool
*/
public $colors = true;

/**
* The API Token taken from the wpvulndb.com site to use API.
* @var bool
*/
public $token = '';
/**
* @param array $arguments
* @return Settings
* @throws Exception\InvalidArgument
*/
public static function parseArguments(array $arguments)
{
$arguments = new ArrayIterator(array_slice($arguments, 1));
$setting = new self;

foreach ($arguments as $argument) {
if ($argument{0} !== '-') {
$setting->paths[] = $argument;
} else {
switch ($argument) {
case '--path':
$setting->path = trim($arguments->getNext());
break;
case '--token':
$setting->token = trim($arguments->getNext());
break;
case '--exclude':
$setting->excluded[] = explode(',', $arguments->getNext());
break;
case '--no-colors':
$setting->colors = false;
break;
default:
throw new \Exception("Invalid argument $argument");
}
}
}

return $setting;
}
}
3 changes: 3 additions & 0 deletions wp-vulnerability-check
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/usr/bin/env php
<?php
require __DIR__ . DIRECTORY_SEPARATOR . 'wp-vulnerability-check.php';
92 changes: 92 additions & 0 deletions wp-vulnerability-check.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
<?php
use UmutPHP\WPVulnerabilityCheck;

const VERSION = '0.0.1';

const SUCCESS = 0,
WITH_ERRORS = 1,
FAILED = 254;

if (PHP_VERSION < '5.4.0') {
fwrite(STDERR,"WP Vulnerability Check requires PHP 5.4.0 and newer");
die(FAILED);
}

function showOptions() {
?>
Options:
--path Full path for the plugin directory of your WordPress installation.
--token Token got from wpvulndb.com
--exclude Exclude the plugins given in comma separated format.
--version Show version.
--help Print this help.
<?php
}

// Help
if (!isset($_SERVER['argv'][1]) || in_array('--help', $_SERVER['argv'])) { ?>
WP Vulnerability Check version <?= VERSION ?>
---------------------------
Usage:
wp-vulnerability-check [options]
<?php
showOptions();
exit;
}

// Version
if (in_array('--version', $_SERVER['argv'])) {
echo VERSION . PHP_EOL;
exit;
}

if (!function_exists('curl_version')) {
echo 'PHP Curl extension is a must.' . PHP_EOL;
die(FAILED);
}

if (!function_exists('json_decode')) {
echo 'PHP JSON extension is a must.' . PHP_EOL;
die(FAILED);
}

$files = array(
__DIR__ . '/../../autoload.php',
__DIR__ . '/vendor/autoload.php'
);

$autoloadFileFound = false;
foreach ($files as $file) {
if (file_exists($file)) {
require $file;
$autoloadFileFound = true;
break;
}
}

if (!$autoloadFileFound) {
$message = 'You need to set up the project dependencies using composer commands:' . PHP_EOL;
fwrite(STDERR,
$message
);
echo $message . PHP_EOL;
die(FAILED);
}

try {
$settings = WPVulnerabilityCheck\Settings::parseArguments($_SERVER['argv']);
} catch (\Exception $e) {
fwrite(STDERR, "Invalid option {$e->getArgument()}" . PHP_EOL);
echo PHP_EOL;
showOptions();
die(FAILED);
}

try {
$check = new WPVulnerabilityCheck\Manager();
$status = $check->check($settings);
die($status ? SUCCESS : WITH_ERRORS);
} catch (\Exception $e) {
fwrite(STDERR, $e->getMessage() . PHP_EOL);
die(FAILED);
}

0 comments on commit 9a8a590

Please sign in to comment.