Skip to content

Commit

Permalink
feat: new wordpress detector and checksum file path verifier
Browse files Browse the repository at this point in the history
  • Loading branch information
marcocesarato committed Oct 24, 2020
1 parent 0abad4a commit 21d76f0
Show file tree
Hide file tree
Showing 4 changed files with 239 additions and 6 deletions.
165 changes: 165 additions & 0 deletions src/Module/Wordpress.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
<?php

namespace marcocesarato\amwscan\Module;

use marcocesarato\amwscan\Console;
use marcocesarato\amwscan\VerifierInterface;

class Wordpress implements VerifierInterface
{
protected static $checksums = array();
protected static $roots = array();
protected static $DS = DIRECTORY_SEPARATOR;

/**
* Initialize path.
*
* @param $path
*/
public static function init($path)
{
if (self::isRoot($path)) {
$version = self::getVersion($path);
if ($version && !empty($version) && !isset(self::$roots[$path])) {
Console::writeLine('Found WordPress ' . $version . ' at "' . $path . '"', 1, 'green');
self::$roots[$path] = array(
'path' => $path,
'version' => $version,
);
self::getChecksums($version);
}
}
}

/**
* Detect root.
*
* @param $path
*
* @return bool
*/
public static function isRoot($path)
{
return
is_dir($path) &&
is_dir($path . self::$DS . 'wp-admin') &&
is_dir($path . self::$DS . 'wp-content') &&
is_dir($path . self::$DS . 'wp-includes') &&
is_file($path . self::$DS . 'wp-config.php') &&
is_file($path . self::$DS . 'wp-includes' . self::$DS . 'version.php')
;
}

/**
* Get version.
*
* @param $root
*
* @return string|null
*/
public static function getVersion($root)
{
$versionFile = $root . self::$DS . 'wp-includes' . self::$DS . 'version.php';
if (is_file($versionFile)) {
$versionContent = file_get_contents($versionFile);
preg_match('/\$wp_version[\s]*=[\s]*[\'"]([0-9.]+)[\'"]/', $versionContent, $match);
$version = trim($match[1]);
if (!empty($version)) {
return $version;
}
}

return null;
}

/**
* Get checksums.
*
* @param $version
*
* @return array
*/
public static function getChecksums($version)
{
if (empty(self::$checksums[$version])) {
$checksums = file_get_contents('https://api.wordpress.org/core/checksums/1.0/?version=' . $version);
$checksums = json_decode($checksums, true);
$versionChecksums = $checksums['checksums'][$version];
self::$checksums[$version] = array();
// Sanitize paths and checksum
foreach ($versionChecksums as $filePath => $checksum) {
$sanitizePath = self::sanitizePath($filePath);
self::$checksums[$version][$sanitizePath] = strtolower($checksum);
}
}

return self::$checksums[$version];
}

/**
* Is verified file.
*
* @param $path
*
* @return bool
*/
public static function isVerified($path)
{
if (!is_file($path)) {
return false;
}

$root = self::getRoot($path);
if (!empty($root)) {
$comparePath = str_replace($root['path'], '', $path);
$comparePath = self::sanitizePath($comparePath);
$checksums = self::getChecksums($root['version']);
if (!$checksums) {
return false;
}
if (!empty($checksums[$comparePath])) {
$checksum = md5_file($path);
$checksum = strtolower($checksum);

return $checksums[$comparePath] === $checksum;
}
}

return false;
}

/**
* Get root from child file.
*
* @param $path
*
* @return array
*/
public static function getRoot($path)
{
foreach (self::$roots as $key => $root) {
if (strpos($path, $root['path']) === 0) {
return $root;
}
}

return null;
}

/**
* Sanitize path to be compared.
*
* @param $path
*
* @return string
*/
public static function sanitizePath($path)
{
$sanitized = preg_replace('#[\\\\/]+#', self::$DS, $path);
$sanitized = trim($sanitized);
$sanitized = trim($sanitized, self::$DS);
$sanitized = strtolower($sanitized);

return $sanitized;
}
}
33 changes: 33 additions & 0 deletions src/Modules.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

namespace marcocesarato\amwscan;

use marcocesarato\amwscan\Module\Wordpress;

class Modules
{
/**
* Check path.
*
* @param $path
*/
public static function init($path)
{
Wordpress::init($path);
}

/**
* Is verified file.
*
* @param $path
*
* @return bool
*/
public static function isVerified($path)
{
$result = false;
$result = (Wordpress::isVerified($path) || $result);

return $result;
}
}
23 changes: 17 additions & 6 deletions src/Scanner.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class Scanner
*
* @var string
*/
public static $version = '0.6.0.109';
public static $version = '0.7.0.110';

/**
* Root path.
Expand Down Expand Up @@ -273,12 +273,12 @@ public function run($args = null)
Console::writeLine('Scanning ' . self::$pathScan, 2);

// Mapping files
Console::writeLine('Mapping files...');
Console::writeLine('Mapping and verifying files. It may take a while, please wait...');
$iterator = $this->mapping();

// Counting files
$files_count = iterator_count($iterator);
Console::writeLine('Found ' . $files_count . ' files', 2);
Console::writeLine('Found ' . $files_count . ' files to check', 2);
Console::writeLine('Checking files...', 2);
Console::progress(0, $files_count);

Expand Down Expand Up @@ -680,7 +680,7 @@ public function mapping()
// Mapping files
$directory = new RecursiveDirectoryIterator(self::$pathScan);
$files = new RecursiveIteratorIterator($directory);
$iterator = new CallbackFilterIterator($files, function ($cur) {
$filtered = new CallbackFilterIterator($files, function ($cur) {
$ignore = false;
$wildcard = '.*?'; // '[^\\\\\\/]*'
// Ignore
Expand All @@ -700,11 +700,21 @@ public function mapping()
}
}

if (!$ignore &&
$cur->isDir()) {
Modules::init($cur->getPath());

return false;
}

return
!$ignore &&
$cur->isFile() &&
in_array($cur->getExtension(), self::getExtensions(), true)
;
in_array($cur->getExtension(), self::getExtensions(), true);
});

$iterator = new CallbackFilterIterator($filtered, function ($cur) {
return $cur->isFile() && !Modules::isVerified($cur->getPathname());
});

return $iterator;
Expand Down Expand Up @@ -974,6 +984,7 @@ private function scan($iterator)
Console::display($title, 'white', 'red');
}
Console::newLine(2);
Console::writeLine('Checksum: ' . md5_file($_FILE_PATH), 1, 'yellow');
Console::writeLine('File path: ' . $_FILE_PATH, 1, 'yellow');
Console::writeLine('Exploits found: ' . Console::eol(1) . implode(Console::eol(1), array_keys($pattern_found)), 2, 'red');
Console::displayLine('OPTIONS:', 2);
Expand Down
24 changes: 24 additions & 0 deletions src/VerifierInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

namespace marcocesarato\amwscan;

interface VerifierInterface
{
/**
* Initialize path.
*
* @param $path
*
* @return mixed
*/
public static function init($path);

/**
* Is verified file.
*
* @param $path
*
* @return mixed
*/
public static function isVerified($path);
}

0 comments on commit 21d76f0

Please sign in to comment.