mirror of https://github.com/MISP/MISP
md5 and sha1 hashes now automatically lowercase
cleaned up some code and fixed some vulnerabilitiespull/61/head
parent
86b760cd54
commit
7b1673d212
|
@ -13,8 +13,8 @@ class EventsController extends AppController {
|
|||
* Components
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
|
||||
*/
|
||||
|
||||
public $components = array('Security', 'Email');
|
||||
public $paginate = array(
|
||||
'limit' => 50,
|
||||
|
@ -22,19 +22,19 @@ class EventsController extends AppController {
|
|||
'Event.date' => 'DESC'
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
|
||||
function beforeFilter() {
|
||||
// what pages are allowed for non-logged-in users
|
||||
$this->Auth->allow('xml');
|
||||
$this->Auth->allow('nids');
|
||||
$this->Auth->allow('text');
|
||||
|
||||
|
||||
// These variables are required for every view
|
||||
$this->set('me', $this->Auth->user());
|
||||
$this->set('isAdmin', $this->_isAdmin());
|
||||
}
|
||||
|
||||
|
||||
public function isAuthorized($user) {
|
||||
// Admins can access everything
|
||||
if (parent::isAuthorized($user)) {
|
||||
|
@ -45,10 +45,10 @@ class EventsController extends AppController {
|
|||
$eventid = $this->request->params['pass'][0];
|
||||
return $this->Event->isOwnedByOrg($eventid, $this->Auth->user('org'));
|
||||
}
|
||||
// the other pages are allowed by logged in users
|
||||
// the other pages are allowed by logged in users
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* index method
|
||||
*
|
||||
|
@ -77,14 +77,14 @@ class EventsController extends AppController {
|
|||
}
|
||||
$this->set('event', $this->Event->read(null, $id));
|
||||
$this->set('relatedEvents', $this->Event->getRelatedEvents());
|
||||
|
||||
|
||||
$related_signatures = array();
|
||||
$this->loadModel('Signature');
|
||||
foreach ($this->Event->data['Signature'] as $signature) {
|
||||
$related_signatures[$signature['id']] = $this->Signature->getRelatedSignatures($signature);
|
||||
}
|
||||
$this->set('relatedSignatures', $related_signatures);
|
||||
|
||||
|
||||
$this->set('categories', $this->Signature->validate['category']['rule'][1]);
|
||||
}
|
||||
|
||||
|
@ -124,12 +124,8 @@ class EventsController extends AppController {
|
|||
if (!$this->Event->exists()) {
|
||||
throw new NotFoundException(__('Invalid event'));
|
||||
}
|
||||
// Replaced by isAuthorized
|
||||
// // only edit own events
|
||||
// $old_event = $this->Event->read(null, $id);
|
||||
// if (!$this->_isAdmin() && $this->Auth->user('org') != $old_event['Event']['org']) {
|
||||
// throw new UnauthorizedException('You are only allowed to edit events of your own organisation.');
|
||||
// }
|
||||
// only edit own events verified by isAuthorized
|
||||
|
||||
if ($this->request->is('post') || $this->request->is('put')) {
|
||||
// always force the user and org, but do not force it for admins
|
||||
if (!$this->_isAdmin()) {
|
||||
|
@ -141,7 +137,7 @@ class EventsController extends AppController {
|
|||
}
|
||||
// we probably also want to remove the alerted flag
|
||||
$this->request->data['Event']['alerted'] = 0;
|
||||
|
||||
|
||||
// say what fields are to be updated
|
||||
$fieldList=array('user_id', 'org', 'date', 'risk', 'info', 'alerted', 'private');
|
||||
if ($this->Event->save($this->request->data, true, $fieldList)) {
|
||||
|
@ -153,7 +149,7 @@ class EventsController extends AppController {
|
|||
} else {
|
||||
$this->request->data = $this->Event->read(null, $id);
|
||||
}
|
||||
|
||||
|
||||
// combobox for types
|
||||
$risks = $this->Event->validate['risk']['rule'][1];
|
||||
$risks = $this->_arrayToValuesIndexArray($risks);
|
||||
|
@ -174,12 +170,8 @@ class EventsController extends AppController {
|
|||
if (!$this->Event->exists()) {
|
||||
throw new NotFoundException(__('Invalid event'));
|
||||
}
|
||||
// Replaced by isAuthorized
|
||||
// // only edit own events
|
||||
// $this->Event->read();
|
||||
// if (!$this->_isAdmin() && $this->Auth->user('org') != $this->Event->data['Event']['org']) {
|
||||
// throw new UnauthorizedException('You are only allowed to edit your own events.');
|
||||
// }
|
||||
// only edit own events verified by isAuthorized
|
||||
|
||||
if ($this->Event->delete()) {
|
||||
$this->Session->setFlash(__('Event deleted'));
|
||||
$this->redirect(array('action' => 'index'));
|
||||
|
@ -197,25 +189,21 @@ class EventsController extends AppController {
|
|||
if (!$this->Event->exists()) {
|
||||
throw new NotFoundException(__('Invalid event'));
|
||||
}
|
||||
|
||||
|
||||
// only allow form submit CSRF protection.
|
||||
if ($this->request->is('post') || $this->request->is('put')) {
|
||||
|
||||
$this->Event->id = $id;
|
||||
$this->Event->read();
|
||||
|
||||
// Replaced by isAuthorized
|
||||
// // only allow alert for own events or admins
|
||||
// if (!$this->_isAdmin() && $this->Auth->user('org') != $this->Event->data['Event']['org']) {
|
||||
// throw new UnauthorizedException('You are only allowed to finish events of your own organisation.');
|
||||
// }
|
||||
|
||||
|
||||
// only allow alert for own events verified by isAuthorized
|
||||
|
||||
// fetch the event and build the body
|
||||
if (1 == $this->Event->data['Event']['alerted']) {
|
||||
$this->Session->setFlash(__('Everyone has already been alerted for this event. To alert again, first edit this event.', true), 'default', array(), 'error');
|
||||
$this->redirect(array('action' => 'view', $id));
|
||||
}
|
||||
|
||||
|
||||
// The mail body, Sanitize::html() is NOT needed as we are sending plain-text mails.
|
||||
$body = "";
|
||||
$appendlen = 20;
|
||||
|
@ -230,7 +218,7 @@ class EventsController extends AppController {
|
|||
if (!empty($relatedEvents)) {
|
||||
foreach ($relatedEvents as $relatedEvent){
|
||||
$body .= 'Related to : '.Configure::read('CyDefSIG.baseurl').'/events/view/'.$relatedEvent['Event']['id'].' ('.$relatedEvent['Event']['date'].')'."\n" ;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
$body .= 'Info : '."\n";
|
||||
|
@ -238,7 +226,7 @@ class EventsController extends AppController {
|
|||
$body .= "\n";
|
||||
$body .= 'Attributes :'."\n";
|
||||
$body_temp_other = "";
|
||||
|
||||
|
||||
if (isset($this->Event->data['Signature'])) {
|
||||
foreach ($this->Event->data['Signature'] as $signature){
|
||||
$line = '- '.$signature['type'].str_repeat(' ', $appendlen - 2 - strlen( $signature['type'])).': '.$signature['value']."\n";
|
||||
|
@ -249,15 +237,15 @@ class EventsController extends AppController {
|
|||
}
|
||||
$body .= "\n";
|
||||
$body .= $body_temp_other; // append the 'other' attribute types to the bottom.
|
||||
|
||||
|
||||
// sign the body
|
||||
require_once 'Crypt/GPG.php';
|
||||
$gpg = new Crypt_GPG(array('homedir' => Configure::read('GnuPG.homedir')));
|
||||
$gpg->addSignKey(Configure::read('GnuPG.email'), Configure::read('GnuPG.password'));
|
||||
$body_signed = $gpg->sign($body, Crypt_GPG::SIGN_MODE_CLEAR);
|
||||
|
||||
|
||||
$this->loadModel('User');
|
||||
|
||||
|
||||
//
|
||||
// Build a list of the recipients that get a non-encrypted mail
|
||||
// But only do this if it is allowed in the bootstrap.php file.
|
||||
|
@ -286,7 +274,7 @@ class EventsController extends AppController {
|
|||
// to reset the email fields using the reset method of the Email component.
|
||||
$this->Email->reset();
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Build a list of the recipients that wish to receive encrypted mails.
|
||||
//
|
||||
|
@ -304,34 +292,34 @@ class EventsController extends AppController {
|
|||
$this->Email->subject = "[CyDefSIG] Event ".$id." - ".$this->Event->data['Event']['risk']." - TLP Amber";
|
||||
$this->Email->template = 'body';
|
||||
$this->Email->sendAs = 'text'; // both text or html
|
||||
|
||||
|
||||
// import the key of the user into the keyring
|
||||
// this is not really necessary, but it enables us to find
|
||||
// this is not really necessary, but it enables us to find
|
||||
// the correct key-id even if it is not the same as the emailaddress
|
||||
$key_import_output = $gpg->importKey($user['User']['gpgkey']);
|
||||
// say what key should be used to encrypt
|
||||
$gpg = new Crypt_GPG();
|
||||
$gpg->addEncryptKey($key_import_output['fingerprint']); // use the key that was given in the import
|
||||
|
||||
|
||||
$body_enc_sig = $gpg->encrypt($body_signed, true);
|
||||
|
||||
|
||||
$this->set('body', $body_enc_sig);
|
||||
$this->Email->send();
|
||||
// If you wish to send multiple emails using a loop, you'll need
|
||||
// to reset the email fields using the reset method of the Email component.
|
||||
$this->Email->reset();
|
||||
}
|
||||
|
||||
|
||||
// update the DB to set the alerted flag
|
||||
$this->Event->saveField('alerted', 1);
|
||||
|
||||
|
||||
// redirect to the view event page
|
||||
$this->Session->setFlash(__('Email sent to all participants.', true));
|
||||
$this->redirect(array('action' => 'view', $id));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
@ -341,12 +329,12 @@ class EventsController extends AppController {
|
|||
if (!$this->Event->exists()) {
|
||||
throw new NotFoundException(__('Invalid event'));
|
||||
}
|
||||
|
||||
|
||||
// User has filled in his contact form, send out the email.
|
||||
if ($this->request->is('post') || $this->request->is('put')) {
|
||||
$message = $this->request->data['Event']['message'];
|
||||
if ($this->_sendContactEmail($id, $message)) {
|
||||
// LATER when a user is deleted this will create problems.
|
||||
// LATER when a user is deleted this will create problems.
|
||||
// LATER send the email to all the people who are in the org that created the event
|
||||
// redirect to the view event page
|
||||
$this->Session->setFlash(__('Email sent to the reporter.', true));
|
||||
|
@ -360,8 +348,8 @@ class EventsController extends AppController {
|
|||
$this->data = $this->Event->read(null, $id);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Sends out an email with the request to be contacted about a specific event.
|
||||
|
@ -391,7 +379,7 @@ class EventsController extends AppController {
|
|||
$body .="\n";
|
||||
$body .="\n";
|
||||
$body .="The event is the following: \n";
|
||||
|
||||
|
||||
// print the event in mail-format
|
||||
// LATER place event-to-email-layout in a function
|
||||
$appendlen = 20;
|
||||
|
@ -406,7 +394,7 @@ class EventsController extends AppController {
|
|||
if (!empty($relatedEvents)) {
|
||||
foreach ($relatedEvents as $relatedEvent){
|
||||
$body .= 'Related to : '.Configure::read('CyDefSIG.baseurl').'/events/view/'.$relatedEvent['Event']['id'].' ('.$relatedEvent['Event']['date'].')'."\n" ;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
$body .= 'Info : '."\n";
|
||||
|
@ -430,7 +418,7 @@ class EventsController extends AppController {
|
|||
$gpg = new Crypt_GPG(array('homedir' => Configure::read('GnuPG.homedir')));
|
||||
$gpg->addSignKey(Configure::read('GnuPG.email'), Configure::read('GnuPG.password'));
|
||||
$body_signed = $gpg->sign($body, Crypt_GPG::SIGN_MODE_CLEAR);
|
||||
|
||||
|
||||
if (!empty($reporter['gpgkey'])) {
|
||||
// import the key of the user into the keyring
|
||||
// this isn't really necessary, but it gives it the fingerprint necessary for the next step
|
||||
|
@ -438,7 +426,7 @@ class EventsController extends AppController {
|
|||
// say what key should be used to encrypt
|
||||
$gpg = new Crypt_GPG();
|
||||
$gpg->addEncryptKey($key_import_output['fingerprint']); // use the key that was given in the import
|
||||
|
||||
|
||||
$body_enc_sig = $gpg->encrypt($body_signed, true);
|
||||
} else {
|
||||
$body_enc_sig = $body_signed;
|
||||
|
@ -453,7 +441,7 @@ class EventsController extends AppController {
|
|||
$this->Email->template = 'body';
|
||||
$this->Email->sendAs = 'text'; // both text or html
|
||||
$this->set('body', $body_enc_sig);
|
||||
|
||||
|
||||
// Add the GPG key of the user as attachment
|
||||
// LATER sign the attached GPG key
|
||||
if (!empty($me_user['gpgkey'])) {
|
||||
|
@ -467,28 +455,28 @@ class EventsController extends AppController {
|
|||
'gpgkey.asc' => $tmpfname
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// send it
|
||||
$result = $this->Email->send();
|
||||
|
||||
|
||||
// remove the temporary gpg file
|
||||
if (!empty($me_user['gpgkey']))
|
||||
unlink($tmpfname);
|
||||
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public function export() {
|
||||
// Simply display a static view
|
||||
|
||||
|
||||
// generate the list of Attribute types
|
||||
$this->loadModel('Signature');
|
||||
$this->set('sig_types', $this->Signature->validate['type']['rule'][1]);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public function xml($key) {
|
||||
// FIXME implement XML output
|
||||
// check if the key is valid -> search for users based on key
|
||||
|
@ -502,7 +490,7 @@ class EventsController extends AppController {
|
|||
$this->header('Content-Type: text/xml'); // set the content type
|
||||
$this->layout = 'xml/default';
|
||||
// $this->header('Content-Disposition: attachment; filename="cydefsig.xml"');
|
||||
|
||||
|
||||
$conditions = array("Event.alerted" => 1);
|
||||
$fields = array('Event.id', 'Event.date', 'Event.risk', 'Event.info');
|
||||
if ('true' == Configure::read('CyDefSIG.showorg')) {
|
||||
|
@ -516,14 +504,14 @@ class EventsController extends AppController {
|
|||
// 'contain' => $contain
|
||||
);
|
||||
$results = $this->Event->find('all', $params);
|
||||
|
||||
|
||||
|
||||
|
||||
/* $xml = Xml::build('<?xml version="1.0" encoding="UTF-8" ?><CyDefSIG></CyDefSIG>'); */
|
||||
|
||||
|
||||
$myXmlOriginal = '<?xml version="1.0"?><root><child>value</child></root>';
|
||||
$xml = Xml::build($myXmlOriginal);
|
||||
$xml->root->addChild('young', 'new value');
|
||||
|
||||
|
||||
// foreach ($results as $result) {
|
||||
// debug($result);
|
||||
// $xml->CyDefSIG->addChild('f', 'b');
|
||||
|
@ -534,8 +522,8 @@ class EventsController extends AppController {
|
|||
// debug($xml->saveXML());
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public function nids($key) {
|
||||
// check if the key is valid -> search for users based on key
|
||||
$this->loadModel('User');
|
||||
|
@ -548,24 +536,24 @@ class EventsController extends AppController {
|
|||
$this->header('Content-Type: text/plain'); // set the content type
|
||||
$this->header('Content-Disposition: attachment; filename="cydefsig.rules"');
|
||||
$this->layout = 'text/default';
|
||||
|
||||
|
||||
$rules= array();
|
||||
|
||||
|
||||
// find events that are published
|
||||
$events = $this->Event->findAllByAlerted(1);
|
||||
$classtype = 'targeted-attack';
|
||||
|
||||
|
||||
foreach ($events as $event) {
|
||||
# proto src_ip src_port direction dst_ip dst_port msg rule_content tag sid rev
|
||||
$rule_format_msg = 'msg: "CyDefSIG %s, Event '.$event['Event']['id'].', '.$event['Event']['risk'].'"';
|
||||
$rule_format_reference = 'reference:url,'.Configure::read('CyDefSIG.baseurl').'/events/view/'.$event['Event']['id'];
|
||||
$rule_format = 'alert %s %s %s %s %s %s ('.$rule_format_msg.'; %s %s classtype:'.$classtype.'; sid:%d; rev:%d; '.$rule_format_reference.';) ';
|
||||
|
||||
|
||||
$sid = $user['User']['nids_sid']+($event['Event']['id']*100); // LATER this will cause issues with events containing more than 99 attributes
|
||||
//debug($event);
|
||||
foreach ($event['Signature'] as $signature) {
|
||||
if (0 == $signature['to_ids']) continue; // attribute is not to be exported to IDS. // LATER filter out to_ids=0 in the query
|
||||
|
||||
|
||||
$sid++;
|
||||
switch ($signature['type']) {
|
||||
// LATER test all the snort signatures
|
||||
|
@ -714,7 +702,7 @@ class EventsController extends AppController {
|
|||
break;
|
||||
case 'snort':
|
||||
$tmp_rule = $signature['value'];
|
||||
|
||||
|
||||
// rebuild the rule by overwriting the different keywords using preg_replace()
|
||||
// sid - '/sid\s*:\s*[0-9]+\s*;/'
|
||||
// rev - '/rev\s*:\s*[0-9]+\s*;/'
|
||||
|
@ -733,7 +721,7 @@ class EventsController extends AppController {
|
|||
if (null == $tmp_rule ) break; // don't output the rule on error with the regex
|
||||
$tmp_rule = preg_replace('/reference\s*:\s*.+;/', $rule_format_reference.';', $tmp_rule, -1, $replace_count['reference']);
|
||||
if (null == $tmp_rule ) break; // don't output the rule on error with the regex
|
||||
|
||||
|
||||
// some values were not replaced, so we need to add them ourselves, and insert them in the rule
|
||||
$extra_for_rule="";
|
||||
if (0 == $replace_count['sid']) {
|
||||
|
@ -748,15 +736,15 @@ class EventsController extends AppController {
|
|||
$extra_for_rule .= $rule_format_reference.';';
|
||||
}
|
||||
$tmp_rule = preg_replace('/;\s*\)/', '; '.$extra_for_rule.')', $tmp_rule);
|
||||
|
||||
|
||||
// finally the rule is cleaned up and can be outputed
|
||||
$rules[] = $tmp_rule;
|
||||
|
||||
|
||||
// TODO test using lots of snort rules.
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -768,10 +756,10 @@ class EventsController extends AppController {
|
|||
print "#</pre>\n";
|
||||
|
||||
$this->set('rules', $rules);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public function text($key, $type="") {
|
||||
// check if the key is valid -> search for users based on key
|
||||
$this->loadModel('User');
|
||||
|
@ -780,10 +768,10 @@ class EventsController extends AppController {
|
|||
if (empty($user)) {
|
||||
throw new UnauthorizedException('Incorrect authentication key');
|
||||
}
|
||||
|
||||
|
||||
$this->header('Content-Type: text/plain'); // set the content type
|
||||
$this->layout = 'text/default';
|
||||
|
||||
|
||||
$this->loadModel('Signature');
|
||||
$params = array(
|
||||
'conditions' => array('Signature.type' => $type), //array of conditions
|
||||
|
@ -793,11 +781,11 @@ class EventsController extends AppController {
|
|||
'group' => array('Signature.value'), //fields to GROUP BY
|
||||
);
|
||||
$signatures = $this->Signature->find('all', $params);
|
||||
|
||||
|
||||
$this->set('signatures', $signatures);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* // LATER move _dnsNameToRawFormat($name) function to a better place
|
||||
* Converts a DNS name to a raw format usable in NIDS like Snort.
|
||||
|
@ -823,7 +811,7 @@ class EventsController extends AppController {
|
|||
// and append |00| to terminate the name
|
||||
return $rawName;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -11,18 +11,18 @@ App::uses('File', 'Utility');
|
|||
class SignaturesController extends AppController {
|
||||
|
||||
public $components = array('Security');
|
||||
|
||||
|
||||
function beforeFilter() {
|
||||
// permit reuse of CSRF tokens on the search page.
|
||||
// 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());
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function isAuthorized($user) {
|
||||
// Admins can access everything
|
||||
|
@ -43,7 +43,7 @@ class SignaturesController extends AppController {
|
|||
// the other pages are allowed by logged in users
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* index method
|
||||
*
|
||||
|
@ -62,13 +62,7 @@ class SignaturesController extends AppController {
|
|||
public function add($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.');
|
||||
// }
|
||||
// only own signatures verified by isAuthorized
|
||||
|
||||
// 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
|
||||
|
@ -77,26 +71,26 @@ class SignaturesController extends AppController {
|
|||
$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', $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);
|
||||
|
||||
|
||||
//
|
||||
// multiple signatures in batch import
|
||||
//
|
||||
if ($this->request->data['Signature']['batch_import'] == 1) {
|
||||
// make array from value field
|
||||
$signatures = explode("\n", $this->request->data['Signature']['value']);
|
||||
|
||||
|
||||
$fails = ""; // will be used to keep a list of the lines that failed or succeeded
|
||||
$successes = "";
|
||||
foreach ($signatures as $key => $signature) {
|
||||
$signature = trim($signature);
|
||||
if (strlen($signature) == 0 )
|
||||
continue; // don't do anything for empty lines
|
||||
|
||||
|
||||
$this->Signature->create();
|
||||
$this->request->data['Signature']['value'] = $signature; // set the value as the content of the single line
|
||||
$this->request->data['Signature']['uuid'] = String::uuid();
|
||||
|
@ -105,7 +99,7 @@ class SignaturesController extends AppController {
|
|||
} else {
|
||||
$fails .= " ".($key+1);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
// we added all the signatures,
|
||||
if ($fails) {
|
||||
|
@ -116,11 +110,11 @@ class SignaturesController extends AppController {
|
|||
// list the ones that succeeded
|
||||
$this->Session->setFlash(__('The lines'.$successes.' have been saved', true));
|
||||
}
|
||||
|
||||
|
||||
$this->redirect(array('controller' => 'events', 'action' => 'view', $this->request->data['Signature']['event_id']));
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
else {
|
||||
//
|
||||
// single signature
|
||||
|
@ -128,7 +122,7 @@ class SignaturesController extends AppController {
|
|||
// create the signature
|
||||
$this->Signature->create();
|
||||
$this->request->data['Signature']['uuid'] = String::uuid();
|
||||
|
||||
|
||||
if ($this->Signature->save($this->request->data)) {
|
||||
// inform the user and redirect
|
||||
$this->Session->setFlash(__('The attribute has been saved'));
|
||||
|
@ -141,7 +135,7 @@ class SignaturesController extends AppController {
|
|||
// set the event_id in the form
|
||||
$this->request->data['Signature']['event_id'] = $event_id;
|
||||
}
|
||||
|
||||
|
||||
// combobox for types
|
||||
$types = $this->Signature->validate['type']['rule'][1];
|
||||
$types = $this->_arrayToValuesIndexArray($types);
|
||||
|
@ -151,14 +145,14 @@ class SignaturesController extends AppController {
|
|||
$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 = '';
|
||||
|
@ -170,18 +164,18 @@ class SignaturesController extends AppController {
|
|||
} 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,
|
||||
'name' => $filename,
|
||||
'download' => true,
|
||||
'path' => DS
|
||||
);
|
||||
$this->set($params);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* add_attachment method
|
||||
*
|
||||
|
@ -190,16 +184,11 @@ class SignaturesController extends AppController {
|
|||
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.');
|
||||
// // }
|
||||
// only own signatures verified by isAuthorized
|
||||
|
||||
// Check if there were problems with the file upload
|
||||
$filename = Sanitize::HTML($this->request->data['Signature']['value']['name']);
|
||||
// only keep the last part of the filename, this should prevent directory attacks
|
||||
$filename = basename($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')
|
||||
|
@ -210,11 +199,11 @@ class SignaturesController extends AppController {
|
|||
$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']) {
|
||||
|
@ -228,14 +217,14 @@ class SignaturesController extends AppController {
|
|||
$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
|
||||
|
@ -245,8 +234,8 @@ class SignaturesController extends AppController {
|
|||
$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
|
||||
|
||||
$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');
|
||||
|
@ -265,10 +254,10 @@ class SignaturesController extends AppController {
|
|||
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
|
||||
rename($file->path, $file_in_zip->path); // TODO check if no workaround exists for the current filtering mechanisms
|
||||
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');
|
||||
if($exec_retval != 0) { // not EXIT_SUCCESS
|
||||
$this->Session->setFlash(__('Problem with zipping the attachment. Please report to administrator. '.$exec_output, true), 'default', array(), 'error');
|
||||
// remove the entry from the database
|
||||
$this->Signature->delete();
|
||||
$file_in_zip->delete();
|
||||
|
@ -278,16 +267,16 @@ class SignaturesController extends AppController {
|
|||
$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);
|
||||
|
@ -305,12 +294,7 @@ class SignaturesController extends AppController {
|
|||
if (!$this->Signature->exists()) {
|
||||
throw new NotFoundException(__('Invalid signature'));
|
||||
}
|
||||
// Replaced by isAuthorized
|
||||
// // only own signatures
|
||||
// $this->Signature->read();
|
||||
// if (!$this->_isAdmin() && $this->Auth->user('org') != $this->Signature->data['Event']['org']) {
|
||||
// throw new UnauthorizedException('You can only edit signatures from your own organisation.');
|
||||
// }
|
||||
// only own signatures verified by isAuthorized
|
||||
|
||||
$this->Signature->read();
|
||||
$event_id = $this->Signature->data['Signature']['event_id'];
|
||||
|
@ -323,15 +307,13 @@ class SignaturesController extends AppController {
|
|||
} else {
|
||||
$this->set('attachment', false);
|
||||
}
|
||||
|
||||
debug($this->Signature->data);
|
||||
|
||||
if ($this->request->is('post') || $this->request->is('put')) {
|
||||
|
||||
if ($this->Signature->save($this->request->data)) {
|
||||
// TODO should I check here if it's possible to change the event_id or org ?
|
||||
// say what fields are to be updated
|
||||
$fieldList=array('category', 'type', 'value', 'to_ids');
|
||||
if ($this->Signature->save($this->request->data, true, $fieldList)) {
|
||||
$this->Session->setFlash(__('The attribute has been saved'));
|
||||
|
||||
debug($this->request->data);
|
||||
|
||||
$this->redirect(array('controller' => 'events', 'action' => 'view', $event_id));
|
||||
} else {
|
||||
$this->Session->setFlash(__('The attribute could not be saved. Please, try again.'));
|
||||
|
@ -365,60 +347,55 @@ class SignaturesController extends AppController {
|
|||
if (!$this->Signature->exists()) {
|
||||
throw new NotFoundException(__('Invalid attribute'));
|
||||
}
|
||||
// Replaced by isAuthorized
|
||||
// // only own signatures
|
||||
// $this->Signature->read();
|
||||
// if (!$this->_isAdmin() && $this->Auth->user('org') != $this->Signature->data['Event']['org']) {
|
||||
// throw new UnauthorizedException('You can only delete signatures from your own organisation.');
|
||||
// }
|
||||
|
||||
// only own signatures verified by isAuthorized
|
||||
|
||||
// attachment will be deleted with the beforeDelete() function in the Model
|
||||
if ($this->Signature->delete()) {
|
||||
$this->Session->setFlash(__('Attribute deleted'));
|
||||
} else {
|
||||
$this->Session->setFlash(__('Attribute was not deleted'));
|
||||
}
|
||||
|
||||
|
||||
$this->redirect($this->referer());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
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
|
||||
$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]);
|
||||
|
|
|
@ -14,7 +14,7 @@ class Signature extends AppModel {
|
|||
* @var string
|
||||
*/
|
||||
public $displayField = 'value';
|
||||
|
||||
|
||||
var $order = array("Signature.event_id" => "DESC", "Signature.type" => "ASC");
|
||||
/**
|
||||
* Validation rules
|
||||
|
@ -60,7 +60,7 @@ class Signature extends AppModel {
|
|||
'required' => true,
|
||||
//'last' => false, // Stop validation after this rule
|
||||
//'on' => 'create', // Limit validation to 'create' or 'update' operations
|
||||
|
||||
|
||||
),
|
||||
'category' => array(
|
||||
'rule' => array('inList', array('Payload delivery',
|
||||
|
@ -153,17 +153,17 @@ class Signature extends AppModel {
|
|||
'order' => ''
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
function beforeSave() {
|
||||
// increment the revision number
|
||||
if (empty($this->data['Signature']['revision'])) $this->data['Signature']['revision'] = 0;
|
||||
$this->data['Signature']['revision'] = 1 + $this->data['Signature']['revision'] ;
|
||||
|
||||
|
||||
// always return true after a beforeSave()
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
function beforeDelete() {
|
||||
// delete attachments from the disk
|
||||
if('attachment' == $this->data['Signature']['type'] ||
|
||||
|
@ -179,38 +179,56 @@ class Signature extends AppModel {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function beforeValidate() {
|
||||
// remove leading and trailing blanks
|
||||
$this->data['Signature']['value'] = trim($this->data['Signature']['value']);
|
||||
|
||||
switch($this->data['Signature']['type']) {
|
||||
// lowercase these things
|
||||
case 'md5':
|
||||
case 'sha1':
|
||||
$this->data['Signature']['value'] = strtolower($this->data['Signature']['value']);
|
||||
break;
|
||||
}
|
||||
|
||||
// always return true, otherwise the object cannot be saved
|
||||
return true;
|
||||
}
|
||||
|
||||
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
|
||||
$conditions = array('Signature.event_id' => $event_id,
|
||||
'Signature.type' => $type,
|
||||
'Signature.category' => $category,
|
||||
'Signature.value' => $value
|
||||
);
|
||||
if (isset($this->data['Signature']['id']))
|
||||
$conditions['Signature.id !='] = $this->data['Signature']['id'];
|
||||
|
||||
$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),
|
||||
'conditions' => $conditions,
|
||||
);
|
||||
if (0 != $this->find('count', $params) )
|
||||
return 'Attribute already exists for this event.';
|
||||
|
||||
|
||||
|
||||
// check data validation
|
||||
switch($this->data['Signature']['type']) {
|
||||
// FIXME lowercase hashes
|
||||
case 'md5':
|
||||
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.';
|
||||
return 'Checksum has invalid length or format. Please double check the value or select "other" for a type.';
|
||||
break;
|
||||
case 'sha1':
|
||||
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.';
|
||||
return 'Checksum has invalid length or format. Please double check the value or select "other" for a type.';
|
||||
break;
|
||||
case 'filename':
|
||||
// no newline
|
||||
|
@ -220,7 +238,8 @@ class Signature extends AppModel {
|
|||
case 'filename|md5':
|
||||
// no newline
|
||||
if (!preg_match("#^.*|[0-9a-f]{32}$#", $value))
|
||||
return true;
|
||||
return true;
|
||||
return 'Checksum has invalid length or format. Please double check the value or select "other" for a type.';
|
||||
break;
|
||||
case 'ip-src':
|
||||
$parts = explode("/", $value);
|
||||
|
@ -307,19 +326,19 @@ class Signature extends AppModel {
|
|||
return true;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// default action is to return false
|
||||
return true;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public function isOwnedByOrg($signatureid, $org) {
|
||||
$this->id = $signatureid;
|
||||
$this->read();
|
||||
return $this->data['Event']['org'] === $org;
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
|
@ -329,12 +348,12 @@ class Signature extends AppModel {
|
|||
'Signature.type =' => $signature['type'], );
|
||||
// $fields = array('Event.*');
|
||||
$fields = array('Signature.*');
|
||||
|
||||
|
||||
$similar_events = $this->find('all',array('conditions' => $conditions,
|
||||
'fields' => $fields,
|
||||
'order' => 'Signature.event_id DESC', )
|
||||
);
|
||||
return $similar_events;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue