2019-06-01 13:06:58 +03:00
|
|
|
<?php
|
2022-05-12 22:53:03 +03:00
|
|
|
/**
|
|
|
|
* Uses the API as documented here:
|
|
|
|
* https://haveibeenpwned.com/API/v3#AllBreaches
|
|
|
|
*
|
|
|
|
* Gets the latest breaches by the date of the breach or when it was added to
|
|
|
|
* HIBP.
|
|
|
|
* */
|
2019-06-01 13:06:58 +03:00
|
|
|
class HaveIBeenPwnedBridge extends BridgeAbstract {
|
|
|
|
const NAME = 'Have I Been Pwned (HIBP) Bridge';
|
|
|
|
const URI = 'https://haveibeenpwned.com';
|
|
|
|
const DESCRIPTION = 'Returns list of Pwned websites';
|
|
|
|
const MAINTAINER = 'VerifiedJoseph';
|
|
|
|
const PARAMETERS = array(array(
|
|
|
|
'order' => array(
|
|
|
|
'name' => 'Order by',
|
|
|
|
'type' => 'list',
|
|
|
|
'values' => array(
|
|
|
|
'Breach date' => 'breachDate',
|
|
|
|
'Date added to HIBP' => 'dateAdded',
|
|
|
|
),
|
|
|
|
'defaultValue' => 'dateAdded',
|
2019-07-26 11:47:20 +03:00
|
|
|
),
|
|
|
|
'item_limit' => array(
|
|
|
|
'name' => 'Limit number of returned items',
|
|
|
|
'type' => 'number',
|
2022-03-24 13:59:34 +03:00
|
|
|
'required' => true,
|
2019-07-26 11:47:20 +03:00
|
|
|
'defaultValue' => 20,
|
2019-06-01 13:06:58 +03:00
|
|
|
)
|
|
|
|
));
|
2022-05-12 22:53:03 +03:00
|
|
|
const API_URI = 'https://haveibeenpwned.com/api/v3';
|
2019-06-01 13:06:58 +03:00
|
|
|
|
|
|
|
const CACHE_TIMEOUT = 3600;
|
|
|
|
|
|
|
|
private $breaches = array();
|
|
|
|
|
|
|
|
public function collectData() {
|
|
|
|
|
2022-05-12 22:53:03 +03:00
|
|
|
$data = json_decode(getContents(self::API_URI . '/breaches'), true);
|
2019-06-01 13:06:58 +03:00
|
|
|
|
|
|
|
$breaches = array();
|
|
|
|
|
2022-05-12 22:53:03 +03:00
|
|
|
foreach($data as $breach) {
|
2019-06-01 13:06:58 +03:00
|
|
|
$item = array();
|
|
|
|
|
2022-05-12 22:53:03 +03:00
|
|
|
$pwnCount = number_format($breach['PwnCount']);
|
|
|
|
$item['title'] = $breach['Title'] . ' - '
|
|
|
|
. $pwnCount . ' breached accounts';
|
|
|
|
$item['dateAdded'] = $breach['AddedDate'];
|
|
|
|
$item['breachDate'] = $breach['BreachDate'];
|
|
|
|
$item['uri'] = self::URI . '/PwnedWebsites' . $breach['Name'];
|
2019-06-01 13:06:58 +03:00
|
|
|
|
2022-05-12 22:53:03 +03:00
|
|
|
$item['content'] = '<p>' . $breach['Description'] . '</p>';
|
2019-07-06 12:55:31 +03:00
|
|
|
$item['content'] .= '<p>' . $this->breachType($breach) . '</p>';
|
2019-06-01 13:06:58 +03:00
|
|
|
|
2022-05-12 22:53:03 +03:00
|
|
|
$breachDate = date('j F Y', strtotime($breach['BreachDate']));
|
|
|
|
$addedDate = date('j F Y', strtotime($breach['AddedDate']));
|
|
|
|
$compData = implode(', ', $breach['DataClasses']);
|
|
|
|
|
|
|
|
$item['content'] .= <<<EOD
|
|
|
|
<p>
|
|
|
|
<strong>Breach date:</strong> {$breachDate}<br>
|
|
|
|
<strong>Date added to HIBP:</strong> {$addedDate}<br>
|
|
|
|
<strong>Compromised accounts:</strong> {$pwnCount}<br>
|
|
|
|
<strong>Compromised data:</strong> {$compData}<br>
|
|
|
|
EOD;
|
|
|
|
$item['uid'] = $breach['Name'];
|
2019-06-01 13:06:58 +03:00
|
|
|
$this->breaches[] = $item;
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->orderBreaches();
|
|
|
|
$this->createItems();
|
|
|
|
}
|
|
|
|
|
2022-05-12 22:53:03 +03:00
|
|
|
private const BREACH_TYPES = array(
|
|
|
|
'IsVerified' => array(
|
|
|
|
false => 'Unverified breach, may be sourced from elsewhere'
|
|
|
|
),
|
|
|
|
'IsFabricated' => array(
|
|
|
|
true => 'Fabricated breach, likely not legitimate'
|
|
|
|
),
|
|
|
|
'IsSensitive' => array(
|
|
|
|
true => 'Sensitive breach, not publicly searchable'
|
|
|
|
),
|
|
|
|
'IsRetired' => array(
|
|
|
|
true => 'Retired breach, removed from system'
|
|
|
|
),
|
|
|
|
'IsSpamList' => array(
|
|
|
|
true => 'Spam list, used for spam marketing'
|
|
|
|
),
|
|
|
|
'IsMalware' => array(
|
|
|
|
true => 'Malware breach'
|
|
|
|
),
|
|
|
|
);
|
|
|
|
|
2019-07-06 12:55:31 +03:00
|
|
|
/**
|
|
|
|
* Extract data breach type(s)
|
|
|
|
*/
|
|
|
|
private function breachType($breach) {
|
|
|
|
|
|
|
|
$content = '';
|
|
|
|
|
2022-05-12 22:53:03 +03:00
|
|
|
foreach (self::BREACH_TYPES as $type => $message) {
|
|
|
|
if (isset($message[$breach[$type]])) {
|
|
|
|
$content .= $message[$breach[$type]] . '.<br>';
|
2019-07-06 12:55:31 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $content;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-06-01 13:06:58 +03:00
|
|
|
/**
|
|
|
|
* Order Breaches by date added or date breached
|
|
|
|
*/
|
|
|
|
private function orderBreaches() {
|
|
|
|
|
|
|
|
$sortBy = $this->getInput('order');
|
|
|
|
$sort = array();
|
|
|
|
|
|
|
|
foreach ($this->breaches as $key => $item) {
|
|
|
|
$sort[$key] = $item[$sortBy];
|
|
|
|
}
|
|
|
|
|
|
|
|
array_multisort($sort, SORT_DESC, $this->breaches);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Create items from breaches array
|
|
|
|
*/
|
|
|
|
private function createItems() {
|
|
|
|
|
2019-07-26 11:47:20 +03:00
|
|
|
$limit = $this->getInput('item_limit');
|
|
|
|
|
|
|
|
if ($limit < 1) {
|
|
|
|
$limit = 20;
|
|
|
|
}
|
|
|
|
|
2019-06-01 13:06:58 +03:00
|
|
|
foreach ($this->breaches as $breach) {
|
|
|
|
$item = array();
|
|
|
|
|
|
|
|
$item['title'] = $breach['title'];
|
|
|
|
$item['timestamp'] = $breach[$this->getInput('order')];
|
|
|
|
$item['uri'] = $breach['uri'];
|
|
|
|
$item['content'] = $breach['content'];
|
2022-05-12 22:53:03 +03:00
|
|
|
$item['uid'] = $breach['uid'];
|
2019-06-01 13:06:58 +03:00
|
|
|
|
|
|
|
$this->items[] = $item;
|
2019-07-26 11:47:20 +03:00
|
|
|
|
|
|
|
if (count($this->items) >= $limit) {
|
|
|
|
break;
|
|
|
|
}
|
2019-06-01 13:06:58 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|