chg: Further work on the objects

- view events with objects via the API
- Further improvements to adding objects
pull/2489/head
iglocska 2017-07-02 22:42:44 +02:00
parent d2e1a8e259
commit df5daae664
5 changed files with 190 additions and 36 deletions

View File

@ -71,7 +71,19 @@ class ObjectsController extends AppController {
if (empty($error)) {
$error = $this->Object->ObjectTemplate->checkTemplateConformity($template, $object);
if ($error === true) {
$this->Object->saveObject($object, $eventId, $template, $this->Auth->user(), $errorBehaviour = 'halt');
$result = $this->Object->saveObject($object, $eventId, $template, $this->Auth->user(), $errorBehaviour = 'halt');
}
if ($this->_isRest()) {
if (is_numeric($result)) {
$object = $this->Object->find('first', array(
'recursive' => -1,
'conditions' => array('Object.id' => $result),
'contain' => array('Attribute')
));
return $this->RestResponse->viewData($object, $this->response->type());
} else {
return $this->RestResponse->saveFailResponse('Attributes', 'add', false, $result, $this->response->type());
}
}
}
}

View File

@ -10,7 +10,7 @@ class JSONConverterTool {
}
public function convert($event, $isSiteAdmin=false) {
$toRearrange = array('Org', 'Orgc', 'SharingGroup', 'Attribute', 'ShadowAttribute', 'RelatedAttribute', 'RelatedEvent', 'Galaxy');
$toRearrange = array('Org', 'Orgc', 'SharingGroup', 'Attribute', 'ShadowAttribute', 'RelatedAttribute', 'RelatedEvent', 'Galaxy', 'Object');
foreach ($toRearrange as $object) {
if (isset($event[$object])) {
$event['Event'][$object] = $event[$object];
@ -49,29 +49,12 @@ class JSONConverterTool {
}
if (isset($event['Event']['Attribute'])) {
// remove value1 and value2 from the output and remove invalid utf8 characters for the xml parser
foreach ($event['Event']['Attribute'] as $key => $value) {
if (isset($value['SharingGroup']) && empty($value['SharingGroup'])) {
unset($event['Event']['Attribute'][$key]['SharingGroup']);
}
unset($event['Event']['Attribute'][$key]['value1']);
unset($event['Event']['Attribute'][$key]['value2']);
unset($event['Event']['Attribute'][$key]['category_order']);
if (isset($event['RelatedAttribute'][$value['id']])) {
$event['Event']['Attribute'][$key]['RelatedAttribute'] = $event['Event']['RelatedAttribute'][$value['id']];
foreach ($event['Event']['Attribute'][$key]['RelatedAttribute'] as &$ra) {
$ra = array('Attribute' => $ra);
}
}
if (isset($event['Event']['Attribute'][$key]['AttributeTag'])) {
foreach ($event['Event']['Attribute'][$key]['AttributeTag'] as $atk => $tag) {
unset($tag['Tag']['org_id']);
$event['Event']['Attribute'][$key]['Tag'][$atk] = $tag['Tag'];
}
unset($event['Event']['Attribute'][$key]['AttributeTag']);
}
}
$event['Event']['Attribute'] = $this->__cleanAttributes($event['Event']['Attribute']);
}
if (isset($event['Event']['Object'])) {
$event['Event']['Object'] = $this->__cleanObjects($event['Event']['Object']);
}
unset($event['Event']['RelatedAttribute']);
if (isset($event['Event']['RelatedEvent'])) {
foreach ($event['Event']['RelatedEvent'] as $key => $value) {
@ -87,6 +70,44 @@ class JSONConverterTool {
return json_encode($result, JSON_PRETTY_PRINT);
}
private function __cleanAttributes($attributes) {
// remove value1 and value2 from the output and remove invalid utf8 characters for the xml parser
foreach ($attributes as $key => $value) {
if (isset($value['SharingGroup']) && empty($value['SharingGroup'])) {
unset($attributes[$key]['SharingGroup']);
}
unset($attributes[$key]['value1']);
unset($attributes[$key]['value2']);
unset($attributes[$key]['category_order']);
if (isset($event['RelatedAttribute'][$value['id']])) {
$attributes[$key]['RelatedAttribute'] = $event['Event']['RelatedAttribute'][$value['id']];
foreach ($attributes[$key]['RelatedAttribute'] as &$ra) {
$ra = array('Attribute' => $ra);
}
}
if (isset($attributes[$key]['AttributeTag'])) {
foreach ($attributes[$key]['AttributeTag'] as $atk => $tag) {
unset($tag['Tag']['org_id']);
$attributes[$key]['Tag'][$atk] = $tag['Tag'];
}
unset($attributes[$key]['AttributeTag']);
}
}
return $attributes;
}
private function __cleanObjects($objects) {
foreach ($objects as $k => $object) {
if (!empty($object['Attribute'])) {
$objects[$k]['Attribute'] = $this->__cleanAttributes($object['Attribute']);
} else {
unset($objects[$k]);
}
}
$objects = array_values($objects);
return $objects;
}
public function arrayPrinter($array, $root = true) {
if (is_array($array)) {
$resultArray = array();

View File

@ -2364,6 +2364,20 @@ class Attribute extends AppModel {
else return 'Could not save changes.';
}
public function saveAttributes($attributes) {
foreach ($attributes as $k => $attribute) {
if (!empty($attribute['encrypt']) && $attribute['encrypt']) {
$result = $this->handleMaliciousBase64($attribute['event_id'], $attribute['value'], $attribute['data'], array('md5'));
$attribute['data'] = $result['data'];
$attribute['value'] = $attribute['value'] . '|' . $result['md5'];
}
unset($attribute['Attachment']);
$this->create();
$this->save($attribute);
}
return true;
}
public function saveAndEncryptAttribute($attribute, $user) {
$hashes = array('md5' => 'malware-sample', 'sha1' => 'filename|sha1', 'sha256' => 'filename|sha256');
if ($attribute['encrypt']) {

View File

@ -311,6 +311,19 @@ class Event extends AppModel {
'finderQuery' => '',
'counterQuery' => ''
),
'Object' => array(
'className' => 'Object',
'foreignKey' => 'event_id',
'dependent' => true,
'conditions' => '',
'fields' => '',
'order' => false,
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
),
'EventTag' => array(
'className' => 'EventTag',
'dependent' => true,
@ -1247,6 +1260,13 @@ class Event extends AppModel {
$isSiteAdmin = $user['Role']['perm_site_admin'];
if (isset($options['disableSiteAdmin']) && $options['disableSiteAdmin']) $isSiteAdmin = false;
$conditionsAttributes = array();
$conditionsObjects = array();
if (isset($options['flattenObjects']) && $options['flattenObjects']) {
$flattenObjects = true;
} else {
$flattenObjects = false;
}
// restricting to non-private or same org if the user is not a site-admin.
if (!$isSiteAdmin) {
@ -1290,14 +1310,28 @@ class Event extends AppModel {
)),
'(SELECT events.org_id FROM events WHERE events.id = Attribute.event_id)' => $user['org_id']
);
$conditionsObjects['AND'][0]['OR'] = array(
array('AND' => array(
'Object.distribution >' => 0,
'Object.distribution !=' => 4,
)),
array('AND' => array(
'Object.distribution' => 4,
'Object.sharing_group_id' => $sgids,
)),
'(SELECT events.org_id FROM events WHERE events.id = Object.event_id)' => $user['org_id']
);
}
if ($options['distribution']) {
$conditions['AND'][] = array('Event.distribution' => $options['distribution']);
$conditionsAttributes['AND'][] = array('Attribute.distribution' => $options['distribution']);
$conditionsObjects['AND'][] = array('Object.distribution' => $options['distribution']);
}
if ($options['sharing_group_id']) {
$conditions['AND'][] = array('Event.sharing_group_id' => $options['sharing_group_id']);
$conditionsAttributes['AND'][] = array('Attribute.sharing_group_id' => $options['sharing_group_id']);
$conditionsObject['AND'][] = array('Object.sharing_group_id' => $options['sharing_group_id']);
}
if ($options['from']) $conditions['AND'][] = array('Event.date >=' => $options['from']);
if ($options['to']) $conditions['AND'][] = array('Event.date <=' => $options['to']);
@ -1311,8 +1345,17 @@ class Event extends AppModel {
'Attribute.deleted' => 0
)
);
$conditionsObjects['AND'][] = array(
'OR' => array(
'(SELECT events.org_id FROM events WHERE events.id = Object.event_id)' => $user['org_id'],
'Object.deleted' => 0
)
);
}
} else $conditionsAttributes['AND']['Attribute.deleted'] = 0;
} else {
$conditionsAttributes['AND']['Attribute.deleted'] = 0;
$conditionsObject['AND']['Object.deleted'] = 0;
}
if ($options['idList'] && !$options['tags']) {
$conditions['AND'][] = array('Event.id' => $options['idList']);
@ -1346,7 +1389,8 @@ class Event extends AppModel {
// do not expose all the data ...
$fields = array('Event.id', 'Event.orgc_id', 'Event.org_id', 'Event.date', 'Event.threat_level_id', 'Event.info', 'Event.published', 'Event.uuid', 'Event.attribute_count', 'Event.analysis', 'Event.timestamp', 'Event.distribution', 'Event.proposal_email_lock', 'Event.user_id', 'Event.locked', 'Event.publish_timestamp', 'Event.sharing_group_id', 'Event.disable_correlation');
$fieldsAtt = array('Attribute.id', 'Attribute.type', 'Attribute.category', 'Attribute.value', 'Attribute.to_ids', 'Attribute.uuid', 'Attribute.event_id', 'Attribute.distribution', 'Attribute.timestamp', 'Attribute.comment', 'Attribute.sharing_group_id', 'Attribute.deleted', 'Attribute.disable_correlation');
$fieldsAtt = array('Attribute.id', 'Attribute.type', 'Attribute.category', 'Attribute.value', 'Attribute.to_ids', 'Attribute.uuid', 'Attribute.event_id', 'Attribute.distribution', 'Attribute.timestamp', 'Attribute.comment', 'Attribute.sharing_group_id', 'Attribute.deleted', 'Attribute.disable_correlation', 'Attribute.object_id', 'Attribute.object_relation');
$fieldsObj = array('*');
$fieldsShadowAtt = array('ShadowAttribute.id', 'ShadowAttribute.type', 'ShadowAttribute.category', 'ShadowAttribute.value', 'ShadowAttribute.to_ids', 'ShadowAttribute.uuid', 'ShadowAttribute.event_uuid', 'ShadowAttribute.event_id', 'ShadowAttribute.old_id', 'ShadowAttribute.comment', 'ShadowAttribute.org_id', 'ShadowAttribute.proposal_to_delete', 'ShadowAttribute.timestamp');
$fieldsOrg = array('id', 'name', 'uuid');
$fieldsServer = array('id', 'url', 'name');
@ -1373,7 +1417,6 @@ class Event extends AppModel {
foreach ($sharingGroupDataTemp as $k => $v) {
$sharingGroupData[$v['SharingGroup']['id']] = $v;
}
$params = array(
'conditions' => $conditions,
'recursive' => 0,
@ -1393,6 +1436,11 @@ class Event extends AppModel {
'order' => false
),
),
'Object' => array(
'fields' => $fieldsObj,
'conditions' => $conditionsObjects,
'order' => false
),
'ShadowAttribute' => array(
'fields' => $fieldsShadowAtt,
'conditions' => array('deleted' => 0),
@ -1405,6 +1453,9 @@ class Event extends AppModel {
)
)
);
if ($flattenObjects) {
unset($params['contain']['Object']);
}
if ($options['metadata']) {
unset($params['contain']['Attribute']);
unset($params['contain']['ShadowAttribute']);
@ -1547,6 +1598,16 @@ class Event extends AppModel {
}
}
if ($event['Attribute'][$key]['object_id'] != 0) {
if (!empty($event['Object'])) {
foreach ($event['Object'] as $objectKey => $objectValue) {
if ($event['Attribute'][$key]['object_id'] == $objectValue['id']) {
$event['Object'][$objectKey]['Attribute'][] = $event['Attribute'][$key];
}
}
}
unset($event['Attribute'][$key]);
}
}
$event['Attribute'] = array_values($event['Attribute']);
}

View File

@ -28,6 +28,7 @@ class Object extends AppModel {
'conditions' => array('Object.template_uuid' => 'ObjectTemplate.uuid')
)
);
public $hasMany = array(
'Attribute' => array(
'className' => 'Attribute',
@ -42,9 +43,28 @@ class Object extends AppModel {
public $validate = array(
);
public function beforeValidate($options = array()) {
parent::beforeValidate();
if (empty($this->data['Object']['comment'])) {
$this->data['Object']['comment'] = "";
}
// generate UUID if it doesn't exist
if (empty($this->data['Object']['uuid'])) {
$this->data['Object']['uuid'] = CakeText::uuid();
}
// generate timestamp if it doesn't exist
if (empty($this->data['Object']['timestamp'])) {
$date = new DateTime();
$this->data['Object']['timestamp'] = $date->getTimestamp();
}
if (!isset($this->data['Object']['distribution']) || $this->data['Object']['distribution'] != 4) $this->data['Object']['sharing_group_id'] = 0;
if (!isset($this->data['Object']['distribution'])) $this->data['Object']['distribution'] = 5;
return true;
}
public function saveObject($object, $eventId, $template, $user, $errorBehaviour = 'drop') {
$this->create();
//id name meta-category description template_uuid template_version event_id uuid timestamp distribution sharing_group_id comment
$templateFields = array(
'name' => 'name',
'meta-category' => 'meta-category',
@ -56,11 +76,17 @@ class Object extends AppModel {
$object['Object'][$k] = $template['ObjectTemplate'][$v];
}
$object['Object']['event_id'] = $eventId;
debug($template);
debug($object);
throw new Exception();
$this->save($object);
return $this->Attribute->saveAttributes($attributes, $eventId, $objectId = 0, $errorBehaviour);
$result = false;
if ($this->save($object)) {
$id = $this->id;
foreach ($object['Attribute'] as $k => $attribute) {
$object['Attribute'][$k]['object_id'] = $id;
}
$result = $this->Attribute->saveAttributes($object['Attribute']);
} else {
$result = $this->validationErrors;
}
return $id;
}
public function buildEventConditions($user, $sgids = false) {
@ -262,11 +288,31 @@ class Object extends AppModel {
if ($attribute['value_select'] !== 'Enter value manually') {
$attributes['Attribute'][$k]['value'] = $attribute['value_select'];
}
unset($attribute['value_select']);
unset($attributes['Attribute'][$k]['value_select']);
}
unset($attribute['save']);
if (isset($attribute['Attachment'])) {
// Check if there were problems with the file upload
// only keep the last part of the filename, this should prevent directory attacks
$filename = basename($attribute['Attachment']['name']);
$tmpfile = new File($attribute['Attachment']['tmp_name']);
if ((isset($attribute['Attachment']['error']) && $attribute['Attachment']['error'] == 0) ||
(!empty($attribute['Attachment']['tmp_name']) && $attribute['Attachment']['tmp_name'] != 'none')
) {
if (!is_uploaded_file($tmpfile->path))
throw new InternalErrorException('PHP says file was not uploaded. Are you attacking me?');
} else {
return 'Issues with the file attachment for the ' . $attribute['object_relation'] . ' attribute. The error code returned is ' . $attribute['Attachment']['error'];
}
$attributes['Attribute'][$k]['value'] = $attribute['Attachment']['name'];
unset($attributes['Attribute'][$k]['Attachment']);
$attributes['Attribute'][$k]['encrypt'] = $attribute['type'] == 'malware-sample' ? 1 : 0;
$attributes['Attribute'][$k]['data'] = base64_encode($tmpfile->read());
$tmpfile->delete();
$tmpfile->close();
}
unset($attributes['Attribute'][$k]['save']);
if ($attribute['distribution'] != 4) {
$attribute['sharing_group_id'] = 0;
$attributes['Attribute'][$k]['sharing_group_id'] = 0;
}
}
return $attributes;