mirror of https://github.com/MISP/MISP
Merge branch 'master' into develop
Conflicts: app/Controller/EventsController.php app/Model/Attribute.php app/View/Events/view.ctppull/63/head
commit
253d8e1b58
|
@ -3,20 +3,37 @@ Existing bugs:
|
|||
- timeout admin_user.
|
||||
- Somehow there got a user_id 0 in events.
|
||||
- View User and Events got lost(?), but is still there in 0.2.2
|
||||
- no paging on event with lots of attributes.
|
||||
|
||||
Fixed bugs:
|
||||
|
||||
- Fix the "Did you ..." message - path routing.
|
||||
- some admin routing.
|
||||
- timeout user (?).
|
||||
- When loged out by session timeout, re-logging gives an error.
|
||||
timeout user (?).
|
||||
- list servers: error lastpushed/pulledid.
|
||||
- attribute with type filename|md5 -> filename, remove |..
|
||||
- add attachment show only categroies with attachment and malware-sample types.
|
||||
- add attribute, non-valide, correct, ´black-holed´.
|
||||
- Can't edit composite attributes.
|
||||
attribute with type filename|md5 -> filename, remove |..
|
||||
- Attachments - incompatible categories should be filtered out.
|
||||
add attachment show only categroies with attachment and malware-sample types.
|
||||
- Accept uppercase MD5 with composite attribs.
|
||||
- Editing attribute - does not validate.
|
||||
- When a validation error occurs, can't submit it any more.
|
||||
add attribute, non-valide, correct, ´black-holed´.
|
||||
- view event, edit attribute, no validation.
|
||||
- add user, some validation error then extra: authkey not defined.
|
||||
- authError gets displayed before login.
|
||||
- IE, no download (Js) (CakePHP bug #2554 related?)
|
||||
- IE - file download does not work.
|
||||
IE, no download (Js) (CakePHP bug #2554 related?)
|
||||
- uppercases in md5 or sha1 when type filename|md5/sha1 is not lc like type md5/sha1.
|
||||
- search attributes: next page goes to search, search again, then at next page.
|
||||
- non-printable in no-composite attribute and all input behind it gets lost.
|
||||
- Search - paginate broken.
|
||||
search attributes: next page goes to search, search again, then at next page.
|
||||
- non-printable in no-composite attribute and all input behind it gets lost.
|
||||
- no paging on event with lots of attributes (over 50% speedup).
|
||||
- a server containing no MISP gives "XML cannot be read." on publish.
|
||||
- a server having a non-existing internet name gives
|
||||
"php_network_getaddresses: getaddrinfo failed: Name or service not known" on publish
|
||||
and pull.
|
||||
- Edit event already published to other servers, then (re)publish does not work
|
||||
so no other participating servers have the new edited event.
|
||||
- An authkey with any length, so less then 40, can be entered.
|
||||
- Add attribute, do not fill in any, and hit Submit, gives error messages.
|
|
@ -88,13 +88,15 @@ Cache::config('default', array('engine' => 'File'));
|
|||
//Configure::write('CyDefSIG.baseurl', 'https://sig.cyber-defence.be');
|
||||
Configure::write('CyDefSIG.baseurl', 'http://localhost:8888');
|
||||
Configure::write('CyDefSIG.name', 'CyDefSIG');
|
||||
Configure::write('CyDefSIG.header', 'CyDefSIG: Cyber Defence Signature Sharing Platform');
|
||||
Configure::write('CyDefSIG.footer', 'Powered by CyDefSIG © Belgian Defense CERT & NCIRC');
|
||||
//Configure::write('CyDefSIG.logo', '/img/logo_big.gif');
|
||||
Configure::write('CyDefSIG.header', 'CyDefSIG: Cyber Defence Signature Sharing Platform');
|
||||
Configure::write('CyDefSIG.footer', 'Powered by CyDefSIG © Belgian Defense CERT & NCIRC');
|
||||
Configure::write('CyDefSIG.org', 'BE MOD'); // if sync this will be Event.org content on the peer side
|
||||
Configure::write('CyDefSIG.logo', 'orgs/MIL.be.png'); // used in Events::index for owned events
|
||||
|
||||
|
||||
Configure::write('CyDefSIG.showorg', 'false'); // show the name of the organisation that uploaded the data
|
||||
Configure::write('CyDefSIG.sync', 'true'); // enable features related to syncing with other CyDefSIG instances
|
||||
Configure::write('CyDefSIG.showorg', 'true'); // show the name/flag of the organisation that uploaded the data
|
||||
Configure::write('CyDefSIG.showowner', 'false'); // show the email of the owner that uploaded the data
|
||||
Configure::write('CyDefSIG.sync', 'false'); // enable features related to syncing with other CyDefSIG instances
|
||||
Configure::write('CyDefSIG.email', 'no-reply@sig.mil.be'); // email from for all the mails
|
||||
|
||||
Configure::write('GnuPG.onlyencrypted', 'true'); // only allow encrypted email, do not allow plaintext mails
|
||||
|
@ -105,6 +107,23 @@ Configure::write('GnuPG.homedir', '/Users/chri/Documents/Work/Projects/201107-Cy
|
|||
Configure::write('SecureAuth.amount', 5); // the maximum amount of failed logins
|
||||
Configure::write('SecureAuth.expire', 300); // the time-window for the maximum amount of logins in seconds
|
||||
|
||||
Configure::write('CyDefSIG.correlation', 'sql'); // correlation between attributes of events.
|
||||
// possible values:
|
||||
// - default, like it was
|
||||
// - db, correlation in database
|
||||
// - sql, selection on event i.s.o. per attribute (improvement possible)
|
||||
/**
|
||||
* Network activity, ip-src
|
||||
* 30 class-C network ip addresses
|
||||
* (time in ms)
|
||||
*
|
||||
* default db sql
|
||||
* all 25366 16601 15941
|
||||
* 24839 16604 15611
|
||||
* paginated 16759 8447 6615
|
||||
* 17734 8639 8846
|
||||
*/
|
||||
|
||||
/**
|
||||
* The settings below can be used to set additional paths to models, views and controllers.
|
||||
*
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
/*
|
||||
* Reset a password
|
||||
*
|
||||
* arg0 = email
|
||||
* arg1 = new password
|
||||
*/
|
||||
class PasswordShell extends AppShell {
|
||||
public $uses = array('User');
|
||||
|
||||
public function main() {
|
||||
// get the users that need their password hashed
|
||||
$results = $this->User->findByEmail($this->args[0]);
|
||||
//$this->out(print_r($results, true));
|
||||
App::import('Component','Auth');
|
||||
$this->Auth = new AuthComponent(new ComponentCollection());
|
||||
|
||||
$count = count($results);
|
||||
|
||||
$results['User']['password'] = $this->args[1];
|
||||
$results['User']['confirm_password'] = $this->args[1];
|
||||
|
||||
if (!$this->User->save($results)) {
|
||||
echo 'Could not update account for User.id = ', $results['User']['id'], PHP_EOL;
|
||||
debug($this->User->validationErrors);
|
||||
$this->out(print_r($this->User->invalidFields(), true));
|
||||
}
|
||||
|
||||
echo 'Updated ', PHP_EOL;
|
||||
exit;
|
||||
}
|
||||
}
|
|
@ -258,7 +258,7 @@ class AppController extends Controller {
|
|||
|
||||
}
|
||||
|
||||
function miratemisp02to10() {
|
||||
function migratemisp02to10() {
|
||||
if (!self::_isAdmin()) throw new NotFoundException();
|
||||
|
||||
// add missing columns, rename other columns
|
||||
|
@ -297,7 +297,7 @@ class AppController extends Controller {
|
|||
}
|
||||
}
|
||||
|
||||
function miratemisp10to11() {
|
||||
function migratemisp10to11() {
|
||||
if (!self::_isAdmin()) throw new NotFoundException();
|
||||
|
||||
// add missing columns, rename other columns
|
||||
|
@ -311,6 +311,33 @@ class AppController extends Controller {
|
|||
$result = $this->{$this->modelClass}->query($query);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function generateCorrelation() {
|
||||
if (!self::_isAdmin()) throw new NotFoundException();
|
||||
|
||||
$this->loadModel('Correlation');
|
||||
$this->loadModel('Attribute');
|
||||
$fields = array('Attribute.id', 'Attribute.event_id', 'Event.date');
|
||||
// get all attributes..
|
||||
$attributes = $this->Attribute->find('all',array('recursive' => 0));
|
||||
// for all attributes..
|
||||
foreach ($attributes as $attribute) {
|
||||
$this->Attribute->setRelatedAttributes($attribute['Attribute'], $fields=array());
|
||||
|
||||
// // i want to keep this in repo for a moment
|
||||
// $relatedAttributes = $this->Attribute->getRelatedAttributes($attribute['Attribute'], $fields);
|
||||
// if ($relatedAttributes) {
|
||||
// foreach ($relatedAttributes as $relatedAttribute) {
|
||||
// // // and store into table
|
||||
// $this->Correlation->create();
|
||||
// $this->Correlation->save(array('Correlation' => array(
|
||||
// '1_event_id' => $attribute['Attribute']['event_id'], '1_attribute_id' => $attribute['Attribute']['id'],
|
||||
// 'event_id' => $relatedAttribute['Attribute']['event_id'], 'attribute_id' => $relatedAttribute['Attribute']['id'],
|
||||
// 'date' => $relatedAttribute['Event']['date'])));
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
// TODO ACL, 6b: check on Group and per Model (not used)
|
||||
|
|
|
@ -25,6 +25,20 @@ class AttributesController extends AppController {
|
|||
$this->Security->csrfUseOnce = false;
|
||||
}
|
||||
$this->Security->validatePost = false;
|
||||
|
||||
// convert uuid to id if present in the url, and overwrite id field
|
||||
if (isset($this->params->query['uuid'])) {
|
||||
$params = array(
|
||||
'conditions' => array('Attribute.uuid' => $this->params->query['uuid']),
|
||||
'recursive' => 0,
|
||||
'fields' => 'Attribute.id'
|
||||
);
|
||||
$result = $this->Attribute->find('first', $params);
|
||||
if (isset($result['Attribute']) && isset($result['Attribute']['id'])) {
|
||||
$id = $result['Attribute']['id'];
|
||||
$this->params->addParams(array('pass' => array($id))); // FIXME find better way to change id variable if uuid is found. params->url and params->here is not modified accordingly now
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -76,7 +90,7 @@ class AttributesController extends AppController {
|
|||
|
||||
// Give error if someone tried to submit a attribute with attachment or malware-sample type.
|
||||
// TODO change behavior attachment options - this is bad ... it should rather by a messagebox or should be filtered out on the view level
|
||||
if($this->Attribute->typeIsAttachment($this->request->data['Attribute']['type'])) {
|
||||
if(isset($this->request->data['Attribute']['type']) && $this->Attribute->typeIsAttachment($this->request->data['Attribute']['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', $this->request->data['Attribute']['event_id']));
|
||||
}
|
||||
|
@ -388,45 +402,85 @@ class AttributesController extends AppController {
|
|||
* @return void
|
||||
*/
|
||||
public function delete($id = null) {
|
||||
if (!$this->request->is('post')) {
|
||||
if (!$this->request->is('post') && !$this->_isRest()) {
|
||||
throw new MethodNotAllowedException();
|
||||
}
|
||||
$this->Attribute->id = $id;
|
||||
|
||||
$this->Attribute->id = $id;
|
||||
if (!$this->Attribute->exists()) {
|
||||
throw new NotFoundException(__('Invalid attribute'));
|
||||
}
|
||||
// only own attributes verified by isAuthorized
|
||||
|
||||
|
||||
if ('true' == Configure::read('CyDefSIG.sync')) {
|
||||
// find the uuid
|
||||
$result = $this->Attribute->findById($id);
|
||||
$uuid = $result['Attribute']['uuid'];
|
||||
}
|
||||
|
||||
// attachment will be deleted with the beforeDelete() function in the Model
|
||||
if ($this->Attribute->delete()) {
|
||||
|
||||
// delete the attribute from remote servers
|
||||
if ('true' == Configure::read('CyDefSIG.sync')) {
|
||||
// find the uuid
|
||||
$this->_deleteAttributeFromServers($uuid);
|
||||
}
|
||||
|
||||
$this->Session->setFlash(__('Attribute deleted'));
|
||||
} else {
|
||||
$this->Session->setFlash(__('Attribute was not deleted'));
|
||||
}
|
||||
|
||||
$this->redirect($this->referer());
|
||||
if (!$this->_isRest()) $this->redirect($this->referer()); // TODO check
|
||||
else $this->redirect(array('action' => 'index'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes this specific attribute from all remote servers
|
||||
* TODO move this to a component(?)
|
||||
*/
|
||||
function _deleteAttributeFromServers($uuid) {
|
||||
$result = $this->Attribute->find('first', array('conditions' => array('Attribute.uuid' => $uuid)));
|
||||
$id = $result['Attribute']['id'];
|
||||
|
||||
// make sure we have all the data of the Attribute
|
||||
$this->Attribute->id=$id;
|
||||
$this->Attribute->recursive=1;
|
||||
$this->Attribute->read();
|
||||
|
||||
// get a list of the servers
|
||||
$this->loadModel('Server');
|
||||
$servers = $this->Server->find('all', array());
|
||||
|
||||
// iterate over the servers and upload the attribute
|
||||
if(empty($servers))
|
||||
return;
|
||||
|
||||
App::uses('HttpSocket', 'Network/Http');
|
||||
$HttpSocket = new HttpSocket();
|
||||
foreach ($servers as &$server) {
|
||||
$this->Attribute->deleteAttributeFromServer($this->Attribute->data, $server, $HttpSocket);
|
||||
}
|
||||
}
|
||||
|
||||
public function search() {
|
||||
|
||||
|
||||
$fullAddress = '/attributes/search';
|
||||
|
||||
|
||||
if ($this->request->here == $fullAddress) {
|
||||
|
||||
|
||||
$this->set('attr_descriptions', $this->Attribute->field_descriptions);
|
||||
$this->set('type_definitions', $this->Attribute->type_definitions);
|
||||
$this->set('category_definitions', $this->Attribute->category_definitions);
|
||||
|
||||
|
||||
// reset the paginate_conditions
|
||||
$this->Session->write('paginate_conditions',array());
|
||||
|
||||
|
||||
if ($this->request->is('post') && ($this->request->here == $fullAddress)) {
|
||||
$keyword = $this->request->data['Attribute']['keyword'];
|
||||
$type = $this->request->data['Attribute']['type'];
|
||||
$category = $this->request->data['Attribute']['category'];
|
||||
|
||||
|
||||
// search the db
|
||||
$conditions = array();
|
||||
if($keyword) {
|
||||
|
@ -446,19 +500,19 @@ class AttributesController extends AppController {
|
|||
|
||||
// and store into session
|
||||
$this->Session->write('paginate_conditions',$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, array_keys($this->Attribute->type_definitions));
|
||||
$types = $this->_arrayToValuesIndexArray($types);
|
||||
$this->set('types',compact('types'));
|
||||
|
||||
|
||||
// combobox for categories
|
||||
$categories = array('ALL');
|
||||
$categories = array_merge($categories, $this->Attribute->validate['category']['rule'][1]);
|
||||
|
@ -474,9 +528,9 @@ class AttributesController extends AppController {
|
|||
// re-get pagination
|
||||
$this->paginate = $this->Session->read('paginate_conditions');
|
||||
$this->set('attributes', $this->paginate());
|
||||
|
||||
|
||||
// set the same view as the index page
|
||||
$this->render('index');
|
||||
$this->render('index');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -517,39 +571,100 @@ class AttributesController extends AppController {
|
|||
// get related
|
||||
$relatedAttributes = array();
|
||||
$this->loadModel('Attribute');
|
||||
$fields = array('Attribute.id', 'Attribute.event_id', 'Attribute.uuid');
|
||||
foreach ($event['Attribute'] as &$attribute) {
|
||||
$relatedAttributes[$attribute['id']] = $this->Attribute->getRelatedAttributes($attribute, $fields);
|
||||
// for REST requests also add the encoded attachment
|
||||
if ($this->_isRest() && $this->Attribute->typeIsAttachment($attribute['type'])) {
|
||||
// LATER check if this has a serious performance impact on XML conversion and memory usage
|
||||
$encoded_file = $this->Attribute->base64EncodeAttachment($attribute);
|
||||
$attribute['data'] = $encoded_file;
|
||||
}
|
||||
}
|
||||
$this->set('relatedAttributes', $relatedAttributes);
|
||||
if ('db' == Configure::read('CyDefSIG.correlation')) {
|
||||
$this->loadModel('Correlation');
|
||||
$fields = array('Correlation.event_id', 'Correlation.attribute_id', 'Correlation.date');
|
||||
$fields2 = array('Correlation.1_attribute_id','Correlation.event_id', 'Correlation.attribute_id', 'Correlation.date');
|
||||
$relatedAttributes2 = array();
|
||||
$relatedAttributes2 = $this->Correlation->find('all',array(
|
||||
'fields' => $fields2,
|
||||
'conditions' => array(
|
||||
'OR' => array(
|
||||
'Correlation.1_event_id' => $id
|
||||
)
|
||||
),
|
||||
'recursive' => 0));
|
||||
foreach ($relatedAttributes2 as $relatedAttribute2) {
|
||||
$relatedAttributes[$relatedAttribute2['Correlation']['1_attribute_id']][] = $relatedAttribute2;
|
||||
}
|
||||
|
||||
// search for related Events using the results form the related attributes
|
||||
// This is a lot faster (only additional query) than $this->Event->getRelatedEvents()
|
||||
$relatedEventIds = array();
|
||||
$relatedEvents = array();
|
||||
foreach ($relatedAttributes as &$relatedAttribute) {
|
||||
if (null == $relatedAttribute) continue;
|
||||
foreach ($relatedAttribute as &$item) {
|
||||
$relatedEventsIds[] = $item['Attribute']['event_id'];
|
||||
foreach ($event['Attribute'] as &$attribute) {
|
||||
// for REST requests also add the encoded attachment
|
||||
if ($this->_isRest() && $this->Attribute->typeIsAttachment($attribute['type'])) {
|
||||
// LATER check if this has a serious performance impact on XML conversion and memory usage
|
||||
$encoded_file = $this->Attribute->base64EncodeAttachment($attribute);
|
||||
$attribute['data'] = $encoded_file;
|
||||
}
|
||||
}
|
||||
|
||||
// search for related Events using the results form the related attributes
|
||||
// This is a lot faster (only additional query) than $this->Event->getRelatedEvents()
|
||||
$relatedEventIds = array();
|
||||
$relatedEventDates = array();
|
||||
$relatedEvents = array();
|
||||
foreach ($relatedAttributes as &$relatedAttribute) {
|
||||
if (null == $relatedAttribute) continue;
|
||||
foreach ($relatedAttribute as &$item) {
|
||||
$relatedEventsIds[] = $item['Correlation']['event_id'];
|
||||
$relatedEventsDates[$item['Correlation']['event_id']] = $item['Correlation']['date'];
|
||||
}
|
||||
}
|
||||
|
||||
arsort($relatedEventsDates);
|
||||
if (isset($relatedEventsDates)) {
|
||||
$relatedEventsDates = array_unique($relatedEventsDates);
|
||||
foreach ($relatedEventsDates as $key => $relatedEventsDate) {
|
||||
$relatedEvents[] = array('id' => $key, 'date' => $relatedEventsDate);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$fields = array('Attribute.id', 'Attribute.event_id', 'Attribute.uuid');
|
||||
if ('sql' == Configure::read('CyDefSIG.correlation')) {
|
||||
$double = $this->Attribute->doubleAttributes();
|
||||
}
|
||||
foreach ($event['Attribute'] as &$attribute) {
|
||||
if ('sql' == Configure::read('CyDefSIG.correlation')) {
|
||||
if (in_array($attribute['value1'],$double) || in_array($attribute['value2'],$double)) {
|
||||
$relatedAttributes[$attribute['id']] = $this->Attribute->getRelatedAttributes($attribute, $fields);
|
||||
} else {
|
||||
$relatedAttributes[$attribute['id']] = array();
|
||||
}
|
||||
} else {
|
||||
$relatedAttributes[$attribute['id']] = $this->Attribute->getRelatedAttributes($attribute, $fields);
|
||||
}
|
||||
// for REST requests also add the encoded attachment
|
||||
if ($this->_isRest() && $this->Attribute->typeIsAttachment($attribute['type'])) {
|
||||
// LATER check if this has a serious performance impact on XML conversion and memory usage
|
||||
$encoded_file = $this->Attribute->base64EncodeAttachment($attribute);
|
||||
$attribute['data'] = $encoded_file;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isset($relatedEventsIds)) {
|
||||
$relatedEventsIds = array_unique($relatedEventsIds);
|
||||
$find_params = array(
|
||||
'conditions' => array('OR' => array('Event.id' => $relatedEventsIds)), //array of conditions
|
||||
'recursive' => 0, //int
|
||||
'fields' => array('Event.id', 'Event.date', 'Event.uuid'), //array of field names
|
||||
'order' => array('Event.date DESC'), //string or array defining order
|
||||
);
|
||||
$relatedEvents = $this->Event->find('all', $find_params);
|
||||
}
|
||||
$this->set('relatedEvents', $relatedEvents);
|
||||
|
||||
// search for related Events using the results form the related attributes
|
||||
// This is a lot faster (only additional query) than $this->Event->getRelatedEvents()
|
||||
$relatedEventIds = array();
|
||||
$relatedEvents = array();
|
||||
foreach ($relatedAttributes as &$relatedAttribute) {
|
||||
if (null == $relatedAttribute) continue;
|
||||
foreach ($relatedAttribute as &$item) {
|
||||
$relatedEventsIds[] = $item['Attribute']['event_id'];
|
||||
}
|
||||
}
|
||||
if (isset($relatedEventsIds)) {
|
||||
$relatedEventsIds = array_unique($relatedEventsIds);
|
||||
$find_params = array(
|
||||
'conditions' => array('OR' => array('Event.id' => $relatedEventsIds)), //array of conditions
|
||||
'recursive' => 0, //int
|
||||
'fields' => array('Event.id', 'Event.date', 'Event.uuid'), //array of field names
|
||||
'order' => array('Event.date DESC'), //string or array defining order
|
||||
);
|
||||
$relatedEvents = $this->Event->find('all', $find_params);
|
||||
}
|
||||
}
|
||||
$this->set('correlation', Configure::read('CyDefSIG.correlation'));
|
||||
$this->set('relatedAttributes', $relatedAttributes);
|
||||
|
||||
$this->set('relatedEvents', $relatedEvents);
|
||||
|
||||
$this->set('categories', $this->Attribute->validate['category']['rule'][1]);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
<?php
|
||||
|
||||
class HidsMd5ExportComponent extends Component {
|
||||
|
||||
public $rules = array();
|
||||
|
||||
|
||||
function explain() {
|
||||
// unshift add in reverse order
|
||||
array_unshift($this->rules, '# ');
|
||||
array_unshift($this->rules, '# Keep in mind MD5 is not collision resistant');
|
||||
array_unshift($this->rules, '# These HIDS export contains MD5 checksums.');
|
||||
}
|
||||
|
||||
function suricataRules($items) {
|
||||
|
||||
$itemsDone = array();
|
||||
foreach ($items as &$item) {
|
||||
|
||||
|
||||
# md5
|
||||
$rule_format = '%s';
|
||||
|
||||
$attribute = &$item['Attribute'];
|
||||
|
||||
switch ($attribute['type']) {
|
||||
case 'md5':
|
||||
if (!in_array ($attribute['value1'], $itemsDone)) {
|
||||
$this->checksumRule($rule_format, $attribute);
|
||||
$itemsDone[] = $attribute['value1'];
|
||||
}
|
||||
break;
|
||||
case 'filename|md5':
|
||||
case 'malware-sample':
|
||||
if (!in_array ($attribute['value2'], $itemsDone)) {
|
||||
$this->partRule($rule_format, $attribute);
|
||||
$itemsDone[] = $attribute['value2'];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
sort($this->rules);
|
||||
$this->explain();
|
||||
|
||||
return $this->rules;
|
||||
|
||||
|
||||
}
|
||||
|
||||
function checksumRule($rule_format, $attribute) {
|
||||
$this->rules[] = sprintf($rule_format,
|
||||
$attribute['value1'] // md5
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
function partRule($rule_format, $attribute) {
|
||||
$this->rules[] = sprintf($rule_format,
|
||||
$attribute['value2'] // md5
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
<?php
|
||||
|
||||
class HidsSha1ExportComponent extends Component {
|
||||
|
||||
public $rules = array();
|
||||
|
||||
function explain() {
|
||||
// unshift add in reverse order
|
||||
array_unshift($this->rules, '# ');
|
||||
array_unshift($this->rules, '# Keep in mind SHA-1 still has a theoretical collision possibility');
|
||||
array_unshift($this->rules, '# These HIDS export contains SHA-1 checksums.');
|
||||
}
|
||||
function suricataRules($items) {
|
||||
|
||||
$itemsDone = array();
|
||||
|
||||
foreach ($items as &$item) {
|
||||
|
||||
|
||||
# sha-1
|
||||
$rule_format = '%s';
|
||||
|
||||
$attribute = &$item['Attribute'];
|
||||
|
||||
switch ($attribute['type']) {
|
||||
case 'sha1':
|
||||
if (!in_array ($attribute['value1'], $itemsDone)) {
|
||||
$this->checksumRule($rule_format, $attribute);
|
||||
$itemsDone[] = $attribute['value1'];
|
||||
}
|
||||
break;
|
||||
case 'filename|sha1':
|
||||
if (!in_array ($attribute['value2'], $itemsDone)) {
|
||||
$this->partRule($rule_format, $attribute);
|
||||
$itemsDone[] = $attribute['value2'];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
sort($this->rules);
|
||||
$this->explain();
|
||||
|
||||
return $this->rules;
|
||||
|
||||
|
||||
}
|
||||
|
||||
function checksumRule($rule_format, $attribute) {
|
||||
$this->rules[] = sprintf($rule_format,
|
||||
$attribute['value1'] // md5
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
function partRule($rule_format, $attribute) {
|
||||
$this->rules[] = sprintf($rule_format,
|
||||
$attribute['value2'] // md5
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -3,6 +3,7 @@
|
|||
class NidsExportComponent extends Component {
|
||||
|
||||
public $rules = array();
|
||||
public $classtype = 'trojan-activity';
|
||||
|
||||
function explain() {
|
||||
$this->rules[] = '# These NIDS rules contain some variables that need to exist in your configuration.';
|
||||
|
@ -16,10 +17,10 @@ class NidsExportComponent extends Component {
|
|||
}
|
||||
|
||||
function suricataRules($items, $start_sid) {
|
||||
$this->whitelist = $this->populateWhitelist();
|
||||
|
||||
$this->explain();
|
||||
|
||||
$classtype = 'trojan-activity';
|
||||
foreach ($items as &$item) {
|
||||
switch ($item['Event']['risk']) {
|
||||
case 'Undefined':
|
||||
|
@ -41,7 +42,7 @@ class NidsExportComponent extends Component {
|
|||
# proto src_ip src_port direction dst_ip dst_port msg rule_content tag sid rev
|
||||
$rule_format_msg = 'msg: "CyDefSIG e'.$item['Event']['id'].' %s"';
|
||||
$rule_format_reference = 'reference:url,'.Configure::read('CyDefSIG.baseurl').'/events/view/'.$item['Event']['id'];
|
||||
$rule_format = 'alert %s %s %s %s %s %s ('.$rule_format_msg.'; %s %s classtype:'.$classtype.'; sid:%d; rev:%d; priority:'.$priority.'; '.$rule_format_reference.';) ';
|
||||
$rule_format = '%salert %s %s %s %s %s %s ('.$rule_format_msg.'; %s %s classtype:'.$this->classtype.'; sid:%d; rev:%d; priority:'.$priority.'; '.$rule_format_reference.';) ';
|
||||
|
||||
$sid = $start_sid+($item['Attribute']['id']*10); // leave 9 possible rules per attribute type
|
||||
$attribute = &$item['Attribute'];
|
||||
|
@ -82,7 +83,7 @@ class NidsExportComponent extends Component {
|
|||
$this->userAgentRule($rule_format, $attribute, $sid);
|
||||
break;
|
||||
case 'snort':
|
||||
$this->snortRule($rule_format, $attribute, $sid);
|
||||
$this->snortRule($rule_format, $attribute, $sid, $rule_format_msg, $rule_format_reference);
|
||||
default:
|
||||
break;
|
||||
|
||||
|
@ -99,7 +100,9 @@ class NidsExportComponent extends Component {
|
|||
}
|
||||
|
||||
function ipDstRule($rule_format, $attribute, &$sid) {
|
||||
$overruled = in_array($attribute['value'], $this->whitelist);
|
||||
$this->rules[] = sprintf($rule_format,
|
||||
($overruled) ? '#OVERRULED BY WHITELIST# ' : '',
|
||||
'ip', // proto
|
||||
'$HOME_NET', // src_ip
|
||||
'any', // src_port
|
||||
|
@ -116,7 +119,9 @@ class NidsExportComponent extends Component {
|
|||
}
|
||||
|
||||
function ipSrcRule($rule_format, $attribute, &$sid) {
|
||||
$this->rules[] = sprintf($rule_format,
|
||||
$overruled = in_array($attribute['value'], $this->whitelist);
|
||||
$this->rules[] = sprintf($rule_format,
|
||||
($overruled) ? '#OVERRULED BY WHITELIST# ' : '',
|
||||
'ip', // proto
|
||||
$attribute['value'], // src_ip
|
||||
'any', // src_port
|
||||
|
@ -132,8 +137,9 @@ class NidsExportComponent extends Component {
|
|||
}
|
||||
|
||||
function emailSrcRule($rule_format, $attribute, &$sid) {
|
||||
$content = 'flow:established,to_server; content:"MAIL FROM|3a|"; nocase; content:"'.$attribute['value'].'"; nocase;';
|
||||
$content = 'flow:established,to_server; content:"MAIL FROM|3a|"; nocase; content:"'.$attribute['value'].'"; nocase;';
|
||||
$this->rules[] = sprintf($rule_format,
|
||||
(false) ? '#OVERRULED BY WHITELIST# ' : '',
|
||||
'tcp', // proto
|
||||
'$EXTERNAL_NET', // src_ip
|
||||
'any', // src_port
|
||||
|
@ -149,8 +155,9 @@ class NidsExportComponent extends Component {
|
|||
}
|
||||
|
||||
function emailDstRule($rule_format, $attribute, &$sid) {
|
||||
$content = 'flow:established,to_server; content:"RCPT TO|3a|"; nocase; content:"'.$attribute['value'].'"; nocase;';
|
||||
$this->rules[] = sprintf($rule_format,
|
||||
$content = 'flow:established,to_server; content:"RCPT TO|3a|"; nocase; content:"'.$attribute['value'].'"; nocase;';
|
||||
$this->rules[] = sprintf($rule_format,
|
||||
(false) ? '#OVERRULED BY WHITELIST# ' : '',
|
||||
'tcp', // proto
|
||||
'$EXTERNAL_NET', // src_ip
|
||||
'any', // src_port
|
||||
|
@ -166,9 +173,10 @@ class NidsExportComponent extends Component {
|
|||
}
|
||||
|
||||
function emailSubjectRule($rule_format, $attribute, &$sid) {
|
||||
// LATER nids - email-subject rule might not match because of line-wrapping
|
||||
// LATER nids - email-subject rule might not match because of line-wrapping
|
||||
$content = 'flow:established,to_server; content:"Subject|3a|"; nocase; content:"'.$attribute['value'].'"; nocase;';
|
||||
$this->rules[] = sprintf($rule_format,
|
||||
(false) ? '#OVERRULED BY WHITELIST# ' : '',
|
||||
'tcp', // proto
|
||||
'$EXTERNAL_NET', // src_ip
|
||||
'any', // src_port
|
||||
|
@ -184,9 +192,10 @@ class NidsExportComponent extends Component {
|
|||
}
|
||||
|
||||
function emailAttachmentRule($rule_format, $attribute, &$sid) {
|
||||
// LATER nids - email-attachment rule might not match because of line-wrapping
|
||||
// LATER nids - email-attachment rule might not match because of line-wrapping
|
||||
$content = 'flow:established,to_server; content:"Content-Disposition: attachment|3b| filename=|22|"; content:"'.$attribute['value'].'|22|";';
|
||||
$this->rules[] = sprintf($rule_format,
|
||||
(false) ? '#OVERRULED BY WHITELIST# ' : '',
|
||||
'tcp', // proto
|
||||
'$EXTERNAL_NET', // src_ip
|
||||
'any', // src_port
|
||||
|
@ -202,8 +211,10 @@ class NidsExportComponent extends Component {
|
|||
}
|
||||
|
||||
function hostnameRule($rule_format, $attribute, &$sid) {
|
||||
$content = 'content:"'.$this->dnsNameToRawFormat($attribute['value'], 'hostname').'"; nocase;';
|
||||
$this->rules[] = sprintf($rule_format,
|
||||
$overruled = $this->checkNames($attribute['value']);
|
||||
$content = 'content:"'.$this->dnsNameToRawFormat($attribute['value'], 'hostname').'"; nocase;';
|
||||
$this->rules[] = sprintf($rule_format,
|
||||
($overruled) ? '#OVERRULED BY WHITELIST# ' : '',
|
||||
'udp', // proto
|
||||
'any', // src_ip
|
||||
'any', // src_port
|
||||
|
@ -217,7 +228,8 @@ class NidsExportComponent extends Component {
|
|||
1 // rev
|
||||
);
|
||||
$sid++;
|
||||
$this->rules[] = sprintf($rule_format,
|
||||
$this->rules[] = sprintf($rule_format,
|
||||
($overruled) ? '#OVERRULED BY WHITELIST# ' : '',
|
||||
'tcp', // proto
|
||||
'any', // src_ip
|
||||
'any', // src_port
|
||||
|
@ -233,8 +245,9 @@ class NidsExportComponent extends Component {
|
|||
$sid++;
|
||||
// also do http requests
|
||||
// warning: only suricata compatible
|
||||
$content = 'flow:to_server,established; content: "Host: '.$attribute['value'].'"; nocase; http_header; ';
|
||||
$content = 'flow:to_server,established; content: "Host: '.$attribute['value'].'"; nocase; http_header; pcre: "/[^A-Za-z0-9-]'.preg_quote($attribute['value']).'[^A-Za-z0-9-]/";';
|
||||
$this->rules[] = sprintf($rule_format,
|
||||
($overruled) ? '#OVERRULED BY WHITELIST# ' : '',
|
||||
'http', // proto
|
||||
'$HOME_NET', // src_ip
|
||||
'any', // src_port
|
||||
|
@ -248,9 +261,12 @@ class NidsExportComponent extends Component {
|
|||
1 // rev
|
||||
);
|
||||
}
|
||||
|
||||
function domainRule($rule_format, $attribute, &$sid) {
|
||||
$content = 'content:"'.$this->dnsNameToRawFormat($attribute['value']).'"; nocase;';
|
||||
$overruled = $this->checkNames($attribute['value']);
|
||||
$content = 'content:"'.$this->dnsNameToRawFormat($attribute['value']).'"; nocase;';
|
||||
$this->rules[] = sprintf($rule_format,
|
||||
($overruled) ? '#OVERRULED BY WHITELIST# ' : '',
|
||||
'udp', // proto
|
||||
'any', // src_ip
|
||||
'any', // src_port
|
||||
|
@ -265,6 +281,7 @@ class NidsExportComponent extends Component {
|
|||
);
|
||||
$sid++;
|
||||
$this->rules[] = sprintf($rule_format,
|
||||
($overruled) ? '#OVERRULED BY WHITELIST# ' : '',
|
||||
'tcp', // proto
|
||||
'any', // src_ip
|
||||
'any', // src_port
|
||||
|
@ -280,8 +297,9 @@ class NidsExportComponent extends Component {
|
|||
$sid++;
|
||||
// also do http requests,
|
||||
// warning: only suricata compatible
|
||||
$content = 'flow:to_server,established; content: "Host:"; nocase; http_header; content:"'.$attribute['value'].'"; nocase; http_header; ';
|
||||
$content = 'flow:to_server,established; content: "Host:"; nocase; http_header; content:"'.$attribute['value'].'"; nocase; http_header; pcre: "/[^A-Za-z0-9-]'.preg_quote($attribute['value']).'[^A-Za-z0-9-]/";';
|
||||
$this->rules[] = sprintf($rule_format,
|
||||
($overruled) ? '#OVERRULED BY WHITELIST# ' : '',
|
||||
'http', // proto
|
||||
'$HOME_NET', // src_ip
|
||||
'any', // src_port
|
||||
|
@ -297,9 +315,13 @@ class NidsExportComponent extends Component {
|
|||
}
|
||||
|
||||
function urlRule($rule_format, $attribute, &$sid) {
|
||||
// warning: only suricata compatible
|
||||
// TODO in hindsight, an url should not be excluded given a host or domain name.
|
||||
// $hostpart = parse_url($attribute['value'], PHP_URL_HOST);
|
||||
// $overruled = $this->checkNames($hostpart);
|
||||
// warning: only suricata compatible
|
||||
$content = 'flow:to_server,established; content:"'.$attribute['value'].'"; nocase; http_uri;';
|
||||
$this->rules[] = sprintf($rule_format,
|
||||
(false) ? '#OVERRULED BY WHITELIST# ' : '',
|
||||
'http', // proto
|
||||
'$HOME_NET', // src_ip
|
||||
'any', // src_port
|
||||
|
@ -319,7 +341,7 @@ class NidsExportComponent extends Component {
|
|||
|
||||
}
|
||||
|
||||
function snortRule($rule_format, $attribute, &$sid) {
|
||||
function snortRule($rule_format, $attribute, &$sid, $rule_format_msg, $rule_format_reference) {
|
||||
// LATER nids - test using lots of snort rules.
|
||||
$tmp_rule = $attribute['value'];
|
||||
|
||||
|
@ -335,7 +357,7 @@ class NidsExportComponent extends Component {
|
|||
if (null == $tmp_rule ) break; // don't output the rule on error with the regex
|
||||
$tmp_rule = preg_replace('/rev\s*:\s*[0-9]+\s*;/', 'rev:1;', $tmp_rule, -1, $replace_count['rev']);
|
||||
if (null == $tmp_rule ) break; // don't output the rule on error with the regex
|
||||
$tmp_rule = preg_replace('/classtype:[a-zA-Z_-]+;/', 'classtype:'.$classtype.';', $tmp_rule, -1, $replace_count['classtype']);
|
||||
$tmp_rule = preg_replace('/classtype:[a-zA-Z_-]+;/', 'classtype:'.$this->classtype.';', $tmp_rule, -1, $replace_count['classtype']);
|
||||
if (null == $tmp_rule ) break; // don't output the rule on error with the regex
|
||||
$tmp_message = sprintf($rule_format_msg, 'snort-rule');
|
||||
$tmp_rule = preg_replace('/msg\s*:\s*".*?"\s*;/', $tmp_message.';', $tmp_rule, -1, $replace_count['msg']);
|
||||
|
@ -353,7 +375,7 @@ class NidsExportComponent extends Component {
|
|||
} if (0 == $replace_count['rev']) {
|
||||
$extra_for_rule .= 'rev:1;';
|
||||
} if (0 == $replace_count['classtype']) {
|
||||
$extra_for_rule .= 'classtype:'.$classtype.';';
|
||||
$extra_for_rule .= 'classtype:'.$this->classtype.';';
|
||||
} if (0 == $replace_count['msg']) {
|
||||
$extra_for_rule .= $tmp_message.';';
|
||||
} if (0 == $replace_count['reference']) {
|
||||
|
@ -421,7 +443,41 @@ class NidsExportComponent extends Component {
|
|||
return $rawName;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
public $whitelist = array();
|
||||
|
||||
function populateWhitelist() {
|
||||
$whitelistCheck = array();
|
||||
|
||||
$this->Whitelist = ClassRegistry::init('Whitelist');
|
||||
$whitelist = $this->Whitelist->find('all', array('recursive' => 0,'fields' => 'name'));
|
||||
|
||||
// loop through whitelist table,
|
||||
foreach ($whitelist as $whitelistItem) {
|
||||
$ipl = array();
|
||||
$ipl = $this->nametoipl($whitelistItem['Whitelist']['name']);
|
||||
$whitelistCheck = array_merge($whitelistCheck,$ipl);
|
||||
if (count($ipl) > 0 && $whitelistItem != $ipl[0]) {
|
||||
$dummyArray = array();
|
||||
$dummyArray[] = $whitelistItem['Whitelist']['name'];
|
||||
$whitelistCheck = array_merge($whitelistCheck,$dummyArray);
|
||||
}
|
||||
}
|
||||
return $whitelistCheck;
|
||||
}
|
||||
|
||||
function nametoipl($name) {
|
||||
if (!$ips = gethostbynamel($name)) $ips = array();
|
||||
return $ips;
|
||||
}
|
||||
|
||||
function checkNames($name) {
|
||||
$ipl = $this->nametoipl($name);
|
||||
$ipl[] = $name;
|
||||
$overruled = false;
|
||||
foreach ($ipl as $ip) {
|
||||
$overruled = in_array($ip, $this->whitelist);
|
||||
if ($overruled) break;
|
||||
}
|
||||
return $overruled;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,8 @@ class EventsController extends AppController {
|
|||
'Security',
|
||||
'Email',
|
||||
'RequestHandler',
|
||||
'HidsMd5Export',
|
||||
'HidsSha1Export',
|
||||
'NidsExport'
|
||||
);
|
||||
public $paginate = array(
|
||||
|
@ -36,6 +38,8 @@ class EventsController extends AppController {
|
|||
// what pages are allowed for non-logged-in users
|
||||
$this->Auth->allow('xml');
|
||||
$this->Auth->allow('nids');
|
||||
$this->Auth->allow('hids_md5');
|
||||
$this->Auth->allow('hids_sha1');
|
||||
$this->Auth->allow('text');
|
||||
|
||||
$this->Auth->allow('dot');
|
||||
|
@ -46,6 +50,20 @@ class EventsController extends AppController {
|
|||
}
|
||||
|
||||
// TODO ACL, if on ent/attr level, $this->set('isAcl', $this->checkAccess());
|
||||
|
||||
// convert uuid to id if present in the url, and overwrite id field
|
||||
if (isset($this->params->query['uuid'])) {
|
||||
$params = array(
|
||||
'conditions' => array('Event.uuid' => $this->params->query['uuid']),
|
||||
'recursive' => 0,
|
||||
'fields' => 'Event.id'
|
||||
);
|
||||
$result = $this->Event->find('first', $params);
|
||||
if (isset($result['Event']) && isset($result['Event']['id'])) {
|
||||
$id = $result['Event']['id'];
|
||||
$this->params->addParams(array('pass' => array($id))); // FIXME find better way to change id variable if uuid is found. params->url and params->here is not modified accordingly now
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function isAuthorized($user) {
|
||||
|
@ -92,46 +110,112 @@ class EventsController extends AppController {
|
|||
$this->Event->read(null, $id);
|
||||
|
||||
$relatedAttributes = array();
|
||||
$this->loadModel('Attribute');
|
||||
$fields = array('Attribute.id', 'Attribute.event_id', 'Attribute.uuid');
|
||||
foreach ($this->Event->data['Attribute'] as &$attribute) {
|
||||
$relatedAttributes[$attribute['id']] = $this->Attribute->getRelatedAttributes($attribute, $fields);
|
||||
// for REST requests also add the encoded attachment
|
||||
if ($this->_isRest() && $this->Attribute->typeIsAttachment($attribute['type'])) {
|
||||
// LATER check if this has a serious performance impact on XML conversion and memory usage
|
||||
$encoded_file = $this->Attribute->base64EncodeAttachment($attribute);
|
||||
$attribute['data'] = $encoded_file;
|
||||
$this->loadModel('Attribute');
|
||||
if ('db' == Configure::read('CyDefSIG.correlation')) {
|
||||
$this->loadModel('Correlation');
|
||||
$fields = array('Correlation.event_id', 'Correlation.attribute_id', 'Correlation.date');
|
||||
$fields2 = array('Correlation.1_attribute_id','Correlation.event_id', 'Correlation.attribute_id', 'Correlation.date');
|
||||
$relatedAttributes2 = array();
|
||||
$relatedAttributes2 = $this->Correlation->find('all',array(
|
||||
'fields' => $fields2,
|
||||
'conditions' => array(
|
||||
'OR' => array(
|
||||
'Correlation.1_event_id' => $id
|
||||
)
|
||||
),
|
||||
'recursive' => 0));
|
||||
if (empty($relatedAttributes2)) {
|
||||
$relatedEvents = null;
|
||||
}
|
||||
}
|
||||
$this->set('relatedAttributes', $relatedAttributes);
|
||||
else {
|
||||
foreach ($relatedAttributes2 as $relatedAttribute2) {
|
||||
$relatedAttributes[$relatedAttribute2['Correlation']['1_attribute_id']][] = array('Attribute' => $relatedAttribute2['Correlation']);
|
||||
}
|
||||
|
||||
// search for related Events using the results form the related attributes
|
||||
// This is a lot faster (only additional query) than $this->Event->getRelatedEvents()
|
||||
$relatedEventIds = array();
|
||||
$relatedEvents = array();
|
||||
foreach ($relatedAttributes as &$relatedAttribute) {
|
||||
if (null == $relatedAttribute) continue;
|
||||
foreach ($relatedAttribute as &$item) {
|
||||
$relatedEventsIds[] = $item['Attribute']['event_id'];
|
||||
foreach ($this->Event->data['Attribute'] as &$attribute) {
|
||||
// for REST requests also add the encoded attachment
|
||||
if ($this->_isRest() && $this->Attribute->typeIsAttachment($attribute['type'])) {
|
||||
// LATER check if this has a serious performance impact on XML conversion and memory usage
|
||||
$encoded_file = $this->Attribute->base64EncodeAttachment($attribute);
|
||||
$attribute['data'] = $encoded_file;
|
||||
}
|
||||
}
|
||||
|
||||
// search for related Events using the results form the related attributes
|
||||
// This is a lot faster (only additional query) than $this->Event->getRelatedEvents()
|
||||
$relatedEventIds = array();
|
||||
$relatedEventDates = array();
|
||||
$relatedEvents = array();
|
||||
foreach ($relatedAttributes as &$relatedAttribute) {
|
||||
if (null == $relatedAttribute) continue;
|
||||
foreach ($relatedAttribute as &$item) {
|
||||
$relatedEventsIds[] = $item['Attribute']['event_id'];
|
||||
$relatedEventsDates[$item['Attribute']['event_id']] = $item['Attribute']['date'];
|
||||
}
|
||||
}
|
||||
|
||||
arsort($relatedEventsDates);
|
||||
if (isset($relatedEventsDates)) {
|
||||
$relatedEventsDates = array_unique($relatedEventsDates);
|
||||
foreach ($relatedEventsDates as $key => $relatedEventsDate) {
|
||||
$relatedEvents[] = array('Event' => array('id' => $key, 'date' => $relatedEventsDate));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$fields = array('Attribute.id', 'Attribute.event_id', 'Attribute.uuid');
|
||||
if ('sql' == Configure::read('CyDefSIG.correlation')) {
|
||||
$double = $this->Attribute->doubleAttributes();
|
||||
}
|
||||
foreach ($this->Event->data['Attribute'] as &$attribute) {
|
||||
if ('sql' == Configure::read('CyDefSIG.correlation')) {
|
||||
if (in_array($attribute['value1'],$double) || in_array($attribute['value2'],$double)) {
|
||||
$relatedAttributes[$attribute['id']] = $this->Attribute->getRelatedAttributes($attribute, $fields);
|
||||
} else {
|
||||
$relatedAttributes[$attribute['id']] = array();
|
||||
}
|
||||
} else {
|
||||
$relatedAttributes[$attribute['id']] = $this->Attribute->getRelatedAttributes($attribute, $fields);
|
||||
}
|
||||
// for REST requests also add the encoded attachment
|
||||
if ($this->_isRest() && $this->Attribute->typeIsAttachment($attribute['type'])) {
|
||||
// LATER check if this has a serious performance impact on XML conversion and memory usage
|
||||
$encoded_file = $this->Attribute->base64EncodeAttachment($attribute);
|
||||
$attribute['data'] = $encoded_file;
|
||||
}
|
||||
}
|
||||
|
||||
// search for related Events using the results form the related attributes
|
||||
// This is a lot faster (only additional query) than $this->Event->getRelatedEvents()
|
||||
$relatedEventIds = array();
|
||||
$relatedEvents = array();
|
||||
foreach ($relatedAttributes as &$relatedAttribute) {
|
||||
if (null == $relatedAttribute) continue;
|
||||
foreach ($relatedAttribute as &$item) {
|
||||
$relatedEventsIds[] = $item['Attribute']['event_id'];
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($relatedEventsIds)) {
|
||||
$relatedEventsIds = array_unique($relatedEventsIds);
|
||||
$find_params = array(
|
||||
'conditions' => array('OR' => array('Event.id' => $relatedEventsIds)), //array of conditions
|
||||
'recursive' => 0, //int
|
||||
'fields' => array('Event.id', 'Event.date', 'Event.uuid'), //array of field names
|
||||
'order' => array('Event.date DESC'), //string or array defining order
|
||||
);
|
||||
$relatedEvents = $this->Event->find('all', $find_params);
|
||||
}
|
||||
}
|
||||
if (isset($relatedEventsIds)) {
|
||||
$relatedEventsIds = array_unique($relatedEventsIds);
|
||||
$find_params = array(
|
||||
'conditions' => array('OR' => array('Event.id' => $relatedEventsIds)), //array of conditions
|
||||
'recursive' => 0, //int
|
||||
'fields' => array('Event.id', 'Event.date', 'Event.uuid'), //array of field names
|
||||
'order' => array('Event.date DESC'), //string or array defining order
|
||||
);
|
||||
$relatedEvents = $this->Event->find('all', $find_params);
|
||||
}
|
||||
|
||||
$this->set('relatedAttributes', $relatedAttributes);
|
||||
|
||||
// passing decriptions for model fields
|
||||
$this->set('event_descriptions', $this->Event->field_descriptions);
|
||||
$this->set('attr_descriptions', $this->Attribute->field_descriptions);
|
||||
|
||||
$this->set('event', $this->Event->data);
|
||||
$this->set('relatedEvents', $relatedEvents);
|
||||
$this->set('relatedEvents', $relatedEvents);
|
||||
|
||||
$this->set('categories', $this->Attribute->validate['category']['rule'][1]);
|
||||
|
||||
|
@ -156,7 +240,7 @@ class EventsController extends AppController {
|
|||
//return false;
|
||||
$this->Session->setFlash('You may only upload GFI Sandbox zip files.');
|
||||
} else {
|
||||
if ($this->_add($this->request->data, $this->Auth, $this->_isRest())) {
|
||||
if ($this->_add($this->request->data, $this->Auth, $this->_isRest(),'')) {
|
||||
if ($this->_isRest()) {
|
||||
// REST users want to see the newly created event
|
||||
$this->view($this->Event->getId());
|
||||
|
@ -189,22 +273,14 @@ class EventsController extends AppController {
|
|||
*
|
||||
* @return bool true if success
|
||||
*/
|
||||
public function _add(&$data, &$auth, $fromXml) {
|
||||
public function _add(&$data, &$auth, $fromXml, $or='') {
|
||||
// force check userid and orgname to be from yourself
|
||||
if (!$fromXml) $data['Event']['user_id'] = $auth->user('id');
|
||||
$data['Event']['org'] = $auth->user('org');
|
||||
$data['Event']['user_id'] = $auth->user('id');
|
||||
$data['Event']['org'] = strlen($or) ? $or : $auth->user('org'); // FIXME security - org problem
|
||||
unset ($data['Event']['id']);
|
||||
$this->Event->create();
|
||||
|
||||
if (isset($data['Event']['uuid'])) {
|
||||
// check if the uuid already exists
|
||||
$existingEventCount = $this->Event->find('count', array('conditions' => array('Event.uuid'=>$data['Event']['uuid'])));
|
||||
if ($existingEventCount > 0) {
|
||||
throw new MethodNotAllowedException('Event already exists'); // LATER throw errors a clean way using XML
|
||||
} // TODO update the event if there are changes
|
||||
}
|
||||
|
||||
if ($fromXml) {
|
||||
if ($fromXml) {
|
||||
// Workaround for different structure in XML/array than what CakePHP expects
|
||||
$this->Event->cleanupEventArrayFromXML($data);
|
||||
|
||||
|
@ -212,22 +288,51 @@ class EventsController extends AppController {
|
|||
// LATER do this with $this->validator()->remove('event_id');
|
||||
unset($this->Event->Attribute->validate['event_id']);
|
||||
unset($this->Event->Attribute->validate['value']['unique']); // otherwise gives bugs because event_id is not set
|
||||
|
||||
// thing a 'pull from server' sets ServersController.php:176
|
||||
// Event.info is appended from the publishing side, given the need to have Server.url
|
||||
$data['Event']['private'] = true;
|
||||
}
|
||||
|
||||
if (isset($data['Event']['uuid'])) { // TODO here we should start RESTful dialog
|
||||
// check if the uuid already exists
|
||||
$existingEventCount = $this->Event->find('count', array('conditions' => array('Event.uuid'=>$data['Event']['uuid'])));
|
||||
if ($existingEventCount > 0) {
|
||||
$existingEvent = $this->Event->find('first', array('conditions' => array('Event.uuid'=>$data['Event']['uuid'])));
|
||||
$data['Event']['id'] = $existingEvent['Event']['id'];
|
||||
$data['Event']['org'] = $existingEvent['Event']['org'];
|
||||
// attributes..
|
||||
$c = 0;
|
||||
if (isset($data['Attribute'])) {
|
||||
foreach ($data['Attribute'] as $attribute){
|
||||
// ..do some
|
||||
$existingAttributeCount = $this->Event->Attribute->find('count', array('conditions' => array('Attribute.uuid'=>$attribute['uuid'])));
|
||||
if ($existingAttributeCount > 0) {
|
||||
$existingAttribute = $this->Event->Attribute->find('first', array('conditions' => array('Attribute.uuid'=>$attribute['uuid'])));
|
||||
$data['Attribute'][$c]['id'] = $existingAttribute['Attribute']['id'];
|
||||
}
|
||||
$c++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$fieldList = array(
|
||||
'Event' => array('org', 'date', 'risk', 'info', 'user_id', 'published', 'uuid', 'private'),
|
||||
'Attribute' => array('event_id', 'category', 'type', 'value', 'value1', 'value2', 'to_ids', 'uuid', 'revision', 'private')
|
||||
);
|
||||
);
|
||||
// this saveAssociated() function will save not only the event, but also the attributes
|
||||
// from the attributes attachments are also saved to the disk thanks to the afterSave() fonction of Attribute
|
||||
if ($this->Event->saveAssociated($data, array('validate' => true, 'fieldList' => $fieldList))) {
|
||||
if (!empty($data['Event']['published']) && 1 == $data['Event']['published']) {
|
||||
// call _sendAlertEmail if published was set in the request
|
||||
$this->_sendAlertEmail($this->Event->getId());
|
||||
if (!$fromXml) {
|
||||
$this->_sendAlertEmail($this->Event->getId());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
throw new MethodNotAllowedException("Validation ERROR: \n".var_export($this->Event->validationErrors, true));
|
||||
//throw new MethodNotAllowedException("Validation ERROR: \n".var_export($this->Event->validationErrors, true));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -247,8 +352,36 @@ class EventsController extends AppController {
|
|||
|
||||
if ($this->request->is('post') || $this->request->is('put')) {
|
||||
if ($this->_isRest()) {
|
||||
// TODO implement REST edit Event
|
||||
throw new NotFoundException('Sorry, this is not yet implemented');
|
||||
// Workaround for different structure in XML/array than what CakePHP expects
|
||||
$this->Event->cleanupEventArrayFromXML($this->request->data);
|
||||
|
||||
// the event_id field is not set (normal) so make sure no validation errors are thrown
|
||||
// LATER do this with $this->validator()->remove('event_id');
|
||||
unset($this->Event->Attribute->validate['event_id']);
|
||||
unset($this->Event->Attribute->validate['value']['unique']); // otherwise gives bugs because event_id is not set
|
||||
|
||||
$fieldList = array(
|
||||
'Event' => array('org', 'date', 'risk', 'info', 'published', 'uuid', 'private'),
|
||||
'Attribute' => array('event_id', 'category', 'type', 'value', 'value1', 'value2', 'to_ids', 'uuid', 'revision', 'private')
|
||||
);
|
||||
// this saveAssociated() function will save not only the event, but also the attributes
|
||||
// from the attributes attachments are also saved to the disk thanks to the afterSave() fonction of Attribute
|
||||
if ($this->Event->saveAssociated($this->request->data, array('validate' => true, 'fieldList' => $fieldList))) {
|
||||
$message = 'Saved';
|
||||
|
||||
$this->set('event', $this->Event);
|
||||
|
||||
// REST users want to see the newly created event
|
||||
$this->view($this->Event->getId());
|
||||
$this->render('view');
|
||||
return true;
|
||||
} else {
|
||||
$message = 'Error';
|
||||
$this->set(array('message' => $message,'_serialize' => array('message'))); // $this->Event->validationErrors
|
||||
$this->render('edit');
|
||||
//throw new MethodNotAllowedException("Validation ERROR: \n".var_export($this->Event->validationErrors, true));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// say what fields are to be updated
|
||||
|
@ -288,17 +421,29 @@ class EventsController extends AppController {
|
|||
* @return void
|
||||
*/
|
||||
public function delete($id = null) {
|
||||
if (!$this->request->is('post')) {
|
||||
if (!$this->request->is('post') && !$this->_isRest()) {
|
||||
throw new MethodNotAllowedException();
|
||||
}
|
||||
$this->Event->id = $id;
|
||||
|
||||
$this->Event->id = $id;
|
||||
if (!$this->Event->exists()) {
|
||||
throw new NotFoundException(__('Invalid event'));
|
||||
}
|
||||
// only edit own events verified by isAuthorized
|
||||
|
||||
|
||||
if ('true' == Configure::read('CyDefSIG.sync')) {
|
||||
// find the uuid
|
||||
$result = $this->Event->findById($id);
|
||||
$uuid = $result['Event']['uuid'];
|
||||
}
|
||||
|
||||
if ($this->Event->delete()) {
|
||||
$this->Session->setFlash(__('Event deleted'));
|
||||
|
||||
// delete the event from remote servers
|
||||
if ('true' == Configure::read('CyDefSIG.sync')) { // TODO test..(!$this->_isRest()) &&
|
||||
$this->_deleteEventFromServers($uuid);
|
||||
}
|
||||
|
||||
$this->Session->setFlash(__('Event deleted'));
|
||||
$this->redirect(array('action' => 'index'));
|
||||
}
|
||||
$this->Session->setFlash(__('Event was not deleted'));
|
||||
|
@ -333,6 +478,27 @@ class EventsController extends AppController {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delets this specific event to all remote servers
|
||||
* TODO move this to a component(?)
|
||||
*/
|
||||
function _deleteEventFromServers($uuid) {
|
||||
|
||||
// get a list of the servers
|
||||
$this->loadModel('Server');
|
||||
$servers = $this->Server->find('all', array());
|
||||
|
||||
// iterate over the servers and upload the event
|
||||
if(empty($servers))
|
||||
return;
|
||||
|
||||
App::uses('HttpSocket', 'Network/Http');
|
||||
$HttpSocket = new HttpSocket();
|
||||
foreach ($servers as &$server) {
|
||||
$this->Event->deleteEventFromServer($uuid, $server, $HttpSocket);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs all the actions required to publish an event
|
||||
*
|
||||
|
@ -389,12 +555,19 @@ class EventsController extends AppController {
|
|||
// only allow form submit CSRF protection.
|
||||
if ($this->request->is('post') || $this->request->is('put')) {
|
||||
// send out the email
|
||||
if ($this->_sendAlertEmail($id)) {
|
||||
$emailResult = $this->_sendAlertEmail($id);
|
||||
if (is_bool($emailResult) && $emailResult = true) {
|
||||
// Performs all the actions required to publish an event
|
||||
$this->_publish($id);
|
||||
|
||||
// redirect to the view event page
|
||||
$this->Session->setFlash(__('Email sent to all participants.', true));
|
||||
} elseif (!is_bool($emailResult)) {
|
||||
// Performs all the actions required to publish an event
|
||||
$this->_publish($id);
|
||||
|
||||
// redirect to the view event page
|
||||
$this->Session->setFlash(__('Published but no email sent given GnuPG is not configured.', true));
|
||||
} else {
|
||||
$this->Session->setFlash('Sending of email failed', 'default', array(), 'error');
|
||||
}
|
||||
|
@ -441,77 +614,89 @@ class EventsController extends AppController {
|
|||
$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.
|
||||
//
|
||||
if ('false' == Configure::read('GnuPG.onlyencrypted')) {
|
||||
$alert_users = $this->User->find('all', array(
|
||||
'conditions' => array('User.autoalert' => 1,
|
||||
'User.gpgkey =' => ""),
|
||||
'recursive' => 0,
|
||||
) );
|
||||
$alert_emails = Array();
|
||||
foreach ($alert_users as &$user) {
|
||||
$alert_emails[] = $user['User']['email'];
|
||||
}
|
||||
// prepare the the unencrypted email
|
||||
$this->Email->from = Configure::read('CyDefSIG.email');
|
||||
//$this->Email->to = "CyDefSIG <sig@cyber-defence.be>"; TODO check if it doesn't break things to not set a to , like being spammed away
|
||||
$this->Email->bcc = $alert_emails;
|
||||
$this->Email->subject = "[".Configure::read('CyDefSIG.name')."] Event ".$id." - ".$event['Event']['risk']." - TLP Amber";
|
||||
$this->Email->template = 'body';
|
||||
$this->Email->sendAs = 'text'; // both text or html
|
||||
$this->set('body', $body_signed);
|
||||
// send it
|
||||
$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();
|
||||
}
|
||||
|
||||
//
|
||||
// Build a list of the recipients that wish to receive encrypted mails.
|
||||
//
|
||||
$alert_users = $this->User->find('all', array(
|
||||
'conditions' => array( 'User.autoalert' => 1,
|
||||
'User.gpgkey !=' => ""),
|
||||
'recursive' => 0,
|
||||
)
|
||||
);
|
||||
// encrypt the mail for each user and send it separately
|
||||
foreach ($alert_users as &$user) {
|
||||
// send the email
|
||||
$this->Email->from = Configure::read('CyDefSIG.email');
|
||||
$this->Email->to = $user['User']['email'];
|
||||
$this->Email->subject = "[".Configure::read('CyDefSIG.name')."] Event ".$id." - ".$event['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
|
||||
// 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(array('homedir' => Configure::read('GnuPG.homedir')));
|
||||
$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();
|
||||
require_once 'Crypt/GPG.php';
|
||||
try {
|
||||
$gpg = new Crypt_GPG(array('homedir' => Configure::read('GnuPG.homedir'))); // , 'debug' => true
|
||||
$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.
|
||||
//
|
||||
if ('false' == Configure::read('GnuPG.onlyencrypted')) {
|
||||
$alert_users = $this->User->find('all', array(
|
||||
'conditions' => array('User.autoalert' => 1,
|
||||
'User.gpgkey =' => ""),
|
||||
'recursive' => 0,
|
||||
) );
|
||||
$alert_emails = Array();
|
||||
foreach ($alert_users as &$user) {
|
||||
$alert_emails[] = $user['User']['email'];
|
||||
}
|
||||
// prepare the the unencrypted email
|
||||
$this->Email->from = Configure::read('CyDefSIG.email');
|
||||
//$this->Email->to = "CyDefSIG <sig@cyber-defence.be>"; TODO check if it doesn't break things to not set a to , like being spammed away
|
||||
$this->Email->bcc = $alert_emails;
|
||||
$this->Email->subject = "[".Configure::read('CyDefSIG.name')."] Event ".$id." - ".$event['Event']['risk']." - TLP Amber";
|
||||
$this->Email->template = 'body';
|
||||
$this->Email->sendAs = 'text'; // both text or html
|
||||
$this->set('body', $body_signed);
|
||||
// send it
|
||||
$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();
|
||||
}
|
||||
|
||||
//
|
||||
// Build a list of the recipients that wish to receive encrypted mails.
|
||||
//
|
||||
$alert_users = $this->User->find('all', array(
|
||||
'conditions' => array( 'User.autoalert' => 1,
|
||||
'User.gpgkey !=' => ""),
|
||||
'recursive' => 0,
|
||||
)
|
||||
);
|
||||
// encrypt the mail for each user and send it separately
|
||||
foreach ($alert_users as &$user) {
|
||||
// send the email
|
||||
$this->Email->from = Configure::read('CyDefSIG.email');
|
||||
$this->Email->to = $user['User']['email'];
|
||||
$this->Email->subject = "[".Configure::read('CyDefSIG.name')."] Event ".$id." - ".$event['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
|
||||
// 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
|
||||
try {
|
||||
$gpg = new Crypt_GPG(array('homedir' => Configure::read('GnuPG.homedir')));
|
||||
$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();
|
||||
} catch (Exception $e){
|
||||
// catch errors like expired PGP keys
|
||||
$this->log($e->getMessage());
|
||||
return $e->getMessage();
|
||||
}
|
||||
// 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();
|
||||
}
|
||||
} catch (Exception $e){
|
||||
// catch errors like expired PGP keys
|
||||
$this->log($e->getMessage());
|
||||
return $e->getMessage();
|
||||
}
|
||||
|
||||
|
||||
// LATER check if sending email succeeded and return appropriate result
|
||||
return true;
|
||||
|
||||
|
@ -639,11 +824,16 @@ class EventsController extends AppController {
|
|||
// 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
|
||||
$key_import_output = $gpg->importKey($reporter['User']['gpgkey']);
|
||||
// say what key should be used to encrypt
|
||||
$gpg = new Crypt_GPG(array('homedir' => Configure::read('GnuPG.homedir')));
|
||||
$gpg->addEncryptKey($key_import_output['fingerprint']); // use the key that was given in the import
|
||||
// say what key should be used to encrypt
|
||||
try {
|
||||
$gpg = new Crypt_GPG(array('homedir' => Configure::read('GnuPG.homedir')));
|
||||
$gpg->addEncryptKey($key_import_output['fingerprint']); // use the key that was given in the import
|
||||
|
||||
$body_enc_sig = $gpg->encrypt($body_signed, true);
|
||||
$body_enc_sig = $gpg->encrypt($body_signed, true);
|
||||
} catch (Exception $e){
|
||||
// catch errors like expired PGP keys
|
||||
$this->log($e->getMessage());
|
||||
}
|
||||
} else {
|
||||
$body_enc_sig = $body_signed;
|
||||
// FIXME should I allow sending unencrypted "contact" mails to people if they didn't import they GPG key?
|
||||
|
@ -764,6 +954,90 @@ class EventsController extends AppController {
|
|||
}
|
||||
|
||||
|
||||
public function hids_md5($key) {
|
||||
// check if the key is valid -> search for users based on key
|
||||
$this->loadModel('User');
|
||||
// no input sanitization necessary, it's done by model
|
||||
// do not fetch recursive
|
||||
$this->User->recursive=0;
|
||||
$user = $this->User->findByAuthkey($key);
|
||||
if (empty($user)) {
|
||||
throw new UnauthorizedException('Incorrect authentication key');
|
||||
}
|
||||
// display the full md5 set
|
||||
$this->response->type(array('txt' => 'text/html')); // set the content type
|
||||
$this->header('Content-Disposition: inline; filename="cydefsig.rules"');
|
||||
$this->layout = 'text/default';
|
||||
|
||||
$this->loadModel('Attribute');
|
||||
|
||||
$params = array(
|
||||
'conditions' => array('Attribute.to_ids' => 1), //array of conditions
|
||||
'recursive' => 0, //int
|
||||
'group' => array('Attribute.type', 'Attribute.value1'), //fields to GROUP BY
|
||||
);
|
||||
$items = $this->Attribute->find('all', $params);
|
||||
|
||||
$rules = $this->HidsMd5Export->suricataRules($items); // TODO NIDS_SID??
|
||||
if (count($rules) >= 4) {
|
||||
print ("#<h1>This part is not finished and might be buggy. Please report any issues.</h1>\n");
|
||||
|
||||
print "#<pre> \n";
|
||||
foreach ($rules as &$rule)
|
||||
print $rule."\n";
|
||||
print "#</pre>\n";
|
||||
|
||||
$this->set('rules', $rules);
|
||||
} else {
|
||||
print "Not any MD5 found to export\n";
|
||||
}
|
||||
$this->render('hids');
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function hids_sha1($key) {
|
||||
// check if the key is valid -> search for users based on key
|
||||
$this->loadModel('User');
|
||||
// no input sanitization necessary, it's done by model
|
||||
// do not fetch recursive
|
||||
$this->User->recursive=0;
|
||||
$user = $this->User->findByAuthkey($key);
|
||||
if (empty($user)) {
|
||||
throw new UnauthorizedException('Incorrect authentication key');
|
||||
}
|
||||
// display the full SHA-1 set
|
||||
$this->response->type(array('txt' => 'text/html')); // set the content type
|
||||
$this->header('Content-Disposition: inline; filename="cydefsig.rules"');
|
||||
$this->layout = 'text/default';
|
||||
|
||||
$this->loadModel('Attribute');
|
||||
|
||||
$params = array(
|
||||
'conditions' => array('Attribute.to_ids' => 1), //array of conditions
|
||||
'recursive' => 0, //int
|
||||
'group' => array('Attribute.type', 'Attribute.value1'), //fields to GROUP BY
|
||||
);
|
||||
$items = $this->Attribute->find('all', $params);
|
||||
|
||||
$rules = $this->HidsSha1Export->suricataRules($items); // TODO NIDS_SID??
|
||||
if (count($rules) >= 4) {
|
||||
print ("#<h1>This part is not finished and might be buggy. Please report any issues.</h1>\n");
|
||||
|
||||
print "#<pre> \n";
|
||||
foreach ($rules as &$rule)
|
||||
print $rule."\n";
|
||||
print "#</pre>\n";
|
||||
|
||||
$this->set('rules', $rules);
|
||||
} else {
|
||||
print "Not any SHA-1 found to export\n";
|
||||
}
|
||||
$this->render('hids');
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function text($key, $type="") {
|
||||
// check if the key is valid -> search for users based on key
|
||||
$this->loadModel('User');
|
||||
|
|
|
@ -98,7 +98,7 @@ class ServersController extends AppController {
|
|||
|
||||
if ($this->request->is('post') || $this->request->is('put')) {
|
||||
// say what fields are to be updated
|
||||
$fieldList=array('url', 'push', 'pull');
|
||||
$fieldList=array('url', 'push', 'pull', 'organization');
|
||||
if ("" != $this->request->data['Server']['authkey'])
|
||||
$fieldList[] = 'authkey';
|
||||
// Save the data
|
||||
|
@ -177,13 +177,14 @@ class ServersController extends AppController {
|
|||
$event['Event']['info'] .= "\n Imported from ".$this->Server->data['Server']['url'];
|
||||
$eventsController = new EventsController();
|
||||
try {
|
||||
$result = $eventsController->_add($event, $this->Auth, $fromXml=true);
|
||||
$result = $eventsController->_add($event, $this->Auth, $fromXml=true, $this->Server->data['Server']['organization']);
|
||||
} catch (MethodNotAllowedException $e) {
|
||||
if ($e->getMessage() == 'Event already exists') {
|
||||
$successes[] = $event_id;
|
||||
//$successes[] = $event_id; // commented given it's in a catch..
|
||||
continue;
|
||||
}
|
||||
}
|
||||
$successes[] = $event_id; // ..moved, so $successes does keep administration.
|
||||
//$result = $this->_importEvent($event);
|
||||
// TODO error handling
|
||||
} else {
|
||||
|
@ -197,7 +198,7 @@ class ServersController extends AppController {
|
|||
$lastpulledid = min(array_keys($fails));
|
||||
} else {
|
||||
// no fails, take the highest success
|
||||
$lastpulledid = max($successes);
|
||||
$lastpulledid = count($successes) > 0 ? max($successes) : 0;
|
||||
}
|
||||
// increment lastid based on the highest ID seen
|
||||
$this->Server->saveField('lastpulledid', $lastpulledid);
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
<?php
|
||||
App::uses('AppController', 'Controller');
|
||||
/**
|
||||
* Whitelists Controller
|
||||
*
|
||||
* @property Whitelist $Whitelist
|
||||
*/
|
||||
class WhitelistsController extends AppController {
|
||||
|
||||
|
||||
/**
|
||||
* index method
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function admin_index() {
|
||||
$this->Whitelist->recursive = 0;
|
||||
$this->set('whitelists', $this->paginate());
|
||||
}
|
||||
|
||||
/**
|
||||
* view method
|
||||
*
|
||||
* @param string $id
|
||||
* @return void
|
||||
*/
|
||||
public function admin_view($id = null) {
|
||||
$this->Whitelist->id = $id;
|
||||
if (!$this->Whitelist->exists()) {
|
||||
throw new NotFoundException(__('Invalid whitelist'));
|
||||
}
|
||||
$this->set('whitelist', $this->Whitelist->read(null, $id));
|
||||
}
|
||||
|
||||
/**
|
||||
* add method
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function admin_add() {
|
||||
if ($this->request->is('post')) {
|
||||
$this->Whitelist->create();
|
||||
if ($this->Whitelist->save($this->request->data)) {
|
||||
$this->Session->setFlash(__('The whitelist has been saved'));
|
||||
$this->redirect(array('action' => 'index'));
|
||||
} else {
|
||||
$this->Session->setFlash(__('The whitelist could not be saved. Please, try again.'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* edit method
|
||||
*
|
||||
* @param string $id
|
||||
* @return void
|
||||
*/
|
||||
public function admin_edit($id = null) {
|
||||
$this->Whitelist->id = $id;
|
||||
if (!$this->Whitelist->exists()) {
|
||||
throw new NotFoundException(__('Invalid whitelist'));
|
||||
}
|
||||
if ($this->request->is('post') || $this->request->is('put')) {
|
||||
if ($this->Whitelist->save($this->request->data)) {
|
||||
$this->Session->setFlash(__('The whitelist has been saved'));
|
||||
$this->redirect(array('action' => 'index'));
|
||||
} else {
|
||||
$this->Session->setFlash(__('The whitelist could not be saved. Please, try again.'));
|
||||
}
|
||||
} else {
|
||||
$this->request->data = $this->Whitelist->read(null, $id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* delete method
|
||||
*
|
||||
* @param string $id
|
||||
* @return void
|
||||
*/
|
||||
public function admin_delete($id = null) {
|
||||
if (!$this->request->is('post')) {
|
||||
throw new MethodNotAllowedException();
|
||||
}
|
||||
$this->Whitelist->id = $id;
|
||||
if (!$this->Whitelist->exists()) {
|
||||
throw new NotFoundException(__('Invalid whitelist'));
|
||||
}
|
||||
if ($this->Whitelist->delete()) {
|
||||
$this->Session->setFlash(__('Whitelist deleted'));
|
||||
$this->redirect(array('action' => 'index'));
|
||||
}
|
||||
$this->Session->setFlash(__('Whitelist was not deleted'));
|
||||
$this->redirect(array('action' => 'index'));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
DROP TABLE IF EXISTS `correlations`;
|
||||
CREATE TABLE `correlations` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`1_event_id` int(11) NOT NULL,
|
||||
`1_attribute_id` int(11) NOT NULL,
|
||||
`event_id` int(11) NOT NULL,
|
||||
`attribute_id` int(11) NOT NULL,
|
||||
`date` date NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM AUTO_INCREMENT=118 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
|
|
@ -0,0 +1,7 @@
|
|||
alter table servers add column lastpulledid int;
|
||||
alter table servers add column lastpushedid int;
|
||||
alter table servers add column organization varchar(10);
|
||||
alter table servers add column logo varchar(20);
|
||||
|
||||
-- example data
|
||||
-- INSERT INTO servers (url,organization,logo) VALUES ('http://192.101.252.40/','NATO NCI','natologo.gif');
|
|
@ -60,6 +60,7 @@ CREATE TABLE `events` (
|
|||
`date` date NOT NULL,
|
||||
`risk` enum('Undefined','Low','Medium','High') COLLATE utf8_bin NOT NULL,
|
||||
`info` text CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
|
||||
`user_id` int(11) NOT NULL,
|
||||
`published` tinyint(1) NOT NULL DEFAULT '0',
|
||||
`uuid` varchar(40) COLLATE utf8_bin NOT NULL,
|
||||
`revision` int(10) NOT NULL DEFAULT '0',
|
||||
|
@ -82,6 +83,8 @@ CREATE TABLE `servers` (
|
|||
`pull` tinyint(1) NOT NULL,
|
||||
`lastpushedid` int(11) NOT NULL,
|
||||
`lastpulledid` int(11) NOT NULL,
|
||||
`organization` varchar(10) COLLATE utf8_bin NOT NULL,
|
||||
`logo` varchar(20) COLLATE utf8_bin NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin AUTO_INCREMENT=1 ;
|
||||
|
||||
|
@ -107,6 +110,18 @@ CREATE TABLE `users` (
|
|||
KEY `email` (`email`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin AUTO_INCREMENT=2 ;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Table structure for table `whitelist`
|
||||
--
|
||||
|
||||
CREATE TABLE `whitelist` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(254) NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin AUTO_INCREMENT=1 ;
|
||||
|
||||
|
||||
--
|
||||
-- Dumping data for table `attributes`
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
DROP TABLE IF EXISTS `whitelist`;
|
||||
CREATE TABLE `whitelist` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(254) NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM AUTO_INCREMENT=118 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
|
|
@ -314,7 +314,12 @@ IF (Attribute.category="External analysis", "j", "k"))))))))))'
|
|||
}
|
||||
|
||||
function afterSave() {
|
||||
$result = true;
|
||||
if ('db' == Configure::read('CyDefSIG.correlation')) {
|
||||
// update correlation..
|
||||
$this->_afterSaveCorrelation($this->data['Attribute']);
|
||||
}
|
||||
|
||||
$result = true;
|
||||
// if the 'data' field is set on the $this->data then save the data to the correct file
|
||||
if (isset($this->data['Attribute']['type']) && $this->typeIsAttachment($this->data['Attribute']['type']) && !empty($this->data['Attribute']['data'])) {
|
||||
$result = $result && $this->saveBase64EncodedAttachment($this->data['Attribute']);
|
||||
|
@ -328,7 +333,7 @@ IF (Attribute.category="External analysis", "j", "k"))))))))))'
|
|||
if($this->typeIsAttachment($this->data['Attribute']['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['Attribute']['event_id']."/".$this->data['Attribute']['id'];
|
||||
$filepath = APP."files".DS.$this->data['Attribute']['event_id'].DS.$this->data['Attribute']['id'];
|
||||
$file = new File ($filepath);
|
||||
if($file->exists()) {
|
||||
if (!$file->delete()) {
|
||||
|
@ -336,12 +341,21 @@ IF (Attribute.category="External analysis", "j", "k"))))))))))'
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ('db' == Configure::read('CyDefSIG.correlation')) {
|
||||
// update correlation..
|
||||
$this->_beforeDeleteCorrelation($this->data['Attribute']['id']);
|
||||
}
|
||||
}
|
||||
|
||||
function beforeValidate() {
|
||||
// remove leading and trailing blanks
|
||||
$this->data['Attribute']['value'] = trim($this->data['Attribute']['value']);
|
||||
|
||||
if (!isset($this->data['Attribute']['type'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch($this->data['Attribute']['type']) {
|
||||
// lowercase these things
|
||||
case 'md5':
|
||||
|
@ -601,7 +615,7 @@ IF (Attribute.category="External analysis", "j", "k"))))))))))'
|
|||
}
|
||||
|
||||
function base64EncodeAttachment($attribute) {
|
||||
$filepath = APP."files/".$attribute['event_id']."/".$attribute['id'];
|
||||
$filepath = APP."files".DS.$attribute['event_id'].DS.$attribute['id'];
|
||||
$file = new File($filepath);
|
||||
if (!$file->exists()) return '';
|
||||
$content = $file->read();
|
||||
|
@ -627,8 +641,7 @@ IF (Attribute.category="External analysis", "j", "k"))))))))))'
|
|||
*
|
||||
* @return void
|
||||
*/
|
||||
public function uploadAttachment($fileP,$realFileName,$malware,$event_id = null) {
|
||||
|
||||
public function uploadAttachment($fileP,$realFileName,$malware,$event_id = null) {
|
||||
// Check if there were problems with the file upload
|
||||
// only keep the last part of the filename, this should prevent directory attacks
|
||||
$filename = basename($fileP);
|
||||
|
@ -683,5 +696,115 @@ IF (Attribute.category="External analysis", "j", "k"))))))))))'
|
|||
}
|
||||
}
|
||||
|
||||
function _afterSaveCorrelation($attribute) {
|
||||
$this->_beforeDeleteCorrelation($attribute);
|
||||
// re-add
|
||||
$this->setRelatedAttributes($attribute, array('Attribute.id', 'Attribute.event_id', 'Event.date'));
|
||||
}
|
||||
|
||||
function _beforeDeleteCorrelation($attribute) {
|
||||
$this->Correlation = ClassRegistry::init('Correlation');
|
||||
$dummy = $this->Correlation->deleteAll(array('OR' => array(
|
||||
'Correlation.1_attribute_id' => $attribute,
|
||||
'Correlation.attribute_id' => $attribute))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* return an array containing 'double-values'
|
||||
*
|
||||
* @return array()
|
||||
*/
|
||||
function doubleAttributes() {
|
||||
$doubleAttributes = array();
|
||||
|
||||
$similar_value1 = $this->find('all',array('conditions' => array(),
|
||||
'fields' => 'value1',
|
||||
'recursive' => 0,
|
||||
'group' => 'Attribute.value1 HAVING count(1)>1' ));
|
||||
$similar_value2 = $this->find('all',array('conditions' => array(),
|
||||
'fields' => 'value2',
|
||||
'recursive' => 0,
|
||||
'group' => 'Attribute.value2 HAVING count(1)>1' ));
|
||||
$similar_values = $this->find('all', array('joins' => array(array(
|
||||
'table' => 'attributes',
|
||||
'alias' => 'att2',
|
||||
'type' => 'INNER',
|
||||
'conditions' => array('Attribute.value2 = att2.value1'))),
|
||||
'fields' => array('att2.value1')));
|
||||
$doubleAttributes = array_merge($similar_value1,$similar_value2);
|
||||
$doubleAttributes = array_merge($doubleAttributes,$similar_values);
|
||||
|
||||
$double = array();
|
||||
foreach ($doubleAttributes as $key => $doubleAttribute) {
|
||||
$v = isset($doubleAttribute['Attribute']) ? $doubleAttribute['Attribute'] : $doubleAttribute['att2'];
|
||||
$v = isset($v['value1']) ? $v['value1'] : $v['value2'];
|
||||
if ($v != '') {
|
||||
$double[] = $v;
|
||||
}
|
||||
}
|
||||
return $double;
|
||||
}
|
||||
|
||||
function setRelatedAttributes($attribute, $fields=array()) {
|
||||
$this->Event = ClassRegistry::init('Event');
|
||||
$relatedAttributes = $this->getRelatedAttributes($attribute, $fields);
|
||||
if ($relatedAttributes) {
|
||||
foreach ($relatedAttributes as $relatedAttribute) {
|
||||
// and store into table
|
||||
$params = array(
|
||||
'conditions' => array('Event.id' => $relatedAttribute['Attribute']['event_id']),
|
||||
'recursive' => 0,
|
||||
'fields' => array('Event.date')
|
||||
);
|
||||
$event_date = $this->Event->find('first', $params);
|
||||
$this->Correlation = ClassRegistry::init('Correlation');
|
||||
$this->Correlation->create();
|
||||
$this->Correlation->save(array(
|
||||
'Correlation' => array(
|
||||
'1_event_id' => $attribute['event_id'], '1_attribute_id' => $attribute['id'],
|
||||
'event_id' => $relatedAttribute['Attribute']['event_id'], 'attribute_id' => $relatedAttribute['Attribute']['id'],
|
||||
'date' => $event_date['Event']['date']))
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the attribute from another Server
|
||||
* TODO move this to a component
|
||||
*
|
||||
* @return bool true if success, error message if failed
|
||||
*/
|
||||
function deleteAttributeFromServer($attribute, $server, $HttpSocket=null) {
|
||||
// TODO private and delete
|
||||
if (true ==$attribute['Attribute']['private']) // never upload private attributes
|
||||
return "Attribute is private and non exportable";
|
||||
|
||||
$url = $server['Server']['url'];
|
||||
$authkey = $server['Server']['authkey'];
|
||||
if (null == $HttpSocket) {
|
||||
App::uses('HttpSocket', 'Network/Http');
|
||||
$HttpSocket = new HttpSocket();
|
||||
}
|
||||
$request = array(
|
||||
'header' => array(
|
||||
'Authorization' => $authkey,
|
||||
'Accept' => 'application/xml',
|
||||
'Content-Type' => 'application/xml',
|
||||
//'Connection' => 'keep-alive' // LATER followup cakephp ticket 2854 about this problem http://cakephp.lighthouseapp.com/projects/42648-cakephp/tickets/2854
|
||||
)
|
||||
);
|
||||
$uri = $url.'/attributes/0?uuid='.$attribute['Attribute']['uuid'];
|
||||
|
||||
// LATER validate HTTPS SSL certificate
|
||||
$this->Dns = ClassRegistry::init('Dns');
|
||||
if ($this->Dns->testipaddress(parse_url($uri, PHP_URL_HOST))) {
|
||||
// TODO NETWORK for now do not know how to catch the following..
|
||||
// TODO NETWORK No route to host
|
||||
$response = $HttpSocket->delete($uri, array(), $request);
|
||||
// TODO REST, DELETE, no responce needed
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
App::uses('AppModel', 'Model');
|
||||
|
||||
/*
|
||||
* Domain Name System related
|
||||
*/
|
||||
class Dns extends AppModel {
|
||||
var $useTable = false;
|
||||
|
||||
/*
|
||||
* Checks for a valid internet name
|
||||
* Returns true if Name is an existing Domain Host Name, false otherwise
|
||||
* TODO should be renamed
|
||||
*
|
||||
* @param unknown_type $nametotest The Domain Host Name to check for existence.
|
||||
* @return boolean
|
||||
*/
|
||||
function testipaddress ($nametotest) {
|
||||
if(intval($nametotest)>0){
|
||||
return true;
|
||||
} else {
|
||||
$ipaddress = $nametotest;
|
||||
$ipaddress = gethostbyname($nametotest);
|
||||
if ($ipaddress == $nametotest) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -88,6 +88,16 @@ class Event extends AppModel {
|
|||
//'on' => 'create', // Limit validation to 'create' or 'update' operations
|
||||
),
|
||||
),
|
||||
'user_id' => array(
|
||||
'numeric' => array(
|
||||
'rule' => array('numeric'),
|
||||
//'message' => 'Your custom message here',
|
||||
//'allowEmpty' => false,
|
||||
//'required' => false,
|
||||
//'last' => false, // Stop validation after this rule
|
||||
//'on' => 'create', // Limit validation to 'create' or 'update' operations
|
||||
),
|
||||
),
|
||||
'published' => array(
|
||||
'boolean' => array(
|
||||
'rule' => array('boolean'),
|
||||
|
@ -300,7 +310,7 @@ class Event extends AppModel {
|
|||
unset($event['Attribute']);
|
||||
|
||||
// cleanup the array from things we do not want to expose
|
||||
unset($event['Event']['org']);
|
||||
//unset($event['Event']['org']);
|
||||
// remove value1 and value2 from the output
|
||||
foreach($event['Event']['Attribute'] as $key => &$attribute) {
|
||||
// do not keep attributes that are private
|
||||
|
@ -316,30 +326,76 @@ class Event extends AppModel {
|
|||
$encoded_file = $this->Attribute->base64EncodeAttachment($attribute);
|
||||
$attribute['data'] = $encoded_file;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// display the XML to the user
|
||||
$xmlArray['Event'][] = $event['Event'];
|
||||
$xmlObject = Xml::fromArray($xmlArray, array('format' => 'tags'));
|
||||
$eventsXml = $xmlObject->asXML();
|
||||
// do a REST POST request with the server
|
||||
$data = $eventsXml;
|
||||
// LATER validate HTTPS SSL certificate
|
||||
$response = $HttpSocket->post($uri, $data, $request);
|
||||
if ($response->isOk()) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
// parse the XML response and keep the reason why it failed
|
||||
$xml_array = Xml::toArray(Xml::build($response->body));
|
||||
if ("Event already exists" == $xml_array['response']['name']) {
|
||||
return true;
|
||||
} else {
|
||||
return $xml_array['response']['name'];
|
||||
}
|
||||
$data = $eventsXml;
|
||||
// LATER validate HTTPS SSL certificate
|
||||
$this->Dns = ClassRegistry::init('Dns');
|
||||
if ($this->Dns->testipaddress(parse_url($uri, PHP_URL_HOST))) {
|
||||
// TODO NETWORK for now do not know how to catch the following..
|
||||
// TODO NETWORK No route to host
|
||||
$response = $HttpSocket->post($uri, $data, $request);
|
||||
if ($response->code == '200') { // 200 (OK) + entity-action-result
|
||||
if ($response->isOk()) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
try {
|
||||
// parse the XML response and keep the reason why it failed
|
||||
$xml_array = Xml::toArray(Xml::build($response->body));
|
||||
} catch (XmlException $e) {
|
||||
return true;
|
||||
}
|
||||
if (strpos($xml_array['response']['name'],"Event already exists")) { // strpos, so i can piggyback some value if needed.
|
||||
return true;
|
||||
} else {
|
||||
return $xml_array['response']['name'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the event and the associated Attributes from another Server
|
||||
* TODO move this to a component
|
||||
*
|
||||
* @return bool true if success, error message if failed
|
||||
*/
|
||||
function deleteEventFromServer($uuid, $server, $HttpSocket=null) {
|
||||
// TODO private and delete(?)
|
||||
|
||||
$url = $server['Server']['url'];
|
||||
$authkey = $server['Server']['authkey'];
|
||||
if (null == $HttpSocket) {
|
||||
App::uses('HttpSocket', 'Network/Http');
|
||||
$HttpSocket = new HttpSocket();
|
||||
}
|
||||
$request = array(
|
||||
'header' => array(
|
||||
'Authorization' => $authkey,
|
||||
'Accept' => 'application/xml',
|
||||
'Content-Type' => 'application/xml',
|
||||
//'Connection' => 'keep-alive' // LATER followup cakephp ticket 2854 about this problem http://cakephp.lighthouseapp.com/projects/42648-cakephp/tickets/2854
|
||||
)
|
||||
);
|
||||
$uri = $url.'/events/0?uuid='.$uuid;
|
||||
|
||||
// LATER validate HTTPS SSL certificate
|
||||
$this->Dns = ClassRegistry::init('Dns');
|
||||
if ($this->Dns->testipaddress(parse_url($uri, PHP_URL_HOST))) {
|
||||
// TODO NETWORK for now do not know how to catch the following..
|
||||
// TODO NETWORK No route to host
|
||||
$response = $HttpSocket->delete($uri, array(), $request);
|
||||
// TODO REST, DELETE, some responce needed
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Download a specific event from a Server
|
||||
* TODO move this to a component
|
||||
|
@ -395,18 +451,21 @@ class Event extends AppModel {
|
|||
)
|
||||
);
|
||||
$uri = $url.'/events/index/sort:id/direction:desc/limit:999'; // LATER verify if events are missing because we only selected the last 999
|
||||
$response = $HttpSocket->get($uri, $data='', $request);
|
||||
$this->Dns = ClassRegistry::init('Dns');
|
||||
if ($this->Dns->testipaddress(parse_url($uri, PHP_URL_HOST))) {
|
||||
$response = $HttpSocket->get($uri, $data='', $request);
|
||||
|
||||
if ($response->isOk()) {
|
||||
$xml = Xml::build($response->body);
|
||||
$eventArray = Xml::toArray($xml);
|
||||
$event_ids=array();
|
||||
foreach ($eventArray['response']['Event'] as &$event) {
|
||||
if (1 != $event['published']) continue; // do not keep non-published events
|
||||
$event_ids[] = $event['id'];
|
||||
}
|
||||
return $event_ids;
|
||||
}
|
||||
if ($response->isOk()) {
|
||||
$xml = Xml::build($response->body);
|
||||
$eventArray = Xml::toArray($xml);
|
||||
$event_ids=array();
|
||||
foreach ($eventArray['response']['Event'] as &$event) {
|
||||
if (1 != $event['published']) continue; // do not keep non-published events
|
||||
$event_ids[] = $event['id'];
|
||||
}
|
||||
return $event_ids;
|
||||
}
|
||||
}
|
||||
// error, so return null
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -102,5 +102,4 @@ class Server extends AppModel {
|
|||
return $this->field('id', array('id' => $serverid, 'org' => $org)) === $serverid;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -109,6 +109,11 @@ class User extends AppModel {
|
|||
),
|
||||
),
|
||||
'authkey' => array(
|
||||
'minlength' => array(
|
||||
'rule' => array('minlength', 40),
|
||||
'message' => 'A authkey of a minimum length of 40 is required.',
|
||||
'required' => true,
|
||||
),
|
||||
'notempty' => array(
|
||||
'rule' => array('notempty'),
|
||||
//'message' => 'Your custom message here',
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
<?php
|
||||
App::uses('AppModel', 'Model');
|
||||
/**
|
||||
* Whitelist Model
|
||||
*
|
||||
*/
|
||||
class Whitelist extends AppModel {
|
||||
/**
|
||||
* Use table
|
||||
*
|
||||
* @var mixed False or table name
|
||||
*/
|
||||
public $useTable = 'whitelist';
|
||||
/**
|
||||
* Display field
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $displayField = 'name';
|
||||
/**
|
||||
* Validation rules
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $validate = array(
|
||||
'name' => array(
|
||||
'notempty' => array(
|
||||
'rule' => array('notempty'),
|
||||
'message' => 'Please fill in this field',
|
||||
//'allowEmpty' => false,
|
||||
//'required' => false,
|
||||
//'last' => false, // Stop validation after this rule
|
||||
//'on' => 'create', // Limit validation to 'create' or 'update' operations
|
||||
),
|
||||
'userdefined' => array(
|
||||
'rule' => array('validateValue'),
|
||||
'message' => 'Name not in the right format. Please double check the name.',
|
||||
//'allowEmpty' => false,
|
||||
//'required' => true,
|
||||
//'last' => false, // Stop validation after this rule
|
||||
//'on' => 'create', // Limit validation to 'create' or 'update' operations
|
||||
),
|
||||
'unique' => array(
|
||||
'rule' => 'isUnique', //array('valueIsUnique'),
|
||||
'message' => 'A similar name already exists.',
|
||||
//'allowEmpty' => false,
|
||||
//'required' => true,
|
||||
//'last' => false, // Stop validation after this rule
|
||||
//'on' => 'create', // Limit validation to 'create' or 'update' operations
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
function validateValue ($fields) {
|
||||
$value = $fields['name'];
|
||||
|
||||
// check data validation
|
||||
// host domainname maybe..
|
||||
if(preg_match("#^[A-Z0-9.-]+\.[A-Z]{2,4}$#i", $value))
|
||||
return true;
|
||||
|
||||
// IP maybe..
|
||||
$parts = explode("/", $value);
|
||||
// [0] = the ip
|
||||
// [1] = the network address
|
||||
if (count($parts) <= 2 ) {
|
||||
// ipv4 and ipv6 matching
|
||||
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;
|
||||
else if(is_numeric($parts[1]) && $parts[1] < 129)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
function valueIsUnique ($fields) {
|
||||
$value = $fields['name'];
|
||||
|
||||
$whitelist = $this->find('all', array('recursive' => 0,'fields' => 'name'));
|
||||
foreach ($whitelist as $whitelistItem) {
|
||||
if ($value == $whitelistItem['Whitelist']['name']) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
VIRTUAL HOST INSTRUCTION
|
||||
------------------------
|
||||
|
||||
CyDefSIG is able to run in an Apache virtual host setup.
|
||||
This takes 2 variables, the hostname and CyDefSIG directory.
|
||||
To this one must enter the hostname in /etc/hosts
|
||||
and create an Apache config in apache2/sites-available.
|
||||
|
||||
Say we have a hostname cydefsig2.local.net and
|
||||
CyDefSIG installed in /var/www/second_instance/cydefsig,
|
||||
we will add to /etc/hosts:
|
||||
|
||||
127.0.1.1 cydefsig2.local.net
|
||||
|
||||
And create a file /etc/apache2/sites-available/<second_instance_name>
|
||||
containing:
|
||||
|
||||
<VirtualHost *:80>
|
||||
ServerAdmin webmaster@example.com
|
||||
ServerName cydefsig2.local.net
|
||||
ServerAlias mysite
|
||||
|
||||
# Indexes + Directory Root.
|
||||
DirectoryIndex index.php
|
||||
DocumentRoot /var/www/second_instance/cydefsig/app/webroot
|
||||
</VirtualHost>
|
|
@ -4,15 +4,15 @@
|
|||
// only show button if alert has not been sent // LATER show the ALERT button in red-ish
|
||||
?>
|
||||
<ul><li><?php
|
||||
echo $this->Form->postLink('Publish Event', array('action' => 'alert', $event['Event']['id']), null, 'Are you sure this event is complete and everyone should be informed?');
|
||||
echo $this->Form->postLink('Publish (no email)', array('action' => 'publish', $event['Event']['id']), null, 'Publish but do NOT send alert email? Only for minor changes!');
|
||||
echo $this->Form->postLink('Publish Event', array('controller' => 'events', 'action' => 'alert', $event['Event']['id']), null, 'Are you sure this event is complete and everyone should be informed?');
|
||||
echo $this->Form->postLink('Publish (no email)', array('controller' => 'events', 'action' => 'publish', $event['Event']['id']), null, 'Publish but do NOT send alert email? Only for minor changes!');
|
||||
?> </li></ul>
|
||||
<?php elseif (0 == $event['Event']['published']): ?>
|
||||
<ul><li>Not published</li></ul>
|
||||
<?php else: ?>
|
||||
<!-- ul><li>Alert already sent</li></ul -->
|
||||
<?php endif; ?>
|
||||
<ul><li><?php echo $this->Html->link(__('Contact reporter', true), array('action' => 'contact', $event['Event']['id'])); ?> </li></ul>
|
||||
<ul><li><?php echo $this->Html->link(__('Contact reporter', true), array('controller' => 'events', 'action' => 'contact', $event['Event']['id'])); ?> </li></ul>
|
||||
</div>
|
||||
|
||||
|
||||
|
@ -70,8 +70,13 @@
|
|||
<ul>
|
||||
<?php foreach ($relatedEvents as $relatedEvent): ?>
|
||||
<li><?php
|
||||
$link_text = $relatedEvent['Event']['date'].' ('.$relatedEvent['Event']['id'].')';
|
||||
echo $this->Html->link($link_text, array('controller' => 'events', 'action' => 'view', $relatedEvent['Event']['id']));
|
||||
if ('db' == Configure::read('CyDefSIG.correlation')) { // TODO array key
|
||||
$link_text = $relatedEvent['date'].' ('.$relatedEvent['id'].')';
|
||||
echo $this->Html->link($link_text, array('controller' => 'attributes', 'action' => 'event', $relatedEvent['id']));
|
||||
} else {
|
||||
$link_text = $relatedEvent['Event']['date'].' ('.$relatedEvent['Event']['id'].')';
|
||||
echo $this->Html->link($link_text, array('controller' => 'attributes', 'action' => 'event', $relatedEvent['Event']['id']));
|
||||
}
|
||||
?></li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
|
@ -112,18 +117,18 @@
|
|||
?></td>
|
||||
<td class="short" title="<?php echo $type_definitions[$attribute['Attribute']['type']]['desc'];?>"><?php echo $attribute['Attribute']['type'];?></td>
|
||||
<td><?php
|
||||
$sig_display = nl2br(h($attribute['Attribute']['value']));
|
||||
$sig_display = nl2br(h($attribute['Attribute']['value']));
|
||||
if('attachment' == $attribute['Attribute']['type'] ||
|
||||
'malware-sample' == $attribute['Attribute']['type'] ) {
|
||||
$filename_hash = explode('|', h($attribute['Attribute']['value']));
|
||||
$filename_hash = explode('|', h($attribute['Attribute']['value']));
|
||||
echo $this->Html->link($filename_hash[0], array('controller' => 'attributes', 'action' => 'download', $attribute['Attribute']['id']));
|
||||
if (isset($filename_hash[1])) echo ' | '.$filename_hash[1];
|
||||
} elseif (strpos($attribute['Attribute']['type'], '|') !== false) {
|
||||
$filename_hash = explode('|', h($attribute['Attribute']['value']));
|
||||
echo $filename_hash[0];
|
||||
if (isset($filename_hash[1])) echo ' | '.$filename_hash[1];
|
||||
} elseif ('vulnerability' == $attribute['Attribute']['type']) {
|
||||
echo $this->Html->link($sig_display, 'http://www.google.com/search?q='.$sig_display, array('target'=> '_blank'));
|
||||
if (isset($filename_hash[1])) echo ' | '.$filename_hash[1];
|
||||
} elseif ('vulnerability' == $attribute['Attribute']['type']) {
|
||||
echo $this->Html->link($sig_display, 'http://www.google.com/search?q='.$sig_display, array('target'=> '_blank'));
|
||||
} elseif ('link' == $attribute['Attribute']['type']) {
|
||||
echo $this->Html->link($sig_display, $sig_display);
|
||||
} else {
|
||||
|
@ -133,9 +138,13 @@
|
|||
<td class="short" style="text-align: center;">
|
||||
<?php
|
||||
$first = 0;
|
||||
if (null != $relatedAttributes[$attribute['Attribute']['id']]) {
|
||||
if (isset($relatedAttributes[$attribute['Attribute']['id']]) && (null != $relatedAttributes[$attribute['Attribute']['id']])) {
|
||||
foreach ($relatedAttributes[$attribute['Attribute']['id']] as $relatedAttribute) {
|
||||
echo $this->Html->link($relatedAttribute['Attribute']['event_id'], array('controller' => 'events', 'action' => 'view', $relatedAttribute['Attribute']['event_id']));
|
||||
if ('db' == Configure::read('CyDefSIG.correlation')) { // TODO array key
|
||||
echo $this->Html->link($relatedAttribute['Correlation']['event_id'], array('controller' => 'events', 'action' => 'view', $relatedAttribute['Correlation']['event_id']));
|
||||
} else {
|
||||
echo $this->Html->link($relatedAttribute['Attribute']['event_id'], array('controller' => 'events', 'action' => 'view', $relatedAttribute['Attribute']['event_id']));
|
||||
}
|
||||
echo ' ';
|
||||
}
|
||||
}
|
||||
|
@ -189,11 +198,10 @@
|
|||
<?php if ($isAdmin || $event['Event']['org'] == $me['org']): ?>
|
||||
<li><?php echo $this->Html->link(__('Add Attribute', true), array('controller' => 'attributes', 'action' => 'add', $event['Event']['id']));?> </li>
|
||||
<li><?php echo $this->Html->link(__('Add Attachment', true), array('controller' => 'attributes', '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><?php echo $this->Html->link(__('Edit Event', true), array('controller' => 'events', 'action' => 'edit', $event['Event']['id'])); ?> </li>
|
||||
<li><?php echo $this->Form->postLink(__('Delete Event'), array('controller' => 'events', 'action' => 'delete', $event['Event']['id']), null, __('Are you sure you want to delete # %s?', $event['Event']['id'])); ?></li>
|
||||
<li> </li>
|
||||
<?php endif; ?>
|
||||
<?php echo $this->element('actions_menu'); ?>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
</div>
|
|
@ -17,13 +17,13 @@ $buttonCounter = 0;
|
|||
foreach ($attributes as $attribute): ?>
|
||||
<tr>
|
||||
<td class="short">
|
||||
<?php echo $this->Html->link($attribute['Event']['id'], array('controller' => 'attributes', 'action' => 'event', $attribute['Event']['id'])); ?>
|
||||
<?php echo $this->Html->link($attribute['Event']['id'], array('controller' => 'events', 'action' => 'view', $attribute['Event']['id'])); ?>
|
||||
</td>
|
||||
<td title="<?php echo $category_definitions[$attribute['Attribute']['category']]['desc'];?>" class="short" onclick="document.location ='<?php echo $this->Html->url(array('controller' => 'attributes', 'action' => 'event', $attribute['Attribute']['event_id']), true) ;?>';">
|
||||
<td title="<?php echo $category_definitions[$attribute['Attribute']['category']]['desc'];?>" class="short" onclick="document.location ='<?php echo $this->Html->url(array('controller' => 'events', 'action' => 'view', $attribute['Attribute']['event_id']), true) ;?>';">
|
||||
<?php echo h($attribute['Attribute']['category']); ?> </td>
|
||||
<td title="<?php echo $type_definitions[$attribute['Attribute']['type']]['desc'];?>" class="short" onclick="document.location ='<?php echo $this->Html->url(array('controller' => 'attributes', 'action' => 'event', $attribute['Attribute']['event_id']), true) ;?>';">
|
||||
<td title="<?php echo $type_definitions[$attribute['Attribute']['type']]['desc'];?>" class="short" onclick="document.location ='<?php echo $this->Html->url(array('controller' => 'events', 'action' => 'view', $attribute['Attribute']['event_id']), true) ;?>';">
|
||||
<?php echo h($attribute['Attribute']['type']); ?> </td>
|
||||
<td onclick="document.location ='<?php echo $this->Html->url(array('controller' => 'attributes', 'action' => 'event', $attribute['Attribute']['event_id']), true) ;?>';">
|
||||
<td onclick="document.location ='<?php echo $this->Html->url(array('controller' => 'events', 'action' => 'view', $attribute['Attribute']['event_id']), true) ;?>';">
|
||||
<?php
|
||||
$sig_display = nl2br(h($attribute['Attribute']['value']));
|
||||
if('attachment' == $attribute['Attribute']['type'] ||
|
||||
|
@ -36,7 +36,7 @@ $buttonCounter = 0;
|
|||
echo $sig_display;
|
||||
}
|
||||
?> </td>
|
||||
<td class="short" style="text-align: center;" onclick="document.location ='<?php echo $this->Html->url(array('controller' => 'attributes', 'action' => 'event', $attribute['Attribute']['event_id']), true) ;?>';">
|
||||
<td class="short" style="text-align: center;" onclick="document.location ='<?php echo $this->Html->url(array('controller' => 'events', 'action' => 'view', $attribute['Attribute']['event_id']), true) ;?>';">
|
||||
<?php echo $attribute['Attribute']['to_ids'] ? 'Yes' : 'No'; ?> </td>
|
||||
<td class="actions"><?php
|
||||
if ($isAdmin || $attribute['Event']['org'] == $me['org']) {
|
||||
|
@ -44,7 +44,7 @@ $buttonCounter = 0;
|
|||
if ($isAclModify || $attribute['Event']['user_id'] == $me['id']) echo $this->Form->postLink(__('Delete'), array('action' => 'delete', $attribute['Attribute']['id']), null, __('Are you sure you want to delete this attribute?'));
|
||||
else echo $this->Html->link(__('Delete'), array('action' => 'delete', $attribute['Attribute']['id']), array('id' => $button_modify_status.$buttonCounter++,'class' => $button_modify_status));
|
||||
}
|
||||
echo $this->Html->link(__('View'), array('controller' => 'attributes', 'action' => 'event', $attribute['Attribute']['event_id']));
|
||||
echo $this->Html->link(__('View'), array('controller' => 'events', 'action' => 'view', $attribute['Attribute']['event_id']));
|
||||
?>
|
||||
</td>
|
||||
</tr>
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
<?php if($isAdmin): ?>
|
||||
<li> </li>
|
||||
<h3><?php echo __('Administration'); ?></h3>
|
||||
<li><?php echo $this->Html->link(__('Whitelist', true), array('controller' => 'whitelists', 'action' => 'index', 'admin' => true)); ?> </li>
|
||||
<li> </li>
|
||||
<li><?php echo $this->Html->link(__('New User', true), array('controller' => 'users', 'action' => 'add', 'admin' => true)); ?> </li>
|
||||
<li><?php echo $this->Html->link(__('List Users', true), array('controller' => 'users', 'action' => 'index', 'admin' => true)); ?> </li>
|
||||
<li><?php echo $this->Html->link(__('New Group', true), array('controller' => 'groups', 'action' => 'add', 'admin' => true)); ?> </li>
|
||||
|
@ -30,4 +32,4 @@
|
|||
<h3><?php echo __('Audit'); ?></h3>
|
||||
<li><?php echo $this->Html->link(__('List Logs', true), array('controller' => 'logs', 'action' => 'index', 'admin' => true)); ?> </li>
|
||||
<li><?php echo $this->Html->link(__('Search Logs', true), array('controller' => 'logs', 'action' => 'admin_search', 'admin' => true,'disabled'=>'disabled','readonly'=>'readonly')); ?> </li>
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
|
|
|
@ -20,6 +20,16 @@ You can <?php echo $this->Html->link('reset', array('controller' => 'users', 'ac
|
|||
<p>You can configure your tools to automatically download the following file:</p>
|
||||
<pre><?php echo Configure::read('CyDefSIG.baseurl');?>/events/nids/<?php echo $me['authkey']; ?></pre>
|
||||
<p></p>
|
||||
<p>Administration is able to maintain a whitelist containing host, domain name and IP numbers to exclude from the NIDS export.</p>
|
||||
|
||||
<h3>HIDS Export</h3>
|
||||
<p>An automatic export of all host related attributes is available, containing MD5 checksums. Only <em>published</em> events and attributes marked as <em>IDS Signature</em> are exported.</p>
|
||||
<p>You can configure your tools to automatically download the following files:</p>
|
||||
<h4>md5</h4>
|
||||
<pre><?php echo Configure::read('CyDefSIG.baseurl');?>/events/hids_md5/<?php echo $me['authkey']; ?></pre>
|
||||
<h4>sha1</h4>
|
||||
<pre><?php echo Configure::read('CyDefSIG.baseurl');?>/events/hids_sha1/<?php echo $me['authkey']; ?></pre>
|
||||
<p></p>
|
||||
|
||||
<h3>Text Export</h3>
|
||||
<p>An automatic export of all attributes of a specific type to a plain text file.</p>
|
||||
|
|
|
@ -8,9 +8,11 @@ $buttonCounter = 0;
|
|||
<h2>Events</h2>
|
||||
<table cellpadding="0" cellspacing="0">
|
||||
<tr>
|
||||
<th><?php echo $this->Paginator->sort('id');?></th>
|
||||
<?php if ('true' == Configure::read('CyDefSIG.showorg') || $isAdmin): ?>
|
||||
<th><?php echo $this->Paginator->sort('org');?></th>
|
||||
<?php endif; ?>
|
||||
<th><?php echo $this->Paginator->sort('id');?></th>
|
||||
<?php if ('true' == Configure::read('CyDefSIG.showowner') || $isAdmin): ?>
|
||||
<th><?php echo $this->Paginator->sort('user_id', 'Email');?></th>
|
||||
<?php endif; ?>
|
||||
<th><?php echo $this->Paginator->sort('date');?></th>
|
||||
|
@ -25,12 +27,18 @@ $buttonCounter = 0;
|
|||
foreach ($events as $event):
|
||||
?>
|
||||
<tr>
|
||||
<?php if ('true' == Configure::read('CyDefSIG.showorg') || $isAdmin): ?>
|
||||
<td class="short" onclick="document.location ='<?php echo $this->Html->url(array('action' => 'view', $event['Event']['id']), true) ;?>';">
|
||||
<?php
|
||||
echo $this->Html->image('orgs/'.h($event['Event']['org']).'.png', array('alt' => h($event['Event']['org']),'width'=>'50','hight'=>'50'));
|
||||
?>
|
||||
</td>
|
||||
<?php endif; ?>
|
||||
<td class="short">
|
||||
<?php echo $this->Html->link($event['Event']['id'], array('controller' => 'events', 'action' => 'view', $event['Event']['id'])); ?>
|
||||
</td>
|
||||
<?php if ('true' == Configure::read('CyDefSIG.showorg') || $isAdmin): ?>
|
||||
<td class="short" onclick="document.location ='<?php echo $this->Html->url(array('action' => 'view', $event['Event']['id']), true) ;?>';">
|
||||
<?php echo h($event['Event']['org']); ?> </td>
|
||||
|
||||
<?php if ('true' == Configure::read('CyDefSIG.showowner') || $isAdmin): ?>
|
||||
<td class="short" onclick="document.location ='<?php echo $this->Html->url(array('action' => 'view', $event['Event']['id']), true) ;?>';">
|
||||
<?php echo h($event['User']['email']); ?> </td>
|
||||
<?php endif; ?>
|
||||
|
@ -58,7 +66,7 @@ $buttonCounter = 0;
|
|||
else echo $this->Html->link(__('Delete'), array('action' => 'delete', $event['Event']['id']), array('id' =>$button_modify_status.$buttonCounter++,'class' => $button_modify_status));
|
||||
}
|
||||
?>
|
||||
<?php echo $this->Html->link(__('View', true), array('controller' => 'attributes', 'action' => 'event', $event['Event']['id'])); ?>
|
||||
<?php echo $this->Html->link(__('View', true), array('controller' => 'events', 'action' => 'view', $event['Event']['id'])); ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
|
|
|
@ -26,8 +26,9 @@ $buttonCounter = 0;
|
|||
<ul><li><?php echo $this->Html->link(__('Contact reporter', true), array('action' => 'contact', $event['Event']['id'])); ?> </li></ul>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<?php if ('true' == Configure::read('CyDefSIG.showorg') || $isAdmin): ?>
|
||||
<?php echo $this->Html->image('orgs/'.h($event['Event']['org']).'.png', array('alt' => h($event['Event']['org']),'width'=>'50','hight'=>'50', 'style' => 'float:right;')); ?>
|
||||
<?php endif; ?>
|
||||
<h2>Event</h2>
|
||||
<dl>
|
||||
<dt>ID</dt>
|
||||
|
@ -41,6 +42,8 @@ $buttonCounter = 0;
|
|||
<?php echo h($event['Event']['org']); ?>
|
||||
|
||||
</dd>
|
||||
<?php endif; ?>
|
||||
<?php if ('true' == Configure::read('CyDefSIG.showowner') || $isAdmin): ?>
|
||||
<dt>Email</dt>
|
||||
<dd>
|
||||
<?php echo h($event['User']['email']); ?>
|
||||
|
@ -144,9 +147,9 @@ $buttonCounter = 0;
|
|||
<td class="short" style="text-align: center;">
|
||||
<?php
|
||||
$first = 0;
|
||||
if (null != $relatedAttributes[$attribute['id']]) {
|
||||
if (isset($relatedAttributes[$attribute['id']]) && (null != $relatedAttributes[$attribute['id']])) {
|
||||
foreach ($relatedAttributes[$attribute['id']] as $relatedAttribute) {
|
||||
echo $this->Html->link($relatedAttribute['Attribute']['event_id'], array('controller' => 'events', 'action' => 'view', $relatedAttribute['Attribute']['event_id']));
|
||||
echo $this->Html->link($relatedAttribute['Attribute']['event_id'], array('controller' => 'events', 'action' => 'view', $relatedAttribute['Attribute']['event_id']));
|
||||
echo ' ';
|
||||
}
|
||||
}
|
||||
|
@ -328,4 +331,4 @@ $('#button_off38').click(function() {
|
|||
$('#button_off39').click(function() {
|
||||
return false;
|
||||
});
|
||||
</script>
|
||||
</script>
|
|
@ -45,7 +45,7 @@
|
|||
<div id="header">
|
||||
<h1><?php echo $this->Html->link(Configure::read('CyDefSIG.header'), array('controller' => 'events', 'action' => 'index')); ?>
|
||||
<?php if($logo = Configure::read('CyDefSIG.logo')) {
|
||||
echo "<img src=\"$logo\" align=\"right\" height=\"30\">";
|
||||
echo $this->Html->image($logo, array('alt' => h(Configure::read('CyDefSIG.header')),'align'=>'right','height'=>'30'));
|
||||
}?></h1>
|
||||
</div>
|
||||
<div id="content">
|
||||
|
|
|
@ -7,7 +7,11 @@
|
|||
'label' => 'Base URL',
|
||||
'before' => $this->Html->div('forminfo', 'The base-url to the external server you want to sync with.<br/>Example: <i>https://foo.sig.mil.be</i>'),
|
||||
));
|
||||
echo $this->Form->input('authkey', array(
|
||||
echo $this->Form->input('organization', array(
|
||||
'label' => 'Organization',
|
||||
'before' => $this->Html->div('forminfo', 'The organization having the external server you want to sync with.<br/>Example: <i>BE</i>'),
|
||||
));
|
||||
echo $this->Form->input('authkey', array(
|
||||
'before' => $this->Html->div('forminfo', 'You can find the authentication key on your profile on the external server.'),
|
||||
));
|
||||
echo $this->Form->input('push', array(
|
||||
|
|
|
@ -8,6 +8,10 @@
|
|||
'label' => 'Base URL',
|
||||
'before' => $this->Html->div('forminfo', 'The base-url to the external server you want to sync with.<br/>Example: <i>https://foo.sig.mil.be</i>'),
|
||||
));
|
||||
echo $this->Form->input('organization', array(
|
||||
'label' => 'Organization',
|
||||
'before' => $this->Html->div('forminfo', 'The organization having the external server you want to sync with.<br/>Example: <i>https://foo.sig.mil.be</i>'),
|
||||
));
|
||||
echo $this->Form->input('authkey', array(
|
||||
'before' => $this->Html->div('forminfo', 'You can find the authentication key on your profile on the external server.<br/><i>Leave empty if you don\'t want to change it</i>.'),
|
||||
));
|
||||
|
|
|
@ -10,6 +10,7 @@ $buttonCounter = 0;
|
|||
<th><?php echo $this->Paginator->sort('push');?></th>
|
||||
<th><?php echo $this->Paginator->sort('pull');?></th>
|
||||
<th><?php echo $this->Paginator->sort('url');?></th>
|
||||
<th>From</th>
|
||||
<?php if ($isAdmin): ?>
|
||||
<th><?php echo $this->Paginator->sort('org');?></th>
|
||||
<?php endif; ?>
|
||||
|
@ -23,6 +24,7 @@ $buttonCounter = 0;
|
|||
<td class="short" style="text-align: center;"><?php echo ($server['Server']['push'])? 'Yes' : 'No'; ?> </td>
|
||||
<td class="short" style="text-align: center;"><?php echo ($server['Server']['pull'])? 'Yes' : 'No'; ?> </td>
|
||||
<td><?php echo h($server['Server']['url']); ?> </td>
|
||||
<td><?php echo h($server['Server']['organization']); ?> </td>
|
||||
<?php if ($isAdmin): ?>
|
||||
<td class="short"><?php echo h($server['Server']['org']); ?> </td>
|
||||
<?php endif; ?>
|
||||
|
@ -460,4 +462,4 @@ $('#button_off120').click(function() {
|
|||
$('#button_off129').click(function() {
|
||||
return false;
|
||||
});
|
||||
</script>
|
||||
</script>
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
<div class="whitelists form">
|
||||
<?php echo $this->Form->create('Whitelist');?>
|
||||
<fieldset>
|
||||
<legend><?php echo __('Add Whitelist'); ?></legend>
|
||||
<?php
|
||||
echo $this->Form->input('name');
|
||||
?>
|
||||
</fieldset>
|
||||
<?php echo $this->Form->end(__('Submit'));?>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<h3><?php echo __('Actions'); ?></h3>
|
||||
<ul>
|
||||
|
||||
<li><?php echo $this->Html->link(__('List Whitelists'), array('admin' => true, 'action' => 'index'));?></li>
|
||||
</ul>
|
||||
</div>
|
|
@ -0,0 +1,19 @@
|
|||
<div class="whitelists form">
|
||||
<?php echo $this->Form->create('Whitelist');?>
|
||||
<fieldset>
|
||||
<legend><?php echo __('Edit Whitelist'); ?></legend>
|
||||
<?php
|
||||
echo $this->Form->input('id');
|
||||
echo $this->Form->input('name');
|
||||
?>
|
||||
</fieldset>
|
||||
<?php echo $this->Form->end(__('Submit'));?>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<h3><?php echo __('Actions'); ?></h3>
|
||||
<ul>
|
||||
|
||||
<li><?php echo $this->Form->postLink(__('Delete'), array('admin' => true, 'action' => 'delete', $this->Form->value('Whitelist.id')), null, __('Are you sure you want to delete # %s?', $this->Form->value('Whitelist.id'))); ?></li>
|
||||
<li><?php echo $this->Html->link(__('List Whitelists'), array('admin' => true, 'action' => 'index'));?></li>
|
||||
</ul>
|
||||
</div>
|
|
@ -0,0 +1,42 @@
|
|||
<div class="whitelists index">
|
||||
<h2><?php echo __('Whitelists');?></h2>
|
||||
<table cellpadding="0" cellspacing="0">
|
||||
<tr>
|
||||
<th><?php echo $this->Paginator->sort('id');?></th>
|
||||
<th><?php echo $this->Paginator->sort('name');?></th>
|
||||
<th class="actions"><?php echo __('Actions');?></th>
|
||||
</tr>
|
||||
<?php
|
||||
foreach ($whitelists as $whitelist): ?>
|
||||
<tr>
|
||||
<td><?php echo h($whitelist['Whitelist']['id']); ?> </td>
|
||||
<td><?php echo h($whitelist['Whitelist']['name']); ?> </td>
|
||||
<td class="actions">
|
||||
<?php echo $this->Html->link(__('View'), array('admin' => true, 'action' => 'view', $whitelist['Whitelist']['id'])); ?>
|
||||
<?php echo $this->Html->link(__('Edit'), array('admin' => true, 'action' => 'edit', $whitelist['Whitelist']['id'])); ?>
|
||||
<?php echo $this->Form->postLink(__('Delete'), array('admin' => true, 'action' => 'delete', $whitelist['Whitelist']['id']), null, __('Are you sure you want to delete # %s?', $whitelist['Whitelist']['id'])); ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</table>
|
||||
<p>
|
||||
<?php
|
||||
echo $this->Paginator->counter(array(
|
||||
'format' => __('Page {:page} of {:pages}, showing {:current} records out of {:count} total, starting on record {:start}, ending on {:end}')
|
||||
));
|
||||
?> </p>
|
||||
|
||||
<div class="paging">
|
||||
<?php
|
||||
echo $this->Paginator->prev('< ' . __('previous'), array(), null, array('class' => 'prev disabled'));
|
||||
echo $this->Paginator->numbers(array('separator' => ''));
|
||||
echo $this->Paginator->next(__('next') . ' >', array(), null, array('class' => 'next disabled'));
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<h3><?php echo __('Actions'); ?></h3>
|
||||
<ul>
|
||||
<li><?php echo $this->Html->link(__('New Whitelist'), array('admin' => true, 'action' => 'add')); ?></li>
|
||||
</ul>
|
||||
</div>
|
|
@ -0,0 +1,24 @@
|
|||
<div class="whitelists view">
|
||||
<h2><?php echo __('Whitelist');?></h2>
|
||||
<dl>
|
||||
<dt><?php echo __('Id'); ?></dt>
|
||||
<dd>
|
||||
<?php echo h($whitelist['Whitelist']['id']); ?>
|
||||
|
||||
</dd>
|
||||
<dt><?php echo __('Name'); ?></dt>
|
||||
<dd>
|
||||
<?php echo h($whitelist['Whitelist']['name']); ?>
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<h3><?php echo __('Actions'); ?></h3>
|
||||
<ul>
|
||||
<li><?php echo $this->Html->link(__('Edit Whitelist'), array('admin' => true, 'action' => 'edit', $whitelist['Whitelist']['id'])); ?> </li>
|
||||
<li><?php echo $this->Form->postLink(__('Delete Whitelist'), array('admin' => true, 'action' => 'delete', $whitelist['Whitelist']['id']), null, __('Are you sure you want to delete # %s?', $whitelist['Whitelist']['id'])); ?> </li>
|
||||
<li><?php echo $this->Html->link(__('List Whitelists'), array('admin' => true, 'action' => 'index')); ?> </li>
|
||||
<li><?php echo $this->Html->link(__('New Whitelist'), array('admin' => true, 'action' => 'add')); ?> </li>
|
||||
</ul>
|
||||
</div>
|
Binary file not shown.
After Width: | Height: | Size: 62 KiB |
Binary file not shown.
After Width: | Height: | Size: 11 KiB |
Binary file not shown.
After Width: | Height: | Size: 6.8 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
|
@ -0,0 +1,2 @@
|
|||
curl -i -H "Accept: application/xml" -H "content-type: text/xml" -H "Authorization: vlf4o42bYSVVWLm28jLB85my4HBZWXTri8vGdySb" \
|
||||
--data "@input/event.xml" -X POST http://localhost/events
|
|
@ -0,0 +1,2 @@
|
|||
curl -H "Accept: application/xml" -H "Authorization: vlf4o42bYSVVWLm28jLB85my4HBZWXTri8vGdySb" \
|
||||
-X DELETE http://localhost/events/$1
|
|
@ -0,0 +1,6 @@
|
|||
curl -H "Accept: application/xml" -H "content-type: text/xml" -H "Authorization: vlf4o42bYSVVWLm28jLB85my4HBZWXTri8vGdySb" \
|
||||
--data "@input/event.xml" -X PUT http://localhost/events/14
|
||||
|
||||
# POST can be used as well..
|
||||
#curl -H "Accept: application/xml" -H "content-type: text/xml" -H "Authorization: vlf4o42bYSVVWLm28jLB85my4HBZWXTri8vGdySb" \
|
||||
#--data "@input/event.xml" -X POST http://localhost/events/14
|
|
@ -0,0 +1,2 @@
|
|||
curl -H "Accept: application/xml" -H "Authorization: vlf4o42bYSVVWLm28jLB85my4HBZWXTri8vGdySb" \
|
||||
-X GET http://localhost/events
|
|
@ -0,0 +1,66 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Event>
|
||||
<id>14</id>
|
||||
<org>NCIRC</org>
|
||||
<date>2012-04-12</date>
|
||||
<risk>Medium</risk>
|
||||
<info>TT6666: malixioious XLS (EDIT 234..5)</info>
|
||||
<user_id>3</user_id>
|
||||
<alerted>0</alerted>
|
||||
<uuid>4f8c2c4e-00dc-42c9-83ad-76e9ff32448e</uuid>
|
||||
<private>0</private>
|
||||
<published>0</published>
|
||||
<Attribute>
|
||||
<id>116</id>
|
||||
<event_id>14</event_id>
|
||||
<type>ip-dst</type>
|
||||
<category>Network activity</category>
|
||||
<to_ids>1</to_ids>
|
||||
<uuid>4f8c2cc3-0410-4bf0-8559-5b9dff32448e</uuid>
|
||||
<revision>1</revision>
|
||||
<private>0</private>
|
||||
<value>1.1.1.111</value>
|
||||
<category_order>g</category_order>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<id>117</id>
|
||||
<event_id>14</event_id>
|
||||
<type>malware-sample</type>
|
||||
<category>Payload delivery</category>
|
||||
<to_ids>0</to_ids>
|
||||
<uuid>4f8c2d08-7e6c-4648-8730-50a7ff32448e</uuid>
|
||||
<revision>1</revision>
|
||||
<private>0</private>
|
||||
<value>Summary_report_Vienna_2012 27 March
|
||||
ok_z.doc|b34a8fcf8e5c81de3f6f177bb6171929</value>
|
||||
<category_order>c</category_order>
|
||||
<data />
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<id>115</id>
|
||||
<event_id>14</event_id>
|
||||
<type>vulnerability</type>
|
||||
<category>Payload delivery</category>
|
||||
<to_ids>1</to_ids>
|
||||
<uuid>4f8c2c69-9bf8-4279-8d03-2138ff32448e</uuid>
|
||||
<revision>1</revision>
|
||||
<private>0</private>
|
||||
<value>CVE-2010-3333</value>
|
||||
<category_order>c</category_order>
|
||||
</Attribute>
|
||||
<RelatedEvent>
|
||||
<id>11</id>
|
||||
<date>2012-04-03</date>
|
||||
<uuid>4f8812ff-ded0-4592-9227-0615ff32448e</uuid>
|
||||
</RelatedEvent>
|
||||
<RelatedEvent>
|
||||
<id>9</id>
|
||||
<date>2012-04-02</date>
|
||||
<uuid>4f85981e-d044-4b16-bc16-0a35ff32448e</uuid>
|
||||
</RelatedEvent>
|
||||
<RelatedEvent>
|
||||
<id>6</id>
|
||||
<date>2012-03-22</date>
|
||||
<uuid>4f7a9faa-91d4-4c91-8ec6-0878ff32448e</uuid>
|
||||
</RelatedEvent>
|
||||
</Event>
|
|
@ -0,0 +1,2 @@
|
|||
curl -H "Accept: application/xml" -H "Authorization: vlf4o42bYSVVWLm28jLB85my4HBZWXTri8vGdySb" \
|
||||
-X GET http://localhost/events/$1
|
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue