Skip to content

Instantly share code, notes, and snippets.

@jkrehm
Created February 12, 2016 18:26
Show Gist options
  • Save jkrehm/7b38a20d6324779ce90b to your computer and use it in GitHub Desktop.
Save jkrehm/7b38a20d6324779ce90b to your computer and use it in GitHub Desktop.
PHP Version Scanner
<?php namespace HighPoint\VersionScan;
use Exception;
use GuzzleHttp\Client;
use GuzzleHttp\Query;
/**
* Version scanner
*/
class Scanner
{
protected $client;
/**
* Instantiate a Guzzle client
*/
public function __construct()
{
$this->client = new Client();
}
/**
* Scan the specified version of PHP for vulnerabilities
*
* @param string $version PHP version to scan
*
* @return array Array of vulnerabilities
*
* @throws Exception If exception caught
*/
public function scan($version = '')
{
// Default to current PHP version
$version = $version ?: phpversion();
// Clean up version number
$modifiedVersion = preg_replace('/([0-9]+\.[0-9]+\.[0-9]+).*/', '$1', $version);
try {
$html = $this->getHTML($modifiedVersion);
$id = $this->parseHTML($html);
$vulnerabilities = $this->getVulnerabilities($id);
} catch (Exception $e) {
if ($e->getCode() !== 200) {
throw $e;
}
$vulnerabilities = [];
}
return array(
'version' => $modifiedVersion,
'versionModified' => $version !== $modifiedVersion,
'vulnerabilities' => $vulnerabilities,
);
}
/**
* Get HTML with PHP version ID
*
* @param string $version PHP version to retrieve
*
* @return string HTML with PHP version ID
*
* @throws Exception If request fails
*/
protected function getHTML($version)
{
$request = $this->client->createRequest('GET', 'http://www.cvedetails.com/version-search.php');
$query = new Query(array(
'vendor' => '',
'product' => 'PHP',
'version' => $version,
));
$request->setQuery($query);
$response = $this->client->send($request);
if ($response->getStatusCode() !== 200) {
throw new Exception('Error getting HTML', $response->getStatusCode());
}
return $response->getBody()->__toString();
}
/**
* Parse HTML to retrieve version ID
*
* @param string $html HTML with PHP version ID
*
* @return string PHP version ID
*
* @throws Exception If ID is not found in the HTML
*/
protected function parseHTML($html)
{
// e.g. <link rel="canonical" href="http://www.cvedetails.com/vulnerability-list.php?vendor_id=74&product_id=128&version_id=178362"/>
if (preg_match('/link.*rel="canonical".*&version_id=(.*?)[&"]/', $html, $id)) {
$id = $id[1];
} else {
throw new Exception('Version ID not found', 200);
}
return $id;
}
/**
* Get list of known vulnerabilities for the PHP version
*
* @param string $id PHP version ID
*
* @return array Known vulnerabilities for PHP version
*
* @throws Exception If request fails
*/
protected function getVulnerabilities($id)
{
$request = $this->client->createRequest('GET', 'http://www.cvedetails.com/json-feed.php');
$query = new Query(array(
'vendor_id' => '74',
'product_id' => '128',
'version_id' => $id,
));
$request->setQuery($query);
$response = $this->client->send($request);
if ($response->getStatusCode() !== 200) {
throw new Exception('Error getting vulnerabilities', $response->getStatusCode());
}
return $response->json();
}
}
@jkrehm
Copy link
Author

jkrehm commented Feb 12, 2016

Usage:

try {
    $scanner = new \HighPoint\VersionScan\Scanner();
    $results = $scanner->scan(); // Note: A specific version can be passed into the scanner
} catch (Exception $e) {
    // Handle the exception
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment