mirror of https://github.com/MISP/MISP
Merge branch 'llm_tests' into develop
commit
075a68f187
|
@ -374,6 +374,28 @@ class EventReportsController extends AppController
|
|||
$this->render('ajax/reportFromEvent');
|
||||
}
|
||||
|
||||
public function sendToLLM($reportId)
|
||||
{
|
||||
if (!$this->request->is('ajax')) {
|
||||
throw new MethodNotAllowedException(__('This function can only be reached via AJAX.'));
|
||||
} else {
|
||||
$report = $this->EventReport->fetchIfAuthorized($this->Auth->user(), $reportId, 'edit', true, false);
|
||||
if ($this->request->is('post')) {
|
||||
$errors = [];
|
||||
$result = $this->EventReport->sendToLLM($report, $this->Auth->user(), $errors);
|
||||
if ($result !== false) {
|
||||
$successMessage = __('Successfully sent to Event Report %s to LLM', $reportId);
|
||||
return $this->__getSuccessResponseBasedOnContext($successMessage, $result, 'sendToLLM', $reportId);
|
||||
} else {
|
||||
$errorMessage = __('Could not send Event Report %s to LLM.%sReasons: %s', $reportId, PHP_EOL, json_encode($errors));
|
||||
return $this->__getFailResponseBasedOnContext($errorMessage, array(), 'sendToLLM', $reportId);
|
||||
}
|
||||
}
|
||||
$this->layout = false;
|
||||
$this->render('ajax/sendToLLM');
|
||||
}
|
||||
}
|
||||
|
||||
private function __generateIndexConditions($filters = [])
|
||||
{
|
||||
$aclConditions = $this->EventReport->buildACLConditions($this->Auth->user());
|
||||
|
@ -529,4 +551,11 @@ class EventReportsController extends AppController
|
|||
}
|
||||
return $savedReport;
|
||||
}
|
||||
|
||||
public function test()
|
||||
{
|
||||
$report = $this->EventReport->find('first', ['conditions' => ['EventReport.id' => 25]]);
|
||||
$errors = [];
|
||||
$this->EventReport->sendToLLM($report, $this->Auth->user(), $errors);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6014,7 +6014,6 @@ class EventsController extends AppController
|
|||
$this->set('file_uploaded', "1");
|
||||
$this->set('file_name', $this->request['data']['Event']['analysis_file']['name']);
|
||||
$this->set('file_content', file_get_contents($this->request['data']['Event']['analysis_file']['tmp_name']));
|
||||
|
||||
//$result = $this->Event->upload_mactime($this->Auth->user(), );
|
||||
} elseif ($this->request->is('post') && $this->request['data']['SelectedData']['mactime_data']) {
|
||||
// Find the event that is to be updated
|
||||
|
@ -6042,7 +6041,7 @@ class EventsController extends AppController
|
|||
'meta-category' => 'file',
|
||||
'description' => 'Mactime template, used in forensic investigations to describe the timeline of a file activity',
|
||||
'template_version' => 1,
|
||||
'template_uuid' => '9297982e-be62-4772-a665-c91f5a8d639'
|
||||
'template_uuid' => '58149b06-eabe-4937-9dac-01d63f504e14'
|
||||
);
|
||||
|
||||
$object['Attribute'] = array(
|
||||
|
@ -6105,7 +6104,7 @@ class EventsController extends AppController
|
|||
|
||||
);
|
||||
$this->loadModel('MispObject');
|
||||
$ObjectResult = $this->MispObject->saveObject($object, $eventId, "", "");
|
||||
$ObjectResult = $this->MispObject->saveObject($object, $eventId, false, $this->Auth->user());
|
||||
$temp = $this->MispObject->ObjectReference->Object->find('first', array(
|
||||
'recursive' => -1,
|
||||
'fields' => array('Object.uuid','Object.id'),
|
||||
|
|
|
@ -3547,7 +3547,7 @@ class Attribute extends AppModel
|
|||
if (isset($attribute['id'])) {
|
||||
$conditions['Attribute.id !='] = $attribute['id'];
|
||||
}
|
||||
|
||||
|
||||
return $this->find('first', [
|
||||
'recursive' => -1,
|
||||
'conditions' => $conditions,
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<?php
|
||||
App::uses('AppModel', 'Model');
|
||||
App::uses('SyncTool', 'Tools');
|
||||
|
||||
/**
|
||||
* @property Event $Event
|
||||
|
@ -960,4 +961,68 @@ class EventReport extends AppModel
|
|||
$report = $reportGenerator->generate();
|
||||
return $report;
|
||||
}
|
||||
|
||||
public function sendToLLM($report, $user, &$errors)
|
||||
{
|
||||
$syncTool = new SyncTool();
|
||||
$config = [];
|
||||
$HttpSocket = $syncTool->setupHttpSocket($config, $this->timeout);
|
||||
$LLMFeatureEnabled = Configure::read('Plugin.CTIInfoExtractor_enable', false);
|
||||
$url = Configure::read('Plugin.CTIInfoExtractor_url');
|
||||
$apiKey = Configure::read('Plugin.CTIInfoExtractor_authentication');
|
||||
if (!$LLMFeatureEnabled || empty($url)) {
|
||||
$errors[] = __('LLM Feature disabled or no URL provided');
|
||||
return false;
|
||||
}
|
||||
$reportContent = $report['EventReport']['content'];
|
||||
$data = json_encode(['text' => $reportContent]);
|
||||
$version = implode('.', $this->Event->checkMISPVersion());
|
||||
$request = [
|
||||
'header' => array_merge([
|
||||
'Accept' => 'application/json',
|
||||
'Content-Type' => 'application/json',
|
||||
'User-Agent' => 'MISP ' . $version . (empty($commit) ? '' : ' - #' . $commit),
|
||||
'x-api-key' => $apiKey,
|
||||
])
|
||||
];
|
||||
|
||||
$response = $HttpSocket->post($url, $data, $request);
|
||||
$data = json_decode($response->body, true);
|
||||
/*
|
||||
debug($data);
|
||||
|
||||
$data = array(
|
||||
'AI_ThreatActor' => 'Sofacy',
|
||||
'AI_AttributedCountry' => 'unknown',
|
||||
'AI_Type' => 'Developments in IT Security',
|
||||
'AI_Motivation' => 'Espionage',
|
||||
'AI_ExecutiveSummary' => 'The Sofacy group, also known as APT28 or Fancy Bear, continues to target government and strategic organizations primarily in North America and Europe. They have recently been using a tool called Zebrocy, delivered via phishing attacks, to cast a wider net within target organizations. They have also been observed leveraging the Dynamic Data Exchange (DDE) exploit technique to deliver different payloads, including the Koadic toolkit. This report provides details on the campaigns and tactics used by the Sofacy group.',
|
||||
'AI_CouldWeBeAffected' => true
|
||||
);
|
||||
*/
|
||||
|
||||
if (!empty($data['AI_ExecutiveSummary'])) {
|
||||
$report['EventReport']['content'] = '# Executive Summary' . PHP_EOL . $data['AI_ExecutiveSummary'] . PHP_EOL . PHP_EOL . '# Report' . PHP_EOL . $report['EventReport']['content'];
|
||||
}
|
||||
$this->save($report);
|
||||
$event = $this->Event->find('first', [
|
||||
'conditions' => ['Event.id' => $report['EventReport']['event_id']],
|
||||
'recursive' => -1
|
||||
]);
|
||||
if (!empty($data['AI_ThreatActor'])) {
|
||||
$tag_id = $this->Event->EventTag->Tag->captureTag(['name' => 'misp-galaxy:threat-actor="' . $data['AI_ThreatActor'] . '"'], $user);
|
||||
$this->Event->EventTag->attachTagToEvent($event['Event']['id'], ['id' => $tag_id]);
|
||||
}
|
||||
|
||||
if (!empty($data['AI_AttributedCountry'])) {
|
||||
$tag_id = $this->Event->EventTag->Tag->captureTag(['name' => 'misp-galaxy:threat-actor-country="' . $data['AI_AttributedCountry'] . '"'], $user);
|
||||
$this->Event->EventTag->attachTagToEvent($event['Event']['id'], ['id' => $tag_id]);
|
||||
}
|
||||
|
||||
if (!empty($data['AI_Motivation'])) {
|
||||
$tag_id = $this->Event->EventTag->Tag->captureTag(['name' => 'misp-galaxy:threat-actor-motivation="' . $data['AI_Motivation'] . '"'], $user);
|
||||
$this->Event->EventTag->attachTagToEvent($event['Event']['id'], ['id' => $tag_id]);
|
||||
}
|
||||
return $report;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7618,6 +7618,29 @@ class Server extends AppModel
|
|||
'test' => 'testForEmpty',
|
||||
'type' => 'string',
|
||||
'null' => true
|
||||
],
|
||||
'CTIInfoExtractor_enable' => [
|
||||
'level' => 1,
|
||||
'description' => __('Enable the experimental CTI info extractor plugin to use a connected LLM server to extract additional information from markdown reports.'),
|
||||
'value' => false,
|
||||
'test' => 'testBool',
|
||||
'type' => 'boolean'
|
||||
],
|
||||
'CTIInfoExtractor_url' => [
|
||||
'level' => 1,
|
||||
'description' => __('The url of the LLM REST service.'),
|
||||
'value' => '',
|
||||
'test' => 'testForEmpty',
|
||||
'type' => 'string',
|
||||
'null' => 'true'
|
||||
],
|
||||
'CTIInfoExtractor_authentication' => [
|
||||
'level' => 1,
|
||||
'description' => __('The authentication key for the LLM REST service.'),
|
||||
'value' => '',
|
||||
'test' => 'testForEmpty',
|
||||
'type' => 'string',
|
||||
'null' => 'true'
|
||||
]
|
||||
),
|
||||
'SimpleBackgroundJobs' => [
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
echo $this->element('genericElements/Form/genericForm', array(
|
||||
'form' => $this->Form,
|
||||
'data' => array(
|
||||
'title' => __('Send report to LLM'),
|
||||
'model' => 'EventReport',
|
||||
'submit' => array(
|
||||
'action' => $this->request->params['action'],
|
||||
'ajaxSubmit' => 'confirmSubmissionToLLM(this)'
|
||||
),
|
||||
)
|
||||
));
|
||||
?>
|
||||
|
||||
<script>
|
||||
function confirmSubmissionToLLM(clicked) {
|
||||
$clicked = $(clicked)
|
||||
$loading = $('<div style="display:flex; align-items: center; flex-direction: column;"></div>').append(
|
||||
$('<h3>Waiting for the robot to do its magic...</h3>'),
|
||||
$('</br>'),
|
||||
$('<i class="fas fa-robot fa-5x fa-spin"></i>'),
|
||||
$('</br>'),
|
||||
)
|
||||
$clicked.parent().parent().find('.modal-body').append($loading)
|
||||
submitGenericFormInPlace(function(data) {
|
||||
window.location.reload();
|
||||
});
|
||||
}
|
||||
</script>
|
|
@ -125,12 +125,6 @@ var afterUpload = "<?php echo $file_uploaded; ?>";
|
|||
var selText = clearText =fileContent = '';
|
||||
var linesArray = [];
|
||||
var rowSelected;
|
||||
$("#accordion1").accordion({
|
||||
heightStyle: "content"
|
||||
})
|
||||
$("#accordion2").accordion({
|
||||
heightStyle: "content"
|
||||
})
|
||||
if(afterUpload == 1)
|
||||
{
|
||||
$('#afterUpload').show();
|
||||
|
|
|
@ -863,6 +863,13 @@ function injectCustomRulesMenu() {
|
|||
{ name: 'Automatic extraction', icon: 'fas fa-magic', clickHandler: automaticEntitiesExtraction},
|
||||
]
|
||||
})
|
||||
createSubMenu({
|
||||
name: 'LLM ',
|
||||
icon: 'fas fa-robot',
|
||||
items: [
|
||||
{ name: 'Send report to LLM', icon: 'fas fa-robot', clickHandler: sendToLLM},
|
||||
]
|
||||
})
|
||||
reloadRenderingRuleEnabledUI()
|
||||
}
|
||||
|
||||
|
@ -1260,6 +1267,11 @@ function submitExtractionSuggestion() {
|
|||
})
|
||||
}
|
||||
|
||||
function sendToLLM() {
|
||||
var url = baseurl + '/eventReports/sendToLLM/' + reportid
|
||||
openGenericModal(url)
|
||||
}
|
||||
|
||||
/**
|
||||
_ _ _ _ _
|
||||
| | | | | (_) |
|
||||
|
|
Loading…
Reference in New Issue