mirror of https://github.com/MISP/MISP
235 lines
11 KiB
PHP
235 lines
11 KiB
PHP
<?php
|
|
|
|
App::uses('AppController', 'Controller');
|
|
|
|
class RegexpController extends AppController
|
|
{
|
|
public $components = array('RequestHandler', 'AdminCrud');
|
|
|
|
public $paginate = array(
|
|
'limit' => 60,
|
|
'order' => array(
|
|
'Regexp.id' => 'ASC'
|
|
)
|
|
);
|
|
|
|
public function admin_add()
|
|
{
|
|
$this->loadModel('Attribute');
|
|
$types = array_keys($this->Attribute->typeDefinitions);
|
|
if (!$this->userRole['perm_regexp_access']) {
|
|
$this->redirect(array('controller' => 'regexp', 'action' => 'index', 'admin' => false));
|
|
}
|
|
if ($this->request->is('post')) {
|
|
if ($this->request->data['Regexp']['all'] == 1) {
|
|
$this->Regexp->create();
|
|
if ($this->Regexp->save($this->request->data)) {
|
|
$this->Flash->success(__('The Regexp has been saved.'));
|
|
$this->redirect(array('action' => 'index'));
|
|
} else {
|
|
if (!($this->Session->check('Message.flash'))) {
|
|
$this->Flash->error(__('The Regexp could not be saved. Please, try again.'));
|
|
}
|
|
}
|
|
} else {
|
|
$success = false;
|
|
foreach ($types as $key => $type) {
|
|
if ($this->request->data['Regexp'][$key] == 1) {
|
|
$this->Regexp->create();
|
|
$this->request->data['Regexp']['type'] = $type;
|
|
$this->Regexp->save($this->request->data);
|
|
$success = true;
|
|
}
|
|
}
|
|
if ($success) {
|
|
$this->Flash->success(__('The Regular expressions have been saved.'));
|
|
$this->redirect(array('action' => 'index'));
|
|
} else {
|
|
$this->Flash->error(__('Could not create the Regex entry as no types were selected. Either check "All" or check the types that you wish the Regex to affect.'));
|
|
}
|
|
}
|
|
}
|
|
$this->set('types', $types);
|
|
}
|
|
|
|
public function admin_index()
|
|
{
|
|
if (!$this->userRole['perm_regexp_access']) {
|
|
$this->redirect(array('controller' => 'regexp', 'action' => 'index', 'admin' => false));
|
|
}
|
|
$this->AdminCrud->adminIndex();
|
|
}
|
|
|
|
public function admin_edit($id = null)
|
|
{
|
|
// unlike other edits, the new regexp edit will actually create copies of an entry and delete the old ones. The reason for this is that each regular expression can now
|
|
// have several entries for different types. For example, /127.0.0.1/ -> '' can be an entry for ip-src, ip-dst, but not url, meaning that the string 127.0.0.1 would be blocked
|
|
// for ip-src and ip-dst attribute entry, but not for url.
|
|
$this->loadModel('Attribute');
|
|
$types = array_keys($this->Attribute->typeDefinitions);
|
|
// send the user away if he/she's no admin
|
|
if (!$this->userRole['perm_regexp_access']) {
|
|
$this->redirect(array('controller' => 'regexp', 'action' => 'index', 'admin' => false));
|
|
}
|
|
$this->Regexp->id = $id;
|
|
if (!$this->Regexp->exists()) {
|
|
throw new NotFoundException('Invalid Regexp');
|
|
}
|
|
if ($this->request->is('post') || $this->request->is('put')) {
|
|
unset($this->request->data['Regexp']['id']);
|
|
// If 'all' is set, it overrides all other type settings. Create an attribute with the "all" setting and save it. Also, delete the original(s)
|
|
if ($this->request->data['Regexp']['all'] == 1) {
|
|
$this->Regexp->create();
|
|
$this->request->data['Regexp']['type'] = 'ALL';
|
|
if ($this->Regexp->save($this->request->data)) {
|
|
$this->Regexp->find_similar($id, true);
|
|
$this->Flash->success('The Regexp has been saved');
|
|
$this->redirect(array('action' => 'index'));
|
|
} else {
|
|
if (!($this->Session->check('Message.flash'))) {
|
|
$this->Flash->error('The Regexp could not be saved. Please, try again.');
|
|
}
|
|
}
|
|
} else {
|
|
// Keep track of which types could not be entered
|
|
$failcount = 0;
|
|
$oldArray = $this->Regexp->find_similar($id);
|
|
$success = false;
|
|
foreach ($types as $key => $type) {
|
|
// If the checkbox for this type was ticked, create an entry for it
|
|
if ($this->request->data['Regexp'][$key] == 1) {
|
|
$this->Regexp->create();
|
|
$this->request->data['Regexp']['type'] = $type;
|
|
$success = true;
|
|
// Add to the failcount if the save fails. Ideally this should be 0
|
|
if (!$this->Regexp->save($this->request->data)) {
|
|
$failcount++;
|
|
}
|
|
}
|
|
}
|
|
if ($success) {
|
|
if ($failcount == 0) {
|
|
// we have managed to successfully save all of the new attributes, time to run through the array containing all of the old entries and delete them.
|
|
foreach ($oldArray as $old) {
|
|
$this->Regexp->delete($old[0]);
|
|
}
|
|
$this->Flash->success(__('The Regular expressions have been saved.'));
|
|
$this->redirect(array('action' => 'index'));
|
|
} else {
|
|
// Since some insertions failed, don't delete the old entries. It's an edit that failed after all
|
|
$this->Flash->error('There were issues saving all of the regexp entries, therefore the old entries were not deleted.');
|
|
}
|
|
} else {
|
|
$this->Flash->error(__('Could not create the Regex entry as no types were selected. Either check "All" or check the types that you wish the Regex to affect.'));
|
|
foreach ($this->request->data['Regexp'] as $k => $t) {
|
|
if (is_numeric($k)) {
|
|
$values[$k] = ($t == '1') ? true : false;
|
|
}
|
|
}
|
|
$this->set('all', $this->request->data['Regexp']['all'] == '1' ? true:false);
|
|
$this->set('value', $values);
|
|
}
|
|
}
|
|
} else {
|
|
// Show the user the regular expression entry that he/she is trying to edit, but also find all of the similar entries and mark the checkboxes appropriately
|
|
// Similar meaning entries with the same 'regexp' and 'replacement' fields but different types
|
|
$this->request->data['Regexp']['id'] = $id;
|
|
$this->request->data = $this->Regexp->read(null, $id);
|
|
$similarArray = $this->Regexp->find_similar($id);
|
|
$values = array();
|
|
// all is set separately from the other check-boxes
|
|
if ($this->request->data['Regexp']['type'] === 'ALL') {
|
|
$this->set('all', true);
|
|
} else {
|
|
$this->set('all', false);
|
|
}
|
|
// set the checkboxes for each type
|
|
foreach ($types as $key => $type) {
|
|
$values[$key] = false;
|
|
foreach ($similarArray as $similar) {
|
|
if ($type === $similar[1]) {
|
|
$values[$key] = true;
|
|
}
|
|
}
|
|
}
|
|
$this->set('value', $values);
|
|
}
|
|
$this->set('types', $types);
|
|
}
|
|
|
|
public function admin_delete($id = null)
|
|
{
|
|
if (!$this->userRole['perm_regexp_access']) {
|
|
$this->redirect(array('controller' => 'regexp', 'action' => 'index', 'admin' => false));
|
|
}
|
|
$this->AdminCrud->adminDelete($id);
|
|
}
|
|
|
|
public function index()
|
|
{
|
|
$this->recursive = 0;
|
|
$this->set('list', $this->paginate());
|
|
}
|
|
|
|
public function admin_clean()
|
|
{
|
|
if (!$this->_isSiteAdmin() || !$this->request->is('post')) {
|
|
throw new MethodNotAllowedException('This action is only accessible via a POST request.');
|
|
}
|
|
$allRegexp = $this->Regexp->find('all');
|
|
$deletable = array();
|
|
$modifications = 0;
|
|
$this->loadModel('Attribute');
|
|
$count = $this->Attribute->find('count', array());
|
|
$chunks = ceil($count / 1000);
|
|
for ($i = 1; $i <= $chunks; $i++) {
|
|
$all = $this->Attribute->find('all', array(
|
|
'recursive' => -1,
|
|
'deleted' => 0,
|
|
'limit' => 1000,
|
|
'page' => $i
|
|
));
|
|
foreach ($all as $item) {
|
|
$result = $this->Regexp->replaceSpecific($item['Attribute']['value'], $allRegexp, $item['Attribute']['type']);
|
|
// 0 = delete it, it is a blocked regexp; 1 = ran regexp check, made changes, resave this attribute with the new value; 2 = ran regexp check, no changes made, go on
|
|
if ($result == 0) {
|
|
$deletable[] = $item['Attribute']['id'];
|
|
} else {
|
|
// Until now this wasn't checked and all attributes were resaved, no matter if they were changed...
|
|
if ($result == 1) {
|
|
$this->Attribute->save($item);
|
|
$modifications++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (count($deletable)) {
|
|
foreach ($deletable as $item) {
|
|
$this->Attribute->delete($item);
|
|
}
|
|
}
|
|
$this->Flash->info(__('All done! Number of changed attributes: ' . $modifications . ' Number of deletions: ' . count($deletable)));
|
|
$this->redirect(array('action' => 'index'));
|
|
}
|
|
|
|
|
|
public function cleanRegexModifiers()
|
|
{
|
|
if (!$this->_isSiteAdmin() || !$this->request->is('post')) {
|
|
throw new MethodNotAllowedException();
|
|
}
|
|
$entries = $this->Regexp->find('all', array());
|
|
$changes = 0;
|
|
foreach ($entries as $entry) {
|
|
$length = strlen($entry['Regexp']['regexp']);
|
|
$this->Regexp->sanitizeModifiers($entry['Regexp']['regexp']);
|
|
if (strlen($entry['Regexp']['regexp']) < $length) {
|
|
$this->Regexp->save($entry);
|
|
$changes++;
|
|
}
|
|
}
|
|
$this->Flash->info(__('All done! Found and cleaned ' . $changes . ' potentially malcious regexes.'));
|
|
$this->redirect('/pages/display/administration');
|
|
}
|
|
}
|