Merge branch 'llm_tests' into develop

pull/9370/head
iglocska 2023-10-31 15:04:27 +01:00
commit 075a68f187
No known key found for this signature in database
GPG Key ID: BEA224F1FEF113AC
8 changed files with 161 additions and 10 deletions

View File

@ -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);
}
}

View File

@ -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'),

View File

@ -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,

View File

@ -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;
}
}

View File

@ -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' => [

View File

@ -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>

View File

@ -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();

View File

@ -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)
}
/**
_ _ _ _ _
| | | | | (_) |