mirror of https://github.com/MISP/MISP
Implemented file-upload of attachment or password protected
malware-samples. Base code contributed by Andrzej Dereszowskipull/61/head
parent
da48ad4769
commit
da2687846b
|
@ -13,3 +13,4 @@
|
|||
/README
|
||||
/app/tmp/sessions/sess_*
|
||||
/app/tmp/logs/*.log
|
||||
/app/files/*
|
||||
|
|
|
@ -67,15 +67,15 @@ class EventsController extends AppController {
|
|||
/**
|
||||
* view method
|
||||
*
|
||||
* @param string $id
|
||||
* @param int $id
|
||||
* @return void
|
||||
*/
|
||||
public function view($id = null) {
|
||||
$this->Event->id = $id;
|
||||
$this->Event->id = $id;
|
||||
if (!$this->Event->exists()) {
|
||||
throw new NotFoundException(__('Invalid event'));
|
||||
}
|
||||
$this->set('event', $this->Event->read(null, $id));
|
||||
$this->set('event', $this->Event->read(null, $id));
|
||||
$this->set('relatedEvents', $this->Event->getRelatedEvents());
|
||||
|
||||
$related_signatures = array();
|
||||
|
@ -85,6 +85,7 @@ class EventsController extends AppController {
|
|||
}
|
||||
$this->set('relatedSignatures', $related_signatures);
|
||||
|
||||
$this->set('categories', $this->Signature->validate['category']['rule'][1]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -115,7 +116,7 @@ class EventsController extends AppController {
|
|||
/**
|
||||
* edit method
|
||||
*
|
||||
* @param string $id
|
||||
* @param int $id
|
||||
* @return void
|
||||
*/
|
||||
public function edit($id = null) {
|
||||
|
@ -162,7 +163,7 @@ class EventsController extends AppController {
|
|||
/**
|
||||
* delete method
|
||||
*
|
||||
* @param string $id
|
||||
* @param int $id
|
||||
* @return void
|
||||
*/
|
||||
public function delete($id = null) {
|
||||
|
@ -334,7 +335,6 @@ class EventsController extends AppController {
|
|||
/**
|
||||
* Send out an contact email to the person who posted the event.
|
||||
* Users with a GPG key will get the mail encrypted, other users will get the mail unencrypted
|
||||
* @todo allow the user to enter a comment in the contact email.
|
||||
*/
|
||||
public function contact($id = null) {
|
||||
$this->Event->id = $id;
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
<?php
|
||||
App::uses('AppController', 'Controller');
|
||||
App::uses('Folder', 'Utility');
|
||||
App::uses('File', 'Utility');
|
||||
|
||||
/**
|
||||
* Signatures Controller
|
||||
*
|
||||
|
@ -10,6 +13,11 @@ class SignaturesController extends AppController {
|
|||
public $components = array('Security');
|
||||
|
||||
function beforeFilter() {
|
||||
// permit reuse of CSRF tokens on the search page.
|
||||
if ('search' == $this->request->params['action']) {
|
||||
$this->Security->csrfUseOnce = false;
|
||||
}
|
||||
|
||||
// These variables are required for every view
|
||||
$this->set('me', $this->Auth->user());
|
||||
$this->set('isAdmin', $this->_isAdmin());
|
||||
|
@ -27,7 +35,7 @@ class SignaturesController extends AppController {
|
|||
return $this->Signature->isOwnedByOrg($signatureid, $this->Auth->user('org'));
|
||||
}
|
||||
// Only on own events for these actions
|
||||
if (in_array($this->action, array('add'))) {
|
||||
if (in_array($this->action, array('add', 'add_attachment'))) {
|
||||
$this->loadModel('Event');
|
||||
$eventid = $this->request->params['pass'][0];
|
||||
return $this->Event->isOwnedByOrg($eventid, $this->Auth->user('org'));
|
||||
|
@ -62,6 +70,15 @@ class SignaturesController extends AppController {
|
|||
// throw new UnauthorizedException('You can only add signatures for your own organisation.');
|
||||
// }
|
||||
|
||||
// Give error if someone tried to submit a signature with attachment or malware-sample type.
|
||||
// FIXME this is bad ... it should rather by a messagebox or should be filtered out on the view level
|
||||
if('attachment' == $this->request->data['Signature']['type'] ||
|
||||
'malware-sample' == $this->request->data['Signature']['type']) {
|
||||
$this->Session->setFlash(__('Attribute has not been added: attachments are added by "Add attachment" button', true), 'default', array(), 'error');
|
||||
$this->redirect(array('controller' => 'events', 'action' => 'view', $old_signature['Event']['id']));
|
||||
}
|
||||
|
||||
|
||||
// remove the alerted flag from the event
|
||||
$this->Event->id = $this->request->data['Signature']['event_id'];
|
||||
$this->Event->saveField('alerted', 0);
|
||||
|
@ -69,7 +86,7 @@ class SignaturesController extends AppController {
|
|||
//
|
||||
// multiple signatures in batch import
|
||||
//
|
||||
if ($this->data['Signature']['batch_import'] == 1) {
|
||||
if ($this->request->data['Signature']['batch_import'] == 1) {
|
||||
// make array from value field
|
||||
$signatures = explode("\n", $this->request->data['Signature']['value']);
|
||||
|
||||
|
@ -129,6 +146,152 @@ class SignaturesController extends AppController {
|
|||
$types = $this->Signature->validate['type']['rule'][1];
|
||||
$types = $this->_arrayToValuesIndexArray($types);
|
||||
$this->set('types',compact('types'));
|
||||
// combobos for categories
|
||||
$categories = $this->Signature->validate['category']['rule'][1];
|
||||
$categories = $this->_arrayToValuesIndexArray($categories);
|
||||
$this->set('categories',compact('categories'));
|
||||
}
|
||||
|
||||
|
||||
public function download($id = null) {
|
||||
$this->Signature->id = $id;
|
||||
if (!$this->Signature->exists()) {
|
||||
throw new NotFoundException(__('Invalid signature'));
|
||||
}
|
||||
|
||||
$this->Signature->read();
|
||||
$file = new File(APP.DS."files".DS.$this->Signature->data['Signature']['event_id'].DS.$this->Signature->data['Signature']['id']);
|
||||
$filename = '';
|
||||
if('attachment' == $this->Signature->data['Signature']['type']) {
|
||||
$filename= $this->Signature->data['Signature']['value'];
|
||||
} elseif ('malware-sample'== $this->Signature->data['Signature']['type']) {
|
||||
$filename_hash = explode('|', $this->Signature->data['Signature']['value']);
|
||||
$filename = $filename_hash[0].".zip";
|
||||
} else {
|
||||
throw new NotFoundException(__('Signature not an attachment or malware-sample'));
|
||||
}
|
||||
|
||||
$file_ext = explode(".", $filename);
|
||||
$this->viewClass = 'Media';
|
||||
$params = array(
|
||||
'id' => $file->path,
|
||||
'name' => $filename,
|
||||
'download' => true,
|
||||
'path' => DS
|
||||
);
|
||||
$this->set($params);
|
||||
}
|
||||
|
||||
/**
|
||||
* add_attachment method
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function add_attachment($event_id = null) {
|
||||
if ($this->request->is('post')) {
|
||||
$this->loadModel('Event');
|
||||
// // Replaced by isAuthorized
|
||||
// // // only own signatures
|
||||
// // $this->Event->recursive = 0;
|
||||
// // $event = $this->Event->findById($this->request->data['Signature']['event_id']);
|
||||
// // if (!$this->_isAdmin() && $this->Auth->user('org') != $event['Event']['org']) {
|
||||
// // throw new UnauthorizedException('You can only add signatures for your own organisation.');
|
||||
// // }
|
||||
|
||||
// Check if there were problems with the file upload
|
||||
$filename = Sanitize::HTML($this->request->data['Signature']['value']['name']);
|
||||
$tmpfile = new File($this->request->data['Signature']['value']['tmp_name']);
|
||||
if ((isset($this->request->data['Signature']['value']['error']) && $this->request->data['Signature']['value']['error'] == 0) ||
|
||||
(!empty( $this->request->data['Signature']['value']['tmp_name']) && $this->request->data['Signature']['value']['tmp_name'] != 'none')
|
||||
) {
|
||||
if(!is_uploaded_file($tmpfile->path))
|
||||
throw new InternalErrorException('PHP says file was not uploaded. Are you attacking me?');
|
||||
} else {
|
||||
$this->Session->setFlash(__('There was a problem to upload the file.', true), 'default', array(), 'error');
|
||||
$this->redirect(array('controller' => 'events', 'action' => 'view', $this->request->data['Signature']['event_id']));
|
||||
}
|
||||
|
||||
// remove the alerted flag from the event
|
||||
$this->Event->id = $this->request->data['Signature']['event_id'];
|
||||
$this->Event->saveField('alerted', 0);
|
||||
|
||||
// save the file-info in the database
|
||||
$this->Signature->create();
|
||||
if($this->request->data['Signature']['malware']) {
|
||||
$this->request->data['Signature']['type'] = "malware-sample";
|
||||
$this->request->data['Signature']['value'] = $filename.'|'.$tmpfile->md5(); // TODO gives problems with bigger files
|
||||
}
|
||||
else {
|
||||
$this->request->data['Signature']['type'] = "attachment";
|
||||
$this->request->data['Signature']['value'] = $filename;
|
||||
}
|
||||
$this->request->data['Signature']['uuid'] = String::uuid();
|
||||
$this->request->data['Signature']['to_ids'] = 0; // LATER permit user to send this to IDS
|
||||
$this->request->data['Signature']['batch_import'] = 0;
|
||||
|
||||
if ($this->Signature->save($this->request->data)) {
|
||||
// signature saved correctly in the db
|
||||
} else {
|
||||
$this->Session->setFlash(__('The attribute could not be saved. Did you already upload this file?'));
|
||||
$this->redirect(array('controller' => 'events', 'action' => 'view', $this->request->data['Signature']['event_id']));
|
||||
}
|
||||
|
||||
// no errors in file upload, entry already in db, now move the file where needed and zip it if required.
|
||||
// no sanitization is required on the filename, path or type as we save
|
||||
// create directory structure
|
||||
$root_dir = APP.DS."files".DS.$this->request->data['Signature']['event_id'];
|
||||
$dir = new Folder($root_dir, true);
|
||||
// move the file to the correct location
|
||||
$destpath = $root_dir.DS.$this->Signature->id; // id of the new signature in the database
|
||||
$file = new File ($destpath);
|
||||
$zipfile = new File ($destpath.'.zip');
|
||||
$file_in_zip = new File($root_dir.DS.$filename); // FIXME do sanitization of the filename
|
||||
|
||||
if($file->exists() || $zipfile->exists() || $file_in_zip->exists()) {
|
||||
// this should never happen as the signature id should be unique
|
||||
$this->Session->setFlash(__('Attachment with this name already exist in this event.', true), 'default', array(), 'error');
|
||||
// remove the entry from the database
|
||||
$this->Signature->delete();
|
||||
$this->redirect(array('controller' => 'events', 'action' => 'view', $this->request->data['Signature']['event_id']));
|
||||
}
|
||||
if(!move_uploaded_file($tmpfile->path, $file->path)) {
|
||||
$this->Session->setFlash(__('Problem with uploading attachment. Cannot move it to its final location.', true), 'default', array(), 'error');
|
||||
// remove the entry from the database
|
||||
$this->Signature->delete();
|
||||
$this->redirect(array('controller' => 'events', 'action' => 'view', $this->request->data['Signature']['event_id']));
|
||||
}
|
||||
|
||||
// zip and password protect the malware files
|
||||
if($this->request->data['Signature']['malware']) {
|
||||
// TODO check if CakePHP has no easy/safe wrapper to execute commands
|
||||
$exec_retval = ''; $exec_output = array();
|
||||
rename($file->path, $file_in_zip->path); // FIXME prevent any attacks
|
||||
exec("zip -j -P infected ".$zipfile->path.' "'.addslashes($file_in_zip->path).'"', $exec_output, $exec_retval);
|
||||
if($exec_retval != 0) { // not EXIT_SUCCESS
|
||||
$this->Session->setFlash(__('Problem with zipping the attachment. Please report to administrator. ', true), 'default', array(), 'error');
|
||||
// remove the entry from the database
|
||||
$this->Signature->delete();
|
||||
$file_in_zip->delete();
|
||||
$file->delete();
|
||||
$this->redirect(array('controller' => 'events', 'action' => 'view', $this->request->data['Signature']['event_id']));
|
||||
};
|
||||
$file_in_zip->delete(); // delete the original not-zipped-file
|
||||
rename($zipfile->path, $file->path); // rename the .zip to .nothing
|
||||
}
|
||||
|
||||
// everything is done, now redirect to event view
|
||||
$this->Session->setFlash(__('The attachment has been uploaded'));
|
||||
$this->redirect(array('controller' => 'events', 'action' => 'view', $this->request->data['Signature']['event_id']));
|
||||
|
||||
} else {
|
||||
// set the event_id in the form
|
||||
$this->request->data['Signature']['event_id'] = $event_id;
|
||||
}
|
||||
|
||||
// combobos for categories
|
||||
$categories = $this->Signature->validate['category']['rule'][1];
|
||||
$categories = $this->_arrayToValuesIndexArray($categories);
|
||||
$this->set('categories',compact('categories'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -148,6 +311,19 @@ class SignaturesController extends AppController {
|
|||
// if (!$this->_isAdmin() && $this->Auth->user('org') != $this->Signature->data['Event']['org']) {
|
||||
// throw new UnauthorizedException('You can only edit signatures from your own organisation.');
|
||||
// }
|
||||
|
||||
$this->Signature->read();
|
||||
if('attachment' == $this->Signature->data['Signature']['type'] ||
|
||||
'malware-sample'== $this->Signature->data['Signature']['type'] ) {
|
||||
$this->set('attachment', true);
|
||||
// FIXME we should ensure value cannot be changed here and not only on a view level (because of the associated file)
|
||||
// $this->Session->setFlash(__('You cannot edit attachment attributes.', true), 'default', array(), 'error');
|
||||
// $this->redirect(array('controller' => 'events', 'action' => 'view', $old_signature['Event']['id']));
|
||||
} else {
|
||||
$this->set('attachment', false);
|
||||
}
|
||||
|
||||
|
||||
if ($this->request->is('post') || $this->request->is('put')) {
|
||||
|
||||
if ($this->Signature->save($this->request->data)) {
|
||||
|
@ -160,13 +336,17 @@ class SignaturesController extends AppController {
|
|||
$this->request->data = $this->Signature->read(null, $id);
|
||||
}
|
||||
|
||||
|
||||
// combobox for types
|
||||
$types = $this->Signature->validate['type']['rule'][1];
|
||||
$types = $this->_arrayToValuesIndexArray($types);
|
||||
$this->set('types',compact('types'));
|
||||
// combobox for categories
|
||||
$categories = $this->Signature->validate['category']['rule'][1];
|
||||
$categories = $this->_arrayToValuesIndexArray($categories);
|
||||
$this->set('categories',compact('categories'));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* delete method
|
||||
*
|
||||
|
@ -188,6 +368,7 @@ class SignaturesController extends AppController {
|
|||
// throw new UnauthorizedException('You can only delete signatures from your own organisation.');
|
||||
// }
|
||||
|
||||
// attachment will be deleted with the beforeDelete() function in the Model
|
||||
if ($this->Signature->delete()) {
|
||||
$this->Session->setFlash(__('Attribute deleted'));
|
||||
} else {
|
||||
|
@ -202,17 +383,45 @@ class SignaturesController extends AppController {
|
|||
public function search() {
|
||||
if ($this->request->is('post')) {
|
||||
$keyword = $this->request->data['Signature']['keyword'];
|
||||
$type = $this->request->data['Signature']['type'];
|
||||
$category = $this->request->data['Signature']['category'];
|
||||
|
||||
// search the db
|
||||
$this->Signature->recursive = 0;
|
||||
$this->paginate = array(
|
||||
'conditions' => array('Signature.value LIKE' => '%'.$keyword.'%'),
|
||||
);
|
||||
$conditions = array();
|
||||
if($keyword) {
|
||||
$conditions['Signature.value LIKE'] = '%'.$keyword.'%';
|
||||
}
|
||||
if($type != 'ALL') {
|
||||
$conditions['Signature.type ='] = $type;
|
||||
}
|
||||
if($category != 'ALL') {
|
||||
$conditions['Signature.category ='] = $category;
|
||||
}
|
||||
$this->Signature->recursive = 0;
|
||||
$this->paginate = array(
|
||||
'conditions' => $conditions
|
||||
);
|
||||
$this->set('signatures', $this->paginate());
|
||||
|
||||
// set the same view as the index page
|
||||
$this->render('index');
|
||||
} else {
|
||||
// no search keyword is given, show the search form
|
||||
|
||||
// adding filtering by category and type
|
||||
// combobox for types
|
||||
$types = array('ALL');
|
||||
$types = array_merge($types, $this->Signature->validate['type']['rule'][1]);
|
||||
$types = $this->_arrayToValuesIndexArray($types);
|
||||
$this->set('types',compact('types'));
|
||||
|
||||
// combobox for categories
|
||||
$categories = array('ALL');
|
||||
$categories = array_merge($categories, $this->Signature->validate['category']['rule'][1]);
|
||||
$categories = $this->_arrayToValuesIndexArray($categories);
|
||||
$this->set('categories',compact('categories'));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -128,7 +128,7 @@ class Event extends AppModel {
|
|||
'dependent' => true, // cascade deletes
|
||||
'conditions' => '',
|
||||
'fields' => '',
|
||||
'order' => 'Signature.type ASC',
|
||||
'order' => array('Signature.category ASC', 'Signature.type ASC'),
|
||||
'limit' => '',
|
||||
'offset' => '',
|
||||
'exclusive' => '',
|
||||
|
@ -159,11 +159,11 @@ class Event extends AppModel {
|
|||
}
|
||||
$conditions = array("Event.id" => $relatedEventIds);
|
||||
$relatedEvents= $this->find('all',
|
||||
array('conditions' => $conditions,
|
||||
'recursive' => 0,
|
||||
'order' => 'Event.date DESC',
|
||||
'fields' => 'Event.*'
|
||||
)
|
||||
array('conditions' => $conditions,
|
||||
'recursive' => 0,
|
||||
'order' => 'Event.date DESC',
|
||||
'fields' => 'Event.*'
|
||||
)
|
||||
);
|
||||
return $relatedEvents;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
<?php
|
||||
App::uses('AppModel', 'Model');
|
||||
App::uses('File', 'Utility');
|
||||
|
||||
/**
|
||||
* Signature Model
|
||||
*
|
||||
|
@ -32,21 +34,26 @@ class Signature extends AppModel {
|
|||
),
|
||||
'type' => array(
|
||||
'rule' => array('inList', array('md5','sha1',
|
||||
'filename',
|
||||
'ip-src',
|
||||
'ip-dst',
|
||||
'domain',
|
||||
'email-src',
|
||||
'email-dst',
|
||||
'email-subject',
|
||||
'email-attachment',
|
||||
'url',
|
||||
'user-agent',
|
||||
'regkey',
|
||||
'AS',
|
||||
'snort',
|
||||
'pattern-in-file',
|
||||
'other')),
|
||||
'filename',
|
||||
'filename|md5',
|
||||
'ip-src',
|
||||
'ip-dst',
|
||||
'domain',
|
||||
'email-src',
|
||||
'email-dst',
|
||||
'email-subject',
|
||||
'email-attachment',
|
||||
'url',
|
||||
'user-agent',
|
||||
'regkey',
|
||||
'regkey|value',
|
||||
'AS',
|
||||
'snort',
|
||||
'pattern-in-file',
|
||||
'pattern-in-memory',
|
||||
'attachment',
|
||||
'malware-sample',
|
||||
'other')),
|
||||
'message' => 'Options : md5, sha1, filename, ip, domain, email, url, regkey, AS, other, ...',
|
||||
//'allowEmpty' => false,
|
||||
'required' => true,
|
||||
|
@ -54,6 +61,21 @@ class Signature extends AppModel {
|
|||
//'on' => 'create', // Limit validation to 'create' or 'update' operations
|
||||
|
||||
),
|
||||
'category' => array(
|
||||
'rule' => array('inList', array('Payload delivery',
|
||||
'Antivirus detection',
|
||||
'Payload installation',
|
||||
'Artifacts dropped',
|
||||
'Persistence mechanism',
|
||||
'Registry keys modified',
|
||||
'Network activity',
|
||||
'Payload type',
|
||||
'Attribution',
|
||||
'Other',
|
||||
'' // FIXME remove this once all signatures have a category. Otherwise sigs without category are not shown in the list
|
||||
)),
|
||||
'message' => 'Options : Payload delivery, Antivirus detection, Payload installation, Files dropped ...'
|
||||
),
|
||||
'value' => array(
|
||||
'notempty' => array(
|
||||
'rule' => array('notempty'),
|
||||
|
@ -141,17 +163,35 @@ class Signature extends AppModel {
|
|||
return true;
|
||||
}
|
||||
|
||||
function beforeDelete() {
|
||||
// delete attachments from the disk
|
||||
if('attachment' == $this->data['Signature']['type'] ||
|
||||
'malware-sample'== $this->data['Signature']['type'] ) {
|
||||
// FIXME secure this filesystem access/delete by not allowing to change directories or go outside of the directory container.
|
||||
// only delete the file if it exists
|
||||
$filepath = APP."files/".$this->data['Signature']['event_id']."/".$this->data['Signature']['id'];
|
||||
$file = new File ($filepath);
|
||||
if($file->exists()) {
|
||||
if (!$file->delete()) {
|
||||
$this->Session->setFlash(__('Delete failed. Please report to administrator', true), 'default', array(), 'error'); // TODO change this message. Throw an internal error
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function validateSignatureValue ($fields) {
|
||||
$value = $fields['value'];
|
||||
$event_id = $this->data['Signature']['event_id'];
|
||||
$type = $this->data['Signature']['type'];
|
||||
$to_ids = $this->data['Signature']['to_ids'];
|
||||
|
||||
$category = $this->data['Signature']['category'];
|
||||
|
||||
// check if the signature already exists in the same event
|
||||
$params = array('recursive' => 0,
|
||||
'conditions' => array('Signature.event_id' => $event_id,
|
||||
'Signature.type' => $type,
|
||||
'Signature.to_ids' => $to_ids,
|
||||
'Signature.category' => $category,
|
||||
'Signature.value' => $value),
|
||||
);
|
||||
if (0 != $this->find('count', $params) )
|
||||
|
@ -160,20 +200,26 @@ class Signature extends AppModel {
|
|||
|
||||
// check data validation
|
||||
switch($this->data['Signature']['type']) {
|
||||
// FIXME lowercase hashes
|
||||
case 'md5':
|
||||
if (preg_match("#^[0-9a-f]{32}$#i", $value))
|
||||
return true;
|
||||
if (preg_match("#^[0-9a-f]{32}$#", $value))
|
||||
return true;
|
||||
return 'Checksum has invalid lenght or format. Please double check the value or select "other" for a type.';
|
||||
break;
|
||||
case 'sha1':
|
||||
if (preg_match("#^[0-9a-f]{40}$#i", $value))
|
||||
return true;
|
||||
if (preg_match("#^[0-9a-f]{40}$#", $value))
|
||||
return true;
|
||||
return 'Checksum has invalid lenght or format. Please double check the value or select "other" for a type.';
|
||||
break;
|
||||
case 'filename':
|
||||
// no newline
|
||||
if (!preg_match("#\n#", $value))
|
||||
return true;
|
||||
return true;
|
||||
break;
|
||||
case 'filename|md5':
|
||||
// no newline
|
||||
if (!preg_match("#^.*|[0-9a-f]{32}$#", $value))
|
||||
return true;
|
||||
break;
|
||||
case 'ip-src':
|
||||
$parts = explode("/", $value);
|
||||
|
@ -184,9 +230,9 @@ class Signature extends AppModel {
|
|||
if (filter_var($parts[0],FILTER_VALIDATE_IP)) {
|
||||
// ip is validated, now check if we have a valid network mask
|
||||
if (empty($parts[1]))
|
||||
return true;
|
||||
return true;
|
||||
else if(is_numeric($parts[1]) && $parts[1] < 129)
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return 'IP address has invalid format. Please double check the value or select "other" for a type.';
|
||||
|
@ -200,54 +246,59 @@ class Signature extends AppModel {
|
|||
if (filter_var($parts[0],FILTER_VALIDATE_IP)) {
|
||||
// ip is validated, now check if we have a valid network mask
|
||||
if (empty($parts[1]))
|
||||
return true;
|
||||
return true;
|
||||
else if(is_numeric($parts[1]) && $parts[1] < 129)
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return 'IP address has invalid format. Please double check the value or select "other" for a type.';
|
||||
break;
|
||||
case 'domain':
|
||||
if(preg_match("#^[A-Z0-9.-]+\.[A-Z]{2,4}$#i", $value))
|
||||
return true;
|
||||
return true;
|
||||
return 'Domain name has invalid format. Please double check the value or select "other" for a type.';
|
||||
break;
|
||||
case 'email-src':
|
||||
// we don't use the native function to prevent issues with partial email addresses
|
||||
if(preg_match("#^[A-Z0-9._%+-]*@[A-Z0-9.-]+\.[A-Z]{2,4}$#i", $value))
|
||||
return true;
|
||||
return true;
|
||||
return 'Email address has invalid format. Please double check the value or select "other" for a type.';
|
||||
break;
|
||||
case 'email-dst':
|
||||
// we don't use the native function to prevent issues with partial email addresses
|
||||
if(preg_match("#^[A-Z0-9._%+-]*@[A-Z0-9.-]+\.[A-Z]{2,4}$#i", $value))
|
||||
return true;
|
||||
return true;
|
||||
return 'Email address has invalid format. Please double check the value or select "other" for a type.';
|
||||
break;
|
||||
case 'email-subject':
|
||||
// no newline
|
||||
if (!preg_match("#\n#", $value))
|
||||
return true;
|
||||
return true;
|
||||
break;
|
||||
case 'email-attachment':
|
||||
// no newline
|
||||
if (!preg_match("#\n#", $value))
|
||||
return true;
|
||||
return true;
|
||||
break;
|
||||
case 'url':
|
||||
// no newline
|
||||
if (!preg_match("#\n#", $value))
|
||||
return true;
|
||||
return true;
|
||||
break;
|
||||
case 'user-agent':
|
||||
// no newline
|
||||
if (!preg_match("#\n#", $value))
|
||||
return true;
|
||||
return true;
|
||||
break;
|
||||
case 'regkey':
|
||||
// no newline
|
||||
if (!preg_match("#\n#", $value))
|
||||
return true;
|
||||
return true;
|
||||
break;
|
||||
case 'regkey|value':
|
||||
// no newline
|
||||
if (!preg_match("#.*|.*#", $value))
|
||||
return true;
|
||||
break;
|
||||
case 'snort':
|
||||
// no validation yet. TODO implement data validation on snort signature type
|
||||
|
@ -269,6 +320,8 @@ class Signature extends AppModel {
|
|||
}
|
||||
|
||||
function getRelatedSignatures($signature) {
|
||||
// LATER there should be a list of types/categories included here as some are not eligible (AV detection category
|
||||
// or "other" type could be excluded)
|
||||
// LATER getRelatedSignatures($signature) this might become a performance bottleneck
|
||||
$conditions = array('Signature.value =' => $signature['value'],
|
||||
'Signature.id !=' => $signature['id'],
|
||||
|
@ -277,8 +330,8 @@ class Signature extends AppModel {
|
|||
$fields = array('Signature.*');
|
||||
|
||||
$similar_events = $this->find('all',array('conditions' => $conditions,
|
||||
'fields' => $fields,
|
||||
'order' => 'Signature.event_id DESC', )
|
||||
'fields' => $fields,
|
||||
'order' => 'Signature.event_id DESC', )
|
||||
);
|
||||
return $similar_events;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<li><?php echo $this->Html->link(__('New Event', true), array('controller' => 'events', 'action' => 'add')); ?></li>
|
||||
<li><?php echo $this->Html->link(__('List Events', true), array('controller' => 'events', 'action' => 'index')); ?></li>
|
||||
<li><?php echo $this->Html->link(__('List Attribute', true), array('controller' => 'signatures', 'action' => 'index')); ?> </li>
|
||||
<li><?php echo $this->Html->link(__('Search Attribute', true), array('controller' => 'signatures', 'action' => 'search')); ?> </li>
|
||||
<li><?php echo $this->Html->link(__('List Attributes', true), array('controller' => 'signatures', 'action' => 'index')); ?> </li>
|
||||
<li><?php echo $this->Html->link(__('Search Attributes', true), array('controller' => 'signatures', 'action' => 'search')); ?> </li>
|
||||
<li><?php echo $this->Html->link(__('Export', true), array('controller' => 'events', 'action' => 'export')); ?></li>
|
||||
|
||||
<li> </li>
|
||||
|
|
|
@ -69,18 +69,38 @@
|
|||
<?php if (!empty($event['Signature'])):?>
|
||||
<table cellpadding = "0" cellspacing = "0">
|
||||
<tr>
|
||||
<th>Category</th>
|
||||
<th>Type</th>
|
||||
<th>Value</th>
|
||||
<th>Related Events</th>
|
||||
<th>To IDS</th>
|
||||
<th>IDS Signature</th>
|
||||
<th class="actions">Actions</th>
|
||||
</tr>
|
||||
<?php
|
||||
$category_prev = "";
|
||||
foreach ($event['Signature'] as $signature):
|
||||
?>
|
||||
<tr>
|
||||
<td class="short"><?php
|
||||
if ($category_prev != $signature['category']) {
|
||||
$category_prev = $signature['category'];
|
||||
echo $signature['category'];
|
||||
} else {
|
||||
echo ' ';
|
||||
}
|
||||
?></td>
|
||||
<td class="short"><?php echo $signature['type'];?></td>
|
||||
<td><?php echo nl2br(Sanitize::html($signature['value']));?></td>
|
||||
<td><?php
|
||||
$sig_display = nl2br(Sanitize::html($signature['value']));
|
||||
if('attachment' == $signature['type'] ||
|
||||
'malware-sample' == $signature['type']) {
|
||||
$filename_hash = explode('|', $signature['value']);
|
||||
echo $this->Html->link($filename_hash[0], array('controller' => 'signatures', 'action' => 'download', $signature['id']));
|
||||
if (isset($filename_hash[1])) echo '|'.$filename_hash[1];
|
||||
} else {
|
||||
echo $sig_display;
|
||||
}
|
||||
?></td>
|
||||
<td class="short" style="text-align: center;">
|
||||
<?php
|
||||
if (null != $relatedSignatures[$signature['id']]) {
|
||||
|
@ -91,7 +111,7 @@
|
|||
}
|
||||
?>
|
||||
</td>
|
||||
<td class="short"><?php echo $signature['to_ids'] ? 'Yes' : 'No';?></td>
|
||||
<td class="short" style="text-align: center;"><?php echo $signature['to_ids'] ? 'Yes' : 'No';?></td>
|
||||
<td class="actions">
|
||||
<?php
|
||||
if ($isAdmin || $event['Event']['org'] == $me['org']) {
|
||||
|
@ -106,7 +126,8 @@
|
|||
<?php if ($isAdmin || $event['Event']['org'] == $me['org']): ?>
|
||||
<div class="actions">
|
||||
<ul>
|
||||
<li><?php echo $this->Html->link('New Attribute', array('controller' => 'signatures', 'action' => 'add', $event['Event']['id']));?> </li>
|
||||
<li><?php echo $this->Html->link('Add Attribute', array('controller' => 'signatures', 'action' => 'add', $event['Event']['id']));?> </li>
|
||||
<li><?php echo $this->Html->link('Add Attachment', array('controller' => 'signatures', 'action' => 'add_attachment', $event['Event']['id']));?> </li>
|
||||
</ul>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
@ -117,7 +138,8 @@
|
|||
<div class="actions">
|
||||
<ul>
|
||||
<?php if ($isAdmin || $event['Event']['org'] == $me['org']): ?>
|
||||
<li><?php echo $this->Html->link(__('New Attribute', true), array('controller' => 'signatures', 'action' => 'add', $event['Event']['id']));?> </li>
|
||||
<li><?php echo $this->Html->link(__('Add Attribute', true), array('controller' => 'signatures', 'action' => 'add', $event['Event']['id']));?> </li>
|
||||
<li><?php echo $this->Html->link(__('Add Attachment', true), array('controller' => 'signatures', 'action' => 'add_attachment', $event['Event']['id']));?> </li>
|
||||
<li><?php echo $this->Html->link(__('Edit Event', true), array('action' => 'edit', $event['Event']['id'])); ?> </li>
|
||||
<li><?php echo $this->Form->postLink(__('Delete Event'), array('action' => 'delete', $event['Event']['id']), null, __('Are you sure you want to delete # %s?', $event['Event']['id'])); ?></li>
|
||||
<li> </li>
|
||||
|
|
|
@ -4,10 +4,12 @@
|
|||
<legend><?php echo __('Add Attribute'); ?></legend>
|
||||
<?php
|
||||
echo $this->Form->hidden('event_id');
|
||||
echo $this->Form->input('category');
|
||||
echo $this->Form->input('type');
|
||||
echo $this->Form->input('to_ids', array(
|
||||
'checked' => true,
|
||||
'after' => ' <i>Can we make an IDS signature based on this attribute ?</i>',
|
||||
'label' => 'IDS Signature?'
|
||||
));
|
||||
echo $this->Form->input('value', array(
|
||||
'error' => array('escape' => false),
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
<div class="signatures form">
|
||||
<?php echo $this->Form->create('Signature', array('enctype' => 'multipart/form-data'));?>
|
||||
<fieldset>
|
||||
<legend><?php echo __('Add Attachment'); ?></legend>
|
||||
<?php
|
||||
echo $this->Form->hidden('event_id');
|
||||
echo $this->Form->input('category');
|
||||
echo $this->Form->file('value', array(
|
||||
'error' => array('escape' => false),
|
||||
));
|
||||
echo $this->Form->input('malware', array(
|
||||
'type' => 'checkbox',
|
||||
'checked' => false,
|
||||
'after' => ' <i>(Every malware sample will be zipped with the password "infected")</i>',
|
||||
));
|
||||
?>
|
||||
</fieldset>
|
||||
<?php echo $this->Form->end(__('Upload'));?>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<ul>
|
||||
<?php echo $this->element('actions_menu'); ?>
|
||||
</ul>
|
||||
</div>
|
|
@ -4,9 +4,17 @@
|
|||
<legend><?php echo __('Edit Attribute'); ?></legend>
|
||||
<?php
|
||||
echo $this->Form->input('id');
|
||||
echo $this->Form->input('type');
|
||||
echo $this->Form->input('value');
|
||||
echo $this->Form->input('to_ids');
|
||||
echo $this->Form->input('category');
|
||||
if($attachment) {
|
||||
echo $this->Form->hidden('type');
|
||||
echo "<BR>Type: ".$this->Form->value('Signature.type');
|
||||
echo $this->Form->hidden('value');
|
||||
echo "<BR>Value: ".$this->Form->value('Signature.value');
|
||||
} else {
|
||||
echo $this->Form->input('type');
|
||||
echo $this->Form->input('value');
|
||||
}
|
||||
echo $this->Form->input('to_ids', array('label' => 'IDS Signature?'));
|
||||
?>
|
||||
</fieldset>
|
||||
<?php echo $this->Form->end(__('Submit'));?>
|
||||
|
|
|
@ -3,9 +3,10 @@
|
|||
<table cellpadding="0" cellspacing="0">
|
||||
<tr>
|
||||
<th><?php echo $this->Paginator->sort('event_id');?></th>
|
||||
<th><?php echo $this->Paginator->sort('category');?></th>
|
||||
<th><?php echo $this->Paginator->sort('type');?></th>
|
||||
<th><?php echo $this->Paginator->sort('value');?></th>
|
||||
<th>To IDS</th>
|
||||
<th>IDS Signature</th>
|
||||
<th class="actions"><?php echo __('Actions');?></th>
|
||||
</tr>
|
||||
<?php
|
||||
|
@ -15,10 +16,20 @@
|
|||
<?php echo $this->Html->link($signature['Event']['id'], array('controller' => 'events', 'action' => 'view', $signature['Event']['id'])); ?>
|
||||
</td>
|
||||
<td class="short" onclick="document.location ='<?php echo $this->Html->url(array('controller' => 'events', 'action' => 'view', $signature['Signature']['event_id']), true) ;?>';">
|
||||
<?php echo h($signature['Signature']['category']); ?> </td>
|
||||
<td class="short" onclick="document.location ='<?php echo $this->Html->url(array('controller' => 'events', 'action' => 'view', $signature['Signature']['event_id']), true) ;?>';">
|
||||
<?php echo h($signature['Signature']['type']); ?> </td>
|
||||
<td onclick="document.location ='<?php echo $this->Html->url(array('controller' => 'events', 'action' => 'view', $signature['Signature']['event_id']), true) ;?>';">
|
||||
<?php echo nl2br(Sanitize::html($signature['Signature']['value'])); ?> </td>
|
||||
<td class="short" onclick="document.location ='<?php echo $this->Html->url(array('controller' => 'events', 'action' => 'view', $signature['Signature']['event_id']), true) ;?>';">
|
||||
<?php
|
||||
$sig_display = nl2br(Sanitize::html($signature['Signature']['value']));
|
||||
if('attachment' == $signature['Signature']['type'] ||
|
||||
'malware-sample' == $signature['Signature']['type']) {
|
||||
echo $this->Html->link($sig_display, array('controller' => 'files', $signature['Signature']['event_id'], $sig_display));
|
||||
} else {
|
||||
echo $sig_display;
|
||||
}
|
||||
?> </td>
|
||||
<td class="short" style="text-align: center;" onclick="document.location ='<?php echo $this->Html->url(array('controller' => 'events', 'action' => 'view', $signature['Signature']['event_id']), true) ;?>';">
|
||||
<?php echo $signature['Signature']['to_ids'] ? 'Yes' : 'No'; ?> </td>
|
||||
<td class="actions"><?php
|
||||
if ($isAdmin || $signature['Event']['org'] == $me['org']) {
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
<legend><?php echo __('Search Attribute'); ?></legend>
|
||||
<?php
|
||||
echo $this->Form->input('keyword');
|
||||
echo $this->Form->input('type');
|
||||
echo $this->Form->input('category');
|
||||
?>
|
||||
</fieldset>
|
||||
<?php echo $this->Form->end(__('Search', true));?>
|
||||
|
|
Loading…
Reference in New Issue