示例#1
0
 /**
  * Wrapper for save data.
  *
  * @return bool
  */
 public function save()
 {
     /*
      * save evidence into table
      **/
     $this->evidence->save();
     /*
      * call saver
      **/
     $saver = new IncidentsSave();
     $saverResult = $saver->save($this->incidents, $this->evidence->id);
     /*
      * We've hit a snag, so we are gracefully killing ourselves
      * after we contact the admin about it. IncidentsSave should never
      * end with problems unless the mysql died while doing transactions
      **/
     if ($saverResult['errorStatus'] === true) {
         Log::error(get_class($saver) . ': ' . 'Saver has ended with errors ! : ' . $saverResult['errorMessage']);
         return false;
     }
     $linkedEvents = Event::where('evidence_id', '=', $this->evidence->id);
     if ($linkedEvents->count() == 0) {
         Log::info(get_class($saver) . ': ' . 'The evidence submitted was never linked to any ticket, thus removing it from the DB again');
         $this->evidence->forceDelete();
     }
     Log::info(get_class($saver) . ': ' . 'Saver has ended without errors');
     return true;
 }
示例#2
0
 /**
  * Execute the command
  *
  * @return void
  */
 public function handle()
 {
     Log::info('(JOB ' . getmypid() . ') ' . get_class($this) . ': ' . 'Queued worker is starting the processing of email file: ' . $this->filename);
     $filesystem = new Filesystem();
     $rawEmail = $filesystem->get($this->filename);
     $parsedMail = new MimeParser();
     $parsedMail->setText($rawEmail);
     // Sanity checks
     if (empty($parsedMail->getHeader('from')) || empty($parsedMail->getMessageBody())) {
         Log::warning('(JOB ' . getmypid() . ') ' . get_class($this) . ': ' . 'Missing e-mail headers from and/or empty body: ' . $this->filename);
         $this->alertAdmin();
         return;
     }
     // Ignore email from our own notification address to prevent mail loops
     if (preg_match('/' . Config::get('main.notifications.from_address') . '/', $parsedMail->getHeader('from'))) {
         Log::warning('(JOB ' . getmypid() . ') ' . get_class($this) . ': ' . 'Loop prevention: Ignoring email from self ' . Config::get('main.notifications.from_address'));
         $this->alertAdmin();
         return;
     }
     // Start with detecting valid ARF e-mail
     $attachments = $parsedMail->getAttachments();
     $arfMail = [];
     foreach ($attachments as $attachment) {
         if ($attachment->contentType == 'message/feedback-report') {
             $arfMail['report'] = $attachment->getContent();
         }
         if ($attachment->contentType == 'message/rfc822') {
             $arfMail['evidence'] = utf8_encode($attachment->getContent());
         }
         if ($attachment->contentType == 'text/plain') {
             $arfMail['message'] = $attachment->getContent();
         }
     }
     /*
      * Sometimes the mime header does not set the main message correctly. This is ment as a fallback and will
      * use the original content body (which is basicly the same mime element). But only fallback if we actually
      * have a RFC822 message with a feedback report.
      */
     if (empty($arfMail['message']) && isset($arfMail['report']) && isset($arfMail['evidence'])) {
         $arfMail['message'] = $parsedMail->getMessageBody();
     }
     // If we do not have a complete e-mail, then we empty the perhaps partially filled arfMail
     // which is useless, hence reset to false
     if (!isset($arfMail['report']) || !isset($arfMail['evidence']) || !isset($arfMail['message'])) {
         $arfMail = false;
     }
     // Asking ParserFactory for an object based on mappings, or die trying
     $parser = ParserFactory::create($parsedMail, $arfMail);
     if ($parser !== false) {
         $parserResult = $parser->parse();
     } else {
         Log::error('(JOB ' . getmypid() . ') ' . get_class($this) . ': ' . ': No parser available to handle message from : ' . $parsedMail->getHeader('from') . ' with subject: ' . $parsedMail->getHeader('subject'));
         $this->alertAdmin();
         return;
     }
     if ($parserResult !== false && $parserResult['errorStatus'] === true) {
         Log::error('(JOB ' . getmypid() . ') ' . get_class($parser) . ': ' . ': Parser has ended with fatal errors ! : ' . $parserResult['errorMessage']);
         $this->alertAdmin();
         return;
     } else {
         Log::info('(JOB ' . getmypid() . ') ' . get_class($parser) . ': ' . ': Parser completed with ' . $parserResult['warningCount'] . ' warnings and collected ' . count($parserResult['data']) . ' events to save');
     }
     if ($parserResult['warningCount'] !== 0 && Config::get('main.emailparser.notify_on_warnings') === true) {
         Log::error('(JOB ' . getmypid() . ') ' . get_class($this) . ': ' . 'Configuration has warnings set as critical and ' . $parserResult['warningCount'] . ' warnings were detected. Sending alert to administrator');
         $this->alertAdmin();
         return;
     }
     if (count($parserResult['data']) !== 0) {
         // Call validator
         $validator = new EventsValidate();
         $validatorResult = $validator->check($parserResult['data']);
         if ($validatorResult['errorStatus'] === true) {
             Log::error('(JOB ' . getmypid() . ') ' . get_class($validator) . ': ' . 'Validator has ended with errors ! : ' . $validatorResult['errorMessage']);
             $this->alertAdmin();
             return;
         } else {
             Log::info('(JOB ' . getmypid() . ') ' . get_class($validator) . ': ' . 'Validator has ended without errors');
         }
         /**
          * save evidence into table
          **/
         $evidence = new Evidence();
         $evidence->filename = $this->filename;
         $evidence->sender = $parsedMail->getHeader('from');
         $evidence->subject = $parsedMail->getHeader('subject');
         $evidence->save();
         /**
          * call saver
          **/
         $saver = new EventsSave();
         $saverResult = $saver->save($parserResult['data'], $evidence->id);
         /**
          * We've hit a snag, so we are gracefully killing ourselves
          * after we contact the admin about it. EventsSave should never
          * end with problems unless the mysql died while doing transactions
          **/
         if ($saverResult['errorStatus'] === true) {
             Log::error('(JOB ' . getmypid() . ') ' . get_class($saver) . ': ' . 'Saver has ended with errors ! : ' . $saverResult['errorMessage']);
             $this->alertAdmin();
             return;
         } else {
             Log::info('(JOB ' . getmypid() . ') ' . get_class($saver) . ': ' . 'Saver has ended without errors');
         }
     } else {
         Log::warning('(JOB ' . getmypid() . ') ' . get_class($this) . ': ' . 'Parser did not return any events therefore skipping validation and saving a empty event set');
     }
     Log::info('(JOB ' . getmypid() . ') ' . get_class($this) . ': ' . 'Queued worker has ended the processing of email file: ' . $this->filename);
 }
 /**
  * @param $ticket
  * @param $account
  */
 private function replayTicket($ticket, $account)
 {
     // Create the ticket as usual
     $newTicket = $this->createTicket($ticket, $account);
     // Now this is the little magic, we need to calculate the offset and make sure that the first
     // and lastseen moments exactly match and the increments between those events are within that
     // same timeframe, but NOT duplicate.
     $firstSeen = (int) $ticket->FirstSeen;
     $lastSeen = (int) $ticket->LastSeen;
     $elapsed = $lastSeen - $firstSeen;
     $step = (int) round($elapsed / $ticket->ReportCount);
     $offset = ['first' => $firstSeen, 'last' => $lastSeen, 'elapsed' => $elapsed, 'step' => $step];
     for ($counter = 0; $counter <= $ticket->ReportCount; $counter++) {
         $offset[$counter] = $firstSeen + $counter * $step;
     }
     // Make sure we end at the right point in time
     end($offset);
     $key = key($offset);
     $offset[$key] = $lastSeen;
     // Now recreate all the events
     for ($counter = 0; $counter <= $ticket->ReportCount; $counter++) {
         // Build new evidence file and write the evidence into the archive
         $evidence = new EvidenceSave();
         $evidenceData = ['createdBy' => '*****@*****.**', 'receivedOn' => time(), 'submittedData' => json_decode(json_encode($ticket), true), 'attachments' => []];
         if (!empty($attachment)) {
             $evidenceData['attachments'][0] = $attachment;
         }
         $evidenceFile = $evidence->save(json_encode($evidenceData));
         // Save the file reference into the database
         $evidenceSave = new Evidence();
         $evidenceSave->filename = $evidenceFile;
         $evidenceSave->sender = '*****@*****.**';
         $evidenceSave->subject = 'Migrated evidence with a little magic';
         $evidenceSave->save();
         // Write the event
         $newEvent = new Event();
         $newEvent->evidence_id = $evidenceSave->id;
         $newEvent->information = $ticket->Information;
         $newEvent->source = $ticket->Source;
         $newEvent->ticket_id = $newTicket->id;
         $newEvent->timestamp = $offset[$counter];
         // Validate the model before saving
         $validator = Validator::make(json_decode(json_encode($newEvent), true), Event::createRules());
         if ($validator->fails()) {
             $this->error('DevError: Internal validation failed when saving the Event object ' . implode(' ', $validator->messages()->all()));
             $this->exception();
         }
         $newEvent->save();
     }
 }
示例#4
0
 /**
  * Execute the command.
  *
  * @return void
  */
 public function handle()
 {
     Log::info(get_class($this) . ': Queued worker is starting the processing of email file: ' . $this->filename);
     $filesystem = new Filesystem();
     $rawEmail = $filesystem->get($this->filename);
     $parsedMail = new MimeParser();
     $parsedMail->setText($rawEmail);
     // Sanity checks
     if (empty($parsedMail->getHeader('from')) || empty($parsedMail->getMessageBody())) {
         Log::warning(get_class($this) . 'Validation failed on: ' . $this->filename);
         $this->exception();
     }
     // Ignore email from our own notification address to prevent mail loops
     if (preg_match('/' . Config::get('main.notifications.from_address') . '/', $parsedMail->getHeader('from'))) {
         Log::warning(get_class($this) . 'Loop prevention: Ignoring email from self ' . Config::get('main.notifications.from_address'));
         $this->exception();
     }
     // Start with detecting valid ARF e-mail
     $attachments = $parsedMail->getAttachments();
     $arfMail = [];
     foreach ($attachments as $attachment) {
         if ($attachment->contentType == 'message/feedback-report') {
             $arfMail['report'] = $attachment->getContent();
         }
         if ($attachment->contentType == 'message/rfc822') {
             $arfMail['evidence'] = $attachment->getContent();
         }
         if ($attachment->contentType == 'text/plain') {
             $arfMail['message'] = $attachment->getContent();
         }
     }
     // If we do not have a complete e-mail, then we empty the perhaps partially filled arfMail
     // which is useless, hence reset to false
     if (!isset($arfMail['report']) || !isset($arfMail['evidence']) || !isset($arfMail['message'])) {
         $arfMail = false;
     }
     // Asking GetParser for an object based on mappings, or die trying
     $parser = GetParser::object($parsedMail, $arfMail);
     $result = false;
     $events = false;
     if ($parser !== false) {
         $result = $parser->parse();
     } else {
         Log::error(get_class($this) . ': Unable to handle message from: ' . $parsedMail->getHeader('from') . ' with subject: ' . $parsedMail->getHeader('subject'));
         $this->exception();
     }
     if ($result !== false && $result['errorStatus'] !== true) {
         Log::info(get_class($parser) . ': Parser as ended without errors. Collected ' . count($result['data']) . ' events to save');
         $events = $result['data'];
     } else {
         Log::error(get_class($parser) . ': Parser as ended with errors ! : ' . $result['errorMessage']);
         $this->exception();
     }
     // call validater
     $validator = new EventsValidate($events);
     $return = $validator->handle();
     if ($return['errorStatus'] === false) {
         Log::error(get_class($validator) . ': Validator as ended with errors ! : ' . $result['errorMessage']);
         $this->exception();
     } else {
         Log::info(get_class($validator) . ': Validator as ended without errors');
     }
     // save evidence into table
     $evidence = new Evidence();
     $evidence->filename = $this->filename;
     $evidence->sender = $parsedMail->getHeader('from');
     $evidence->subject = $parsedMail->getHeader('subject');
     $evidence->save();
     // call saver
     $saver = new EventsSave($events, $evidence->id);
     $return = $saver->handle();
     if ($return['errorStatus'] === false) {
         Log::error(get_class($saver) . ': Saver as ended with errors ! : ' . $result['errorMessage']);
         $this->exception();
     } else {
         Log::info(get_class($saver) . ': Saver as ended without errors');
     }
 }
示例#5
0
 /**
  * Execute the command
  *
  * @return boolean
  */
 public function handle()
 {
     Log::info(get_class($this) . ': ' . 'Queued worker is starting the collector: ' . $this->collector);
     $collector = collectorFactory::create($this->collector);
     if (!$collector) {
         Log::error("The requested collector {$this->collector} could not be started check logs for PID:" . getmypid());
         $this->exception();
     }
     $collectorResult = $collector->parse();
     if ($collectorResult['errorStatus'] == true) {
         Log::error("The requested collector {$this->collector} returned an error. check logs for PID:" . getmypid());
         $this->exception();
     }
     if (count($collectorResult['data']) !== 0) {
         // Call validator
         $validator = new EventsValidate();
         $validatorResult = $validator->check($collectorResult['data']);
         if ($validatorResult['errorStatus'] === true) {
             Log::error(get_class($validator) . ': ' . 'Validator has ended with errors ! : ' . $validatorResult['errorMessage']);
             $this->exception();
             return;
         } else {
             Log::info(get_class($validator) . ': ' . 'Validator has ended without errors');
         }
         /**
          * save evidence onto disk
          */
         $filesystem = new Filesystem();
         $datefolder = Carbon::now()->format('Ymd');
         $path = storage_path() . '/mailarchive/' . $datefolder . '/';
         $file = Uuid::generate(4) . '.eml';
         $filename = $path . $file;
         if (!$filesystem->isDirectory($path)) {
             // If a datefolder does not exist, then create it or die trying
             if (!$filesystem->makeDirectory($path)) {
                 Log::error(get_class($this) . ': ' . 'Unable to create directory: ' . $path);
                 $this->exception();
             }
             chown($path, 'abuseio');
             chgrp($path, 'abuseio');
         }
         if ($filesystem->isFile($filename)) {
             Log::error(get_class($this) . ': ' . 'File aready exists: ' . $filename);
             $this->exception();
         }
         if ($filesystem->put($filename, json_encode(['collectorName' => $this->collector, 'collectorData' => $collectorResult])) === false) {
             Log::error(get_class($this) . ': ' . 'Unable to write file: ' . $filename);
             $this->exception();
         }
         chown($path . $filename, 'abuseio');
         chgrp($path . $filename, 'abuseio');
         /**
          * save evidence into table
          **/
         $evidence = new Evidence();
         $evidence->filename = $filename;
         $evidence->sender = 'abuse@localhost';
         $evidence->subject = "CLI Collector {$this->collector}";
         $evidence->save();
         /**
          * call saver
          **/
         $saver = new EventsSave();
         $saverResult = $saver->save($collectorResult['data'], $evidence->id);
         /**
          * We've hit a snag, so we are gracefully killing ourselves
          * after we contact the admin about it. EventsSave should never
          * end with problems unless the mysql died while doing transactions
          **/
         if ($saverResult['errorStatus'] === true) {
             Log::error(get_class($saver) . ': ' . 'Saver has ended with errors ! : ' . $saverResult['errorMessage']);
             $this->exception();
             return;
         } else {
             Log::info(get_class($saver) . ': ' . 'Saver has ended without errors');
         }
     } else {
         Log::warning(get_class($this) . ': ' . 'Collector did not return any events therefore skipping validation and saving a empty event set');
     }
     Log::info(get_class($this) . ': ' . 'Queued worker has ended the processing of collector: ' . $this->collector);
 }