<?php
namespace App\Controller;
use App\Entity\DarkOwl;
use App\Entity\Domain;
use App\Entity\ExposedIp;
use App\Entity\ExposedSubDomain;
use App\Entity\LeakedPassword;
use App\Entity\Organisation;
use App\Entity\User;
use App\Entity\Vulnerability;
use App\Entity\VulnerabilityLevel;
use App\Manager\LeakedPasswordManager;
use App\Repository\CronLogRepository;
use App\Repository\DarkOwlRepository;
use App\Repository\DomainRepository;
use App\Repository\ExposedIpRepository;
use App\Repository\ExposedSubDomainRepository;
use App\Repository\LeakedPasswordRepository;
use App\Repository\VulnerabilityRepository;
use App\Service\Misc;
use App\Service\ScoreService;
use App\Service\Stats;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\HeaderUtils;
class ClientController extends AbstractController
{
/**
* @var Stats $stats
*/
private $stats;
/**
* @var Misc $misc
*/
private $misc;
public function __construct(Stats $stats, Misc $misc)
{
$this->stats = $stats;
$this->misc = $misc;
}
/**
* @Route("/", name="home")
*/
public function index(DomainRepository $domainRepository)
{
if ($this->getUser()->isAdmin()) {
return $this->redirectToRoute('admin_dashboard');
}
/**
* @var User $user
*/
$user = $this->getUser();
$organisation = $this->misc->getUserOrganisation($user);
$leakedPassword = $this->stats->getLeakedPasswordStats($organisation);
$exposedSubDomain = $this->stats->getExposedDomainStats($organisation);
$exposedIp = $this->stats->getExposedIpStats($organisation);
$vulnerability = $this->stats->getVulneranilityStats($organisation);
$score = null;
/**
* @var Domain $domain
*/
foreach ($domainRepository->findDomainsByOrga($organisation) as $domain) {
$score = $domain->getLastScore();
}
$data = [];
if ($score) {
$value = $score->getScore();
if ($value == 0) {
$data = [
"class" => "none",
"label" => "Info",
];
} elseif ($value >= 0.1 && $value < 4) {
$data = [
"class" => "low",
"label" => "Low",
];
} elseif ($value >= 4 && $value < 7) {
$data = [
"class" => "medium",
"label" => "Medium",
];
} elseif ($value >= 7 && $value < 9) {
$data = [
"class" => "high",
"label" => "High",
];
} elseif ($value >= 9 && $value <= 10) {
$data = [
"class" => "critical",
"label" => "Critical",
];
}
}
return $this->render('client/index.html.twig', [
'leakedPassword' => $leakedPassword,
'exposedDomain' => $exposedSubDomain,
'exposedIp' => $exposedIp,
'vulnerability' => $vulnerability,
'score' => $score,
'data' => $data,
'organisation' => $organisation,
'sub' => $this->misc->getActifSubsription($organisation),
]);
}
/**
* @IsGranted("leaked-passwords")
* @Route("/leaked-passwords", name="leakedpassowrds")
*/
public function leakedPassword(
Request $request,
LeakedPasswordRepository $leakedPasswordRepository,
ScoreService $service
)
{
/**
* @var User $user
*/
$user = $this->getUser();
$organisation = $this->misc->getUserOrganisation($user);
$today = $request->query->get('today', false) === "1";
$leakedPasswords = $leakedPasswordRepository->findLeakedPasswordsByDate(
$organisation,
$today ? date('Y-m-d') : null
);
return $this->render('client/leakedpasswords.html.twig', [
'leakedpasswords' => $leakedPasswords,
]);
}
/**
* @IsGranted("leaked-passwords")
* @Route("/leaked-password/{id}/notify", name="leakedpassowrd_notify")
*/
public function notifyLeakedPassword(
LeakedPassword $leakedPassword,
LeakedPasswordManager $leakedPasswordManager,
Request $request
): Response {
$notify = filter_var($request->query->get('notify', false), FILTER_VALIDATE_BOOLEAN);
$leakedPasswordManager->notifyLeakedPassword(
$leakedPassword,
$this->getUser(),
$notify
);
return new JsonResponse(['response' => 'ok']);
}
/**
* @IsGranted("exposed-sub-domains")
* @Route("/exposed-domains/{id}/normal", name="normal_exposed_domain")
*/
public function normalExposedDomain(
ExposedSubDomain $exposedSubDomain,
Request $request
): Response {
$user = $this->getUser();
$status = filter_var($request->query->get('status', false), FILTER_VALIDATE_BOOLEAN);
if ($exposedSubDomain->getDomain()->getOrganisation()->getId() === $this->misc->getUserOrganisation($user)->getId()) {
$exposedSubDomain->setIsNormal($status);
$this->getDoctrine()->getManager()->flush();
}
return new JsonResponse(['response' => 'ok']);
}
/**
* @IsGranted("exposed-sub-domains")
* @Route("/exposed-subdomains", name="exposedsubdomains")
*/
public function exposedSubDomains(Request $request, ExposedSubDomainRepository $exposedSubDomainRepository)
{
/**
* @var User $user
*/
$user = $this->getUser();
$organisation = $this->misc->getUserOrganisation($user) ;
return $this->render('client/exposedsubdomains.html.twig', [
'subdomains' => $exposedSubDomainRepository->findExposedSubDomainsByOrganisationAndDate($organisation),
'today' => $request->query->get('today', false) === "1"
]);
}
/**
* @IsGranted("exposed-ips-and-ports")
* @Route("/exposed-ips-ports/{id}/normal", name="normal_exposed_ip")
*/
public function normalExposedIp(
ExposedIp $exposedIp,
Request $request
): Response {
$user = $this->getUser();
$status = filter_var($request->query->get('normal', false), FILTER_VALIDATE_BOOLEAN);
if ($exposedIp->getOrganisation()->getId() === $this->misc->getUserOrganisation($user)->getId()) {
$exposedIp->setIsNormal(!$status);
$this->getDoctrine()->getManager()->flush();
}
return new JsonResponse([
'response' => 'ok',
'class' => !$status ? 'normal' : 'abnormal',
'html' => !$status ? 'Normal' : 'Abnormal',
]);
}
/**
* @IsGranted("exposed-ips-and-ports")
* @Route("/exposed-ips-ports", name="exposedipsports")
*/
public function exposedIpsPorts(ExposedIpRepository $exposedIpRepository)
{
/**
* @var User $user
*/
$user = $this->getUser();
/**
* @var Organisation $organisation
*/
$organisation = $this->misc->getUserOrganisation($user);
return $this->render(
'client/exposedipsports.html.twig',
[
"ips" => $exposedIpRepository->findExposedIpsByOrgaAndDate($organisation)
]
);
}
/**
* @IsGranted("potential-vulnerabilities")
* @Route("/potential-vulnerabilities", name="potentialvulnerabilities")
*/
public function potentialVulnerabilities(
Request $request,
CronLogRepository $cronLogRepository,
DomainRepository $domainRepository
) {
$today = $request->query->get('today', false) === "1";
/**
* @var User $user
*/
$user = $this->getUser();
$organisation = $this->misc->getUserOrganisation($user);
$lastExec = $cronLogRepository
->findOneBy(
['organisation' => $organisation, 'commandName' => 'app:processing-organization'],
['id' => 'DESC']
);
$domains = [];
/**
* @var Domain $domain
*/
foreach ($domainRepository->findDomainsByOrga($organisation) as $domain) {
if (!isset($domains[$domain->getUrl()])) {
$domains[$domain->getUrl()] = [];
}
/**
* @var Vulnerability $vul
*/
foreach ($domain->getVulnerabilities() as $vul) {
if ($today && $vul->getCreatedAt()->format('Y-m-d') != date('Y-m-d')) {
continue;
}
$key = $this->getUrl($vul->getMetadata()) ;
if (!isset($domains[$key][$vul->getLevel()->getSlug()])) {
$domains[$key][$vul->getLevel()->getSlug()] = [];
}
$domains[$key][$vul->getLevel()->getSlug()] = $vul->getLevel();
}
}
return $this->render('client/potentialvulnerabilities.html.twig', [
'domains' => $domains,
'today' => $today,
'lastExec' => $lastExec,
]);
}
/**
* @IsGranted("potential-vulnerabilities")
* @Route("/get-vulnerabilities", name="getvulnerabilities")
*/
public function getVulnerabilities(
Request $request,
VulnerabilityRepository $vulnerabilityRepository
) {
/**
* @var User $user
*/
$user = $this->getUser();
$domain_url = $request->query->get('domain');
$level_id = $request->query->get('level', \false);
$today = $request->query->get('today', \false);
$vuls = $vulnerabilityRepository->findVulnerabilitiesByDomainAndLevel($domain_url, $level_id, $today);
if (!empty($vuls)) {
$v = $vuls[0];
if ($v->getDomain()->getOrganisation()->getId() !== $this->misc->getUserOrganisation($user)->getId()) {
$vuls = [];
}
}
$levels = [];
foreach ($vuls as $vul) {
$levels[] = $vul->getLevel()->getSlug();
}
return $this->render('client/tablevulnerabilities.html.twig', [
'vuls' => $vuls,
'levels' => \array_unique($levels),
]);
}
/**
* @Route("/notifications", name="notifications")
*/
public function notifications()
{
/**
* @var User $user
*/
$user = $this->getUser();
$em = $this->getDoctrine()->getManager();
$leakedPassword = $em->getRepository(LeakedPassword::class)->findLeakedPasswordsByDate(
$this->misc->getUserOrganisation($user),
date('Y-m-d'),
'%Y-%m-%d'
);
$exposedSubDomain = $em->getRepository(ExposedSubDomain::class)->findExposedSubDomainsByOrganisationAndDate(
$this->misc->getUserOrganisation($user),
date('Y-m-d'),
'%Y-%m-%d'
);
$vulnerability = $em->getRepository(Vulnerability::class)->findVulnerabilitiesByOrganisationAndDate(
$this->misc->getUserOrganisation($user),
date('Y-m-d'),
'%Y-%m-%d'
);
$count = 0;
if (count($leakedPassword)>0) {
$count++;
}
if (count($exposedSubDomain)>0) {
$count++;
}
if (count($vulnerability)>0) {
$count++;
}
return $this->render('partials/customer/notifications.html.twig', [
'count' => $count,
'leakedPassword' => count($leakedPassword),
'exposedSubDomain' => count($exposedSubDomain),
'vulnerability' => count($vulnerability),
]);
}
/**
* @IsGranted("dark-web-exposure")
* @Route("/dark-web-exposure", name="darkwebexposure")
*/
public function darkwebexposure(Request $request, DarkOwlRepository $darkOwlRepository)
{
/**
* @var User $user
*/
$user = $this->getUser();
$datas = $darkOwlRepository->findByOrganisation($this->misc->getUserOrganisation($user));
return $this->render('client/darkwebexposure.html.twig', [
'darkOwls' => $datas
]);
}
/**
* @IsGranted("dark-web-exposure")
* @Route("/dark-web-exposure/{documentID}", name="darkwebexposure-details")
*/
public function darkwebexposureDetails(Request $request, DarkOwl $darkOwl)
{
return $this->render('client/darkwebexposure-details.html.twig', [
'darkowl' => $darkOwl
]);
}
/**
* @IsGranted("dark-web-exposure")
* @Route("/dark-web-exposure/{documentID}/download", name="darkwebexposure-download")
*/
public function downloadDarkwebexposureDetails(Request $request, DarkOwl $darkOwl)
{
$body = \str_replace('\n', "\n", $darkOwl->getBody());
$filename = 'cypherleak-'.$darkOwl->getDocumentID().'.txt';
$filepath = sys_get_temp_dir().\DIRECTORY_SEPARATOR.$filename;
$file = \fopen($filepath, 'w');
\fwrite($file, $body);
\fclose($file);
$response = new BinaryFileResponse($filepath);
$disposition = HeaderUtils::makeDisposition(
HeaderUtils::DISPOSITION_ATTACHMENT,
$filename
);
$response->headers->set('Content-Disposition', $disposition);
return $response;
}
private function getUrl($url)
{
$parts = \explode('/', $url);
return count($parts)>= 3 ? $parts[0].'//'.$parts[2] : $url;
}
}