NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name BTAS // @namespace https://github.com/Mr-Tree-S/BTAS // @homepageURL https://github.com/Mr-Tree-S/BTAS // @version 3.8.7 // @description Blue Team Auxiliary Script // @author Barry, Jack, Xingyu, Mike // @license Apache-2.0 // @updateURL https://raw.githubusercontent.com/Mr-Tree-S/BTAS/main/BTAS.js // @downloadURL https://raw.githubusercontent.com/Mr-Tree-S/BTAS/main/BTAS.js // @match https://login.microsoftonline.com/* // @match https://security.microsoft.com/* // @include https://caas*.com/* // @include https://mss*mss.com/* // @require https://code.jquery.com/jquery-3.6.4.min.js // @require https://cdn.jsdelivr.net/npm/clipboard@2.0.11/dist/clipboard.min.js // @require https://unpkg.com/@popperjs/core@2/dist/umd/popper.min.js // @require https://unpkg.com/tippy.js@6/dist/tippy-bundle.umd.js // @require https://cdnjs.cloudflare.com/ajax/libs/dompurify/3.0.6/purify.min.js // @grant GM_registerMenuCommand // @grant GM_unregisterMenuCommand // @grant GM_xmlhttpRequest // @grant GM_openInTab // @grant GM_getValue // @grant GM_setValue // @connect raw.githubusercontent.com // @connect myqcloud.com // @connect 172.18.4.200 // @run-at document-idle // @grant GM_addStyle // ==/UserScript== var $ = window.jQuery; /** * This function creates and displays a flag using AJS.flag function * @param {string} type - The type of flag, can be one of the following: "success", "info", "warning", "error" * @param {string} title - The title of the flag * @param {string} body - The body of the flag * @param {string} close - The close of flag, can be one of the following: "auto", "manual", "never" */ function security_microsoft() { var queryString = window.location.search; var urlParams = new URLSearchParams(queryString); var current_domain = urlParams.get('current'); var customers = {}; const cachedWebsiteContent = GM_getValue('cachedWebsiteContent', null); console.log(cachedWebsiteContent); cachedWebsiteContent.forEach((item, index) => { if (item && item['category'] == 'mde' && item['url']) { customers[item['name']] = item['url']; } }); var customer = customers[current_domain]; if (customer) { console.log('account11', customer); } else { customer = current_domain; } if (current_domain == 'none') { let urls = localStorage.getItem('urls').toString().split(','); for (var i = 0; i < urls.length; i++) { if (i == 0) { window.location.href = urls[i]; } else { GM_openInTab(urls[i], { active: false, // 设置为 false,以在后台打开,不激活新标签页 insert: true // 设置为 true,将新标签页插入到当前标签页之后 }); } } localStorage.removeItem('urls'); } setTimeout(() => { document.getElementById('O365_MainLink_Me').click(); console.log('account1'); }, 9000); setTimeout(() => { var account = document.getElementById('mectrl_currentAccount_secondary').textContent; console.log(account, customer); if ( !account.includes(customer) && !customer.includes(account.split('@')[1].split('.')[0]) && current_domain != 'none' ) { let urls = []; urlParams.forEach(function (value, key) { if (key.includes('url')) { urls.push(value); } }); localStorage.setItem('urls', urls); document.getElementById('mectrl_body_signOut').click(); } else { urlParams.forEach(function (value, key) { if (key.includes('url')) { GM_openInTab(value, { active: false, // 设置为 false,以在后台打开,不激活新标签页 insert: true // 设置为 true,将新标签页插入到当前标签页之后 }); } }); window.close(); } }, 9900); } function switch_user_microsoft() { console.log('login.microsoft', $('#idDiv_SAOTCC_Title').text().trim()); if ($('#login_workload_logo_text').text().trim() == '您已注销帐户') { window.location.href = 'https://security.microsoft.com/homepage?¤t=none'; } if (document.title == '登录到您的帐户' && $('#idDiv_SAOTCC_Title').text().trim() != '输入验证码') { setTimeout(() => { var inputElement = document.querySelectorAll('.form-control')[0]; inputElement.addEventListener('input', function (event) { var inputValue = inputElement.value; if (inputValue.includes('@')) { $('#idSIButton9').click(); setTimeout(() => { $('#idSIButton9').click(); }, 1500); } }); }, 1600); } else { setTimeout(() => { var inputElement = document.querySelectorAll('.form-control')[0]; inputElement.addEventListener('keyup', function (event) { var inputValue = inputElement.value; console.log(inputValue); // 打印当输入框的内容在元素失去焦点时的值 if (inputValue.length == 6) { $('#idSubmit_SAOTCC_Continue').click(); } }); }, 800); } } function addCss() { const ss = $(` <style> .red_highlight{ color:red; font-weight: bold; } .black_highlight{ color:black; font-weight: bold; } .aui-dropdown2{ max-width: 550px !important; } .aui-dropdown2 .aui-dropdown2-checkbox, .aui-dropdown2 .aui-dropdown2-radio, .aui-dropdown2 .aui-icon-container { padding-top: 10px; padding-left: 35px; } #reply{ column-count: 2; } .aui-flag{ border: 4px solid rgb(222,184,135) ; } .fix-button{ background-color: rgb(222,184,135); color:white; z-index: 100; margin-right: 12px; } </style> `); $('head').append(ss); function hideAllFlag() { $('.aui-flag').toggle(); } const button = $('<div>') .attr('id', 'hide-reminder') .addClass('aui-button toolbar-trigger fix-button aui-button-primary') .append($('<span>').addClass('trigger-label').text('NOTICE')) .click(hideAllFlag); const checkExist = setInterval(function () { const targetDiv = document.getElementById('aui-flag-container'); const toolbar = $('.aui-header-secondary'); if (targetDiv) { toolbar.prepend(button); clearInterval(checkExist); // 停止检查 } }, 100); // 每100毫秒检查一次 } function showFlag(type, title, body, close) { AJS.flag({ type: type, title: DOMPurify.sanitize(title), body: DOMPurify.sanitize(body), close: close }); // addButton('hide-reminder', 'Hide Reminder', hideAllFlag); // 为 flag 的内容区域添加滚动条样式 const flagBody = $('#aui-flag-container > div > div'); flagBody.css({ 'overflow': 'auto', 'max-height': '150px' // 添加最大高度,超出部分将出现滚动条 }); // 为 flag 的container区域添加滚动条样式 const flagContainer = $('#aui-flag-container'); flagContainer.css({ 'overflow': 'auto', 'overflow-x': 'hidden', //隐藏水平滚动条 'max-height': '90%' // 添加最大高度,超出部分将出现滚动条 }); } /** * This function shows alert message in dialog and create a copy button * @param {string} body - Alert Message String */ function showDialog(body) { // avoid editor treat double backslash as breakline and avoid xss attack body = DOMPurify.sanitize(body.replace(/\\\\/g, '\\')); // Create custom dialog style const customDialogContent = AJS.$(`<section id="custom-dialog" class="aui-dialog2 aui-dialog2-large aui-layer" role="dialog" tabindex="-1" data-aui-modal="true" data-aui-remove-on-hide="true" aria-labelledby="dialog-show-button--heading" aria-describedby="dialog-show-button--description" hidden > <header class="aui-dialog2-header"> <h2 class="aui-dialog2-header-main" id="dialog-show-button--heading">Description</h2> </header> <div class="aui-dialog2-content" id="dialog-show-button--description"> <p style="word-wrap: break-word; white-space: pre-line">${body}</p> </div> <footer class="aui-dialog2-footer"> <div class="aui-dialog2-footer-actions"> <button id="dialog-copy-button" class="aui-button aui-button-primary">Copy</button> <button id="dialog-close-button" class="aui-button aui-button-link">Close</button> </div> </footer> </section>`); // Show the dialog AJS.dialog2(customDialogContent).show(); // Close the dialog AJS.$('#dialog-close-button').on('click', function (e) { e.preventDefault(); AJS.dialog2(customDialogContent).hide(); //tippy.destroy(); }); // Init tippy instance tippy('#dialog-copy-button', { content: 'Copy Success', placement: 'bottom', trigger: 'click' }); // Copy description text AJS.$('#dialog-copy-button').on('click', function () { const textToCopy = customDialogContent.find('#dialog-show-button--description').text().trim(); // Create Clipboard instance const clipboard = new ClipboardJS('#dialog-copy-button', { text: function () { return textToCopy; } }); // Copy success clipboard.on('success', function (e) { clipboard.destroy(); e.clearSelection(); }); }); } /** * This function registers a Tampermonkey search menu command * @param {Array} searchEngines - Search engines array containing the Jira, VT, AbuseIPDB */ function registerSearchMenu() { console.log('#### Code registerSearchMenu run ####'); const LogSourceDomain = $('#customfield_10223-val').text().trim() || '*'; const Host = function () { let search = { 'Source IP(s) and Hostname(s)': $('#customfield_10206-val').text().trim(), 'Destination IP(s) and Hostname(s)': $('#customfield_10208-val').text().trim() }; if (search['Source IP(s) and Hostname(s)']) { return `AND 'Source IP(s) and Hostname(s)' ~ '${search['Source IP(s) and Hostname(s)']}'`; } else if (search['Destination IP(s) and Hostname(s)']) { return `AND 'Destination IP(s) and Hostname(s)' ~ '${search['Destination IP(s) and Hostname(s)']}'`; } else { return ''; } }; let cachedEntry = GM_getValue('cachedEntry', null); let url = `${ cachedEntry['hk'] }/issues/?jql=text ~ "%s" AND "Log Source Domain" ~ "%D" ${Host()} ORDER BY created DESC`; if (window.location.href.includes(cachedEntry['macao'].split('//')[1])) { url = `${cachedEntry['macao']}/issues/?jql=text ~ "%s" ORDER BY created DESC`; } console.log('===url', url); const searchEngines = [ { name: 'Jira', url: url }, { name: 'VT', url: 'https://www.virustotal.com/gui/search/%s' }, { name: 'AbuseIPDB', url: 'https://www.abuseipdb.com/check/%s' }, { name: 'Base64 Decode', url: `https://icyberchef.com/#recipe=From_Base64('A-Za-z0-9%2B/%3D',true,false)&input=%b` } ]; searchEngines.forEach((engine) => { GM_registerMenuCommand(engine.name, () => { const selectedText = window.getSelection().toString(); const searchURL = engine.url .replace('%s', selectedText) .replace('%D', LogSourceDomain) .replace('%b', btoa(selectedText)); if (selectedText.length === 0) { showFlag('error', 'No text selected', 'Please select some text and try again', 'auto'); } else { window.open(searchURL, '_blank'); } }); }); } /** * This function registers custom add/remove quick reply menus in Tampermonkey * Add custom reply: input custom reply and store in local * Remove quick reply: remove all local storage custom replies */ function registerCustomQuickReplyMenu() { GM_registerMenuCommand('Add Custom Quick Reply', () => { const userInput_name = prompt('Enter saved quick reply name (the name should be unique)').toString(); const userInput_reply = prompt('Enter a custom quick reply (<br> is used for line break)').toString(); if (userInput_name !== null && userInput_reply !== null) { const key = `customReply_${userInput_name}`; // local save localStorage.setItem(key, userInput_reply); } }); GM_registerMenuCommand('Remove Custom Quick Reply', () => { for (let i = 0; i < localStorage.length; i++) { const key = localStorage.key(i); if (key.startsWith('customReply_')) { localStorage.removeItem(key); } } showFlag('success', 'Cleared All Custom Replies', '', 'auto'); }); GM_registerMenuCommand('MDE Assist', () => { let MDE_Assist_ = localStorage.getItem('MDE_Assist'); const MDE_Assist = prompt( 'Whether MDE Assist is enabled(Example:enable 1, disable 0)', MDE_Assist_ ).toString(); localStorage.setItem('MDE_Assist', MDE_Assist); }); } /** * This function create a Quick Reply button in editor */ function QuickReply() { const replyButton = `<button class="aui-button aui-dropdown2-trigger" aria-controls="is-radio-checked">Quick Reply</button> <aui-dropdown-menu id="is-radio-checked"> <aui-section id="reply"> <aui-item-radio interactive>Close ticket</aui-item-radio> <aui-item-radio interactive>Monitor ticket</aui-item-radio> <aui-item-radio interactive>Waiting ticket</aui-item-radio> <aui-item-radio interactive>Waiting Full Scan</aui-item-radio> <aui-item-radio interactive>Ask for Whitelist</aui-item-radio> <aui-item-radio interactive>Whitelist Done</aui-item-radio> <aui-item-radio interactive>Agent recover</aui-item-radio> <aui-item-radio interactive>Leaked Credentials</aui-item-radio> <aui-item-radio interactive>Compromised Accounts</aui-item-radio> <aui-item-radio interactive>Log resume</aui-item-radio> <aui-item-radio interactive>关闭工单</aui-item-radio> <aui-item-radio interactive>Haeco high severity</aui-item-radio> <aui-item-radio interactive>Haeco medium severity</aui-item-radio> <aui-item-radio interactive>Haeco low severity</aui-item-radio> </aui-section> </aui-dropdown-menu>`; const commentBar = $($('.aui-toolbar2-primary')[1]); commentBar.append(replyButton); const commentBarSection = document.querySelector('aui-section#reply'); const replyComment = { 'Close ticket': 'Dear Customer,<br>Thanks for your reply, we will close this ticket.<br>Best Regards.', 'Monitor ticket': 'Dear Customer,<br>Thanks for your reply, we will keep monitor.<br>Best Regards.', 'Waiting ticket': 'Dear Customer,<br>Thanks, we look forward to hearing from you.', 'Waiting Full Scan': 'Dear Customer,<br>Full scan have been triggered , if suspicious files detected new MDE alert/ticket will be created.', 'Ask for Whitelist': 'Dear Customer,<br>Can we add the ticket to white list?<br>Best Regards.', 'Whitelist Done': 'Dear Customer,<br>We have informed the relevant parties to add this ticket to the white list and will close this ticket<br>Best Regards.', 'Haeco high severity': '<h2><strong><span style="color: red;" data-mce-style="color: red;"><samp>[The ticket is escalated to High Severity]</samp></span></strong></h2><br>', 'Haeco medium severity': '<h2><span style="color: rgb(255, 171, 0);" data-mce-style="color: #ffab00;"><strong><samp>[The ticket is escalated to Medium Severity]</samp></strong></span></h2><br>', 'Haeco low severity': '<h2><span style="color: rgb(76, 154, 255);" data-mce-style="color: #4c9aff;"><strong><samp>[The ticket is de-escalated to Low Severity]</samp></strong></span></h2><br>', 'Leaked Credentials': '<p>Dear Client,</p><p>Our Cyber Threat Intelligence investigated the incident and found <Number> leaked credentials related to your organization exposed in dark web. The credentials are listed below:</p><table width="962" class="mce-item-table"><tbody><tr><td width="137"><div><p><strong>EMAIL/USERNAME</strong></p></div></td><td width="137"><div><p><strong>PASSWORD TYPE</strong></p></div></td><td width="137"><div><p><strong>PASSWORD</strong></p></div></td><td width="137"><div><p><strong>SOURCE</strong></p></div></td><td width="137"><div><p><strong>PRICE</strong></p></div></td><td width="137"><div><p><strong>POSTED DATE</strong></p></div></td><td width="137"><div><p><strong>SERVICE</strong></p></div></td></tr><tr><td width="137"><br data-mce-bogus="1"></td><td width="137"><br data-mce-bogus="1"></td><td width="137"><br data-mce-bogus="1"></td><td width="137"><br data-mce-bogus="1"></td><td width="137"><br data-mce-bogus="1"></td><td width="137"><br data-mce-bogus="1"></td><td width="137"><br data-mce-bogus="1"></td></tr></tbody></table><p>[Source Detail from Kela]</p><p><SOURCE Details/Description></p><p>[Service if disclose need check]</p><p>As per our open-source investigation through passive means, we observe that:</p><p>< SERVICE> appear to be <SERVICE USAGE></p><p>[Recommendation]</p><p>We recommend confirming that the service coverage is to customers only, or whether it also includes staff and/or third-party, and evaluate if accounts with administrative privileges require a password change. We also recommend to heighten monitoring of customer login to indicate anomalies in location or timing, and review password policies and evaluate if there is a need to strengthen (e.g., mandate password rotation regularly). A further recommendation is to reach out to these account holders if the accounts are still active, and request that they change their passwords.</p><p>Please do not hesitate to reach out to us if you have any queries. Thank you.</p><p>Best Regards,<br>Cyber Threat Intelligence Team</p>', 'Compromised Accounts': '<p>Dear Client,</p><p>Our Cyber Threat Intelligence investigated the incident and found <Number> compromised accounts related to your organisation exposed in dark web. The credentials are listed below:</p><table width="962" class="mce-item-table"><tbody><tr><td width="137"><div><p><strong>EMAIL/USERNAME</strong></p></div></td><td width="137"><div><p><strong>PASSWORD TYPE</strong></p></div></td><td width="137"><div><p><strong>PASSWORD</strong></p></div></td><td width="137"><div><p><strong>SOURCE</strong></p></div></td><td width="137"><div><p><strong>PRICE</strong></p></div></td><td width="137"><div><p><strong>POSTED DATE</strong></p></div></td><td width="137"><div><p><strong>SERVICE</strong></p></div></td></tr><tr><td width="137"><br data-mce-bogus="1"></td><td width="137"><br data-mce-bogus="1"></td><td width="137"><br data-mce-bogus="1"></td><td width="137"><br data-mce-bogus="1"></td><td width="137"><br data-mce-bogus="1"></td><td width="137"><br data-mce-bogus="1"></td><td width="137"><br data-mce-bogus="1"></td></tr></tbody></table><p>[Source Detail from Kela]</p><p><SOURCE Details/Description></p><p>[Service if disclose need check]</p><p>As per our open-source investigation through passive means, we observe that:</p><p>< SERVICE> appear to be <SERVICE USAGE> </p><p>[Recommendation]</p><p>We recommend confirming that the service coverage is to customers only, or whether it also includes staff and/or third-party, and evaluate if accounts with administrative privileges require a password change. We also recommend to heighten monitoring of customer login to indicate anomalies in location or timing, and review password policies and evaluate if there is a need to strengthen (e.g., mandate password rotation regularly). A further recommendation is to reach out to these account holders if the accounts are still active, and request that they change their passwords.</p><p>Please do not hesitate to reach out to us if you have any queries. Thank you.</p><p>Best Regards,<br>Cyber Threat Intelligence Team</p>', 'Log resume': 'Dear Customer,<br>Thanks for your reply, <br>Log resumed, we will close this ticket.<br>Best Regards.', 'Agent recover': 'Dear Customer,<br>Thanks for your reply,<br>The agent is now active and we will close this case<br>Best Regards.', '关闭工单': '尊敬的客户,<br>感谢您的回复,我们将关闭此工单。 <br>祝您生活愉快。<br>' }; // Check local storage at initialization time function getAllCustomReply() { for (let i = 0; i < localStorage.length; i++) { const key = localStorage.key(i); if (key.startsWith('customReply_')) { const storedReply = localStorage.getItem(key).toString(); const storeReplyName = key.split('_')[1].toString(); replyComment[storeReplyName] = storedReply; $('#reply').append(`<aui-item-radio interactive>${storeReplyName}</aui-item-radio>`); } } } getAllCustomReply(); try { if (commentBarSection !== null) { commentBarSection.addEventListener('change', function (e) { if (e.target.hasAttribute('checked')) { tinymce.activeEditor.setContent(''); let replyValue = replyComment[e.target.textContent]; tinymce.activeEditor.execCommand('mceInsertContent', false, replyValue); } }); } } catch (error) { console.error(error); } } /**jsonView */ function jsonToTree(data) { let flag = false; let html = '<ul class="code-java" style="list-style-type: none;margin-top: 0px;padding-left: 20px;">'; if (Array.isArray(data)) { let temp = '['; data.forEach((element) => { temp += jsonToTree(element); }); html += temp + '],'; } else if (data != null && typeof data === 'object' && Object.keys(data).length !== 0) { flag = true; for (let key in data) { if (data.hasOwnProperty(key)) { html += '<li class="code-quote">"' + key + '": '; if (Array.isArray(data[key])) { let temp = '['; data[key].forEach((element) => { temp += jsonToTree(element); }); html += temp + '],'; } else if (typeof data[key] === 'object') { try { if (Object.keys(data[key]).length == 0) { html += '{},'; } else { const str = jsonToTree(data[key]); html += str; } } catch (TypeError) { html += '"",'; } } else { html += '"' + data[key].toString() + '",'; } html += '</li>'; } } } else { html += '"' + data.toString() + '",'; } if (flag === true) { html = '{' + html + '},'; } html += '</ul>'; return html; } function ToWhitelist() { const summary = $('#summary-val').text().trim(); var LogSourceDomain = $('#customfield_10223-val').text().trim(); let DecoderName = $('#customfield_10807-val').text().trim().toLowerCase(); let Component = 'Wazuh'; if (DecoderName.includes('mde') || DecoderName.includes('m365')) { Component = 'MDE'; } if (DecoderName.includes('cortex')) { Component = 'Cortex'; } let whitelist = { summary: summary, LogSourceDomain: LogSourceDomain, Component: Component, MSS: window.location.href }; localStorage.setItem('whitelist', JSON.stringify(whitelist)); let cachedEntry = GM_getValue('cachedEntry', null); window.open(`${cachedEntry['hk']}/plugins/servlet/desk/portal/2/create/100`, '_blank'); } /** * This function registers two Tampermonkey exception menu command * Add Exception: adds the currently selected text to an exception list stored in local storage * Clear Exception: clears the exception list from local storage */ let exceptionKey = localStorage.getItem('exceptionKey')?.split(',') || []; let notifyKey = [...exceptionKey]; function registerExceptionMenu() { console.log('#### Code registerExceptionMenu run ####'); GM_registerMenuCommand('Add Exception', () => { const selection = window.getSelection().toString().trim(); if (!selection) { showFlag('error', 'No Issue Key selected', '', 'auto'); return; } exceptionKey.push(selection); localStorage.setItem('exceptionKey', exceptionKey.toString()); showFlag('success', '', `Added <strong>${selection}</strong> successfully`, 'auto'); }); GM_registerMenuCommand('Clear Exception', () => { localStorage.setItem('exceptionKey', ''); exceptionKey = notifyKey = []; showFlag('success', 'Cleared All Issue Key', '', 'auto'); }); GM_registerMenuCommand('JsonViewer', () => { var isJson = function (str) { try { JSON.parse(str); } catch (e) { showFlag('error', 'Please select json format data', '', 'auto'); return false; } return true; }; let selection = window.getSelection().toString().trim(); if (!selection) { showFlag('error', 'No Issue Key selected', '', 'auto'); return; } else if (isJson(selection)) { var jsonData = jsonToTree(JSON.parse(selection)); /** var jsonView = document.createElement('pre'); jsonView.textContent = JSON.stringify(jsonData,null,2); **/ showDialog(jsonData, 'Json Format'); } }); } /** * This function creates audio and checkbox controls and adds them to the Jira share button's parent node * @returns {Object} Object containing references to the audio control and audio checkbox, keep checkbox, prompt checkbox */ // ## In the future, the alert sound will be migrated to another server, and more fun music will be added. function createNotifyControls() { console.log('#### Code createNotifyControls run ####'); const operationsBar = $('div.saved-search-operations.operations'); const audioControl = $('<span></span>'); function createAudioControl(parentNode) { const currentDate = new Date(); const audioURL = currentDate.getHours() >= 9 && currentDate.getHours() < 21 ? 'https://gitee.com/aspirepig/aspirepig/raw/master/12221.wav' : 'https://gitee.com/aspirepig/aspirepig/raw/master/alerts.wav'; audioControl.html(`<audio id="myAudio" src="${audioURL}" type="audio/mpeg" controls></audio>`); parentNode.prepend(audioControl); } function createCheckbox(parentNode, localStorageKey, checkStatus) { const checkbox = $('<span></span>'); const value = localStorage.getItem(localStorageKey); checkbox.html( `<input type="checkbox" name="${localStorageKey}" ${ value == 'true' ? 'checked' : checkStatus ? 'checked' : '' }>${localStorageKey}` ); checkbox.find('input').on('click', () => { localStorage.setItem(localStorageKey, checkbox.find('input').prop('checked')); }); parentNode.prepend(checkbox); return checkbox; } createAudioControl(operationsBar); const audioCheckbox = createCheckbox(operationsBar, 'audioNotify', false); const keepCheckbox = createCheckbox(operationsBar, 'keepAudio', false); const promptCheckbox = createCheckbox(operationsBar, 'prompt', true); return { audioControl, audioCheckbox, keepCheckbox, promptCheckbox }; } /** * Check for updates in the issues list and play a sound if new issues are found * @param {Object} NotifyControls - Object containing the audio control, audio checkbox, keep checkbox, prompt checkbox */ function checkupdate(NotifyControls) { console.log('#### Code checkupdate run ####'); const { audioControl, audioCheckbox, keepCheckbox, promptCheckbox } = NotifyControls; const table = $('tbody'); if (!table.length) return; let cachedEntry = GM_getValue('cachedEntry', null); let Tickets = ''; table.find('tr').each(function () { const summary = $(this).find('.summary p').text().trim(); const issuekey = $(this).find('.issuekey a.issue-link').attr('data-issue-key'); if (!notifyKey.includes(issuekey)) { notifyKey.push(issuekey); Tickets += `${summary}==${issuekey}\n`; } }); if (Tickets || keepCheckbox.find('input').prop('checked')) { if (audioCheckbox.find('input').prop('checked')) { audioControl.find('audio').get(0).currentTime = 0; audioControl.find('audio').get(0).play(); } } $('.aui-banner').remove(); let overdueTickets = ''; table.find('tr').each(function () { const issuekey = $(this).find('.issuekey a.issue-link').attr('data-issue-key'); const datetime = new Date($(this).find('.updated time').attr('datetime')); const currentTime = new Date(); const diffMs = currentTime - datetime; const diffMinutes = Math.floor(diffMs / 60000); if (diffMinutes > 30 && diffMinutes < 120) { overdueTickets += `<a href="${cachedEntry['hk']}/browse/${issuekey}" target="_blank">${issuekey}</a>, `; } }); if (overdueTickets && promptCheckbox.find('input').prop('checked')) { GM_addStyle(` .aui-banner.aui-banner-warning { background-color: #ffab00 !important; color: black !important; } `); AJS.banner({ body: `Ticket: ${overdueTickets}<br>30 minutes have passed since the ticket's status changed, please handle it as soon as possible`, type: 'warning' }); } } /** * This function checks for specific keywords within a string * Advises the user to double-check and contact L2 or TL if suspicious. */ function checkKeywords() { console.log('#### Code checkKeywords run ####'); function check(keywords) { const rawLog = $('#customfield_10219-val').text().trim().toLowerCase(); const summary = $('#summary-val').text().trim().toLowerCase(); let Raw_Crotex_alert = $('.code-java').text().trim().toLowerCase(); for (const keyword of keywords) { if ( rawLog.includes(keyword['keyword'].toLowerCase()) || Raw_Crotex_alert.includes(keyword['keyword'].toLowerCase()) || summary.includes(keyword['keyword'].toLowerCase()) ) { AJS.banner({ body: `\"${keyword['keyword']}\" was found in the ticket, it is maybe used for "${keyword['remark']}", please double-check and contact L2 or TL if suspicious.` }); } } } function fetchData(url, apiKey) { const cachedKeywordsContent = GM_getValue('cachedKeywordsContent', null); const cachedWebsiteContent = GM_getValue('cachedWebsiteContent', null); const cachedWhitehashContent = GM_getValue('cachedWhitehashContent', null); GM_xmlhttpRequest({ method: 'GET', url: url, headers: { 'api-key': apiKey }, timeout: 4000, // 超过4秒未获取到文件则使用缓存文件 onload: function (response) { if (response.status === 200) { const data = JSON.parse(response.responseText)['data']; console.log(data); if (cachedKeywordsContent == null) { GM_setValue('cachedKeywordsContent', data['keywords']); } if (cachedWebsiteContent == null) { GM_setValue('cachedWebsiteContent', data['website']); let cachedEntry = {}; data['website'].forEach((item, index) => { if (item && item['name'] == 'hk' && item['url']) { cachedEntry['hk'] = item['url']; } if (item && item['name'] == 'macao' && item['url']) { cachedEntry['macao'] = item['url']; } GM_setValue('cachedEntry', cachedEntry); }); } if (cachedWhitehashContent == null) { GM_setValue('cachedWhitehashContent', data['whitehash']); } } else { console.error('Error fetching cachedContent:', response.status); } }, ontimeout: function () { if (cachedKeywordsContent == null || cachedWebsiteContent == null || cachedWhitehashContent == null) { showFlag('Error', 'BTAS缓存数据获取失败', '未连接到 VPN,请连接后刷新页面', 'auto'); } }, onerror: function (error) { console.error('Error:', error); } }); } const url = 'https://172.18.4.200/api/7vVKD9hF/message/'; const apiKey = 'Tnznjha3yhJgA7YG'; const cachedKeywordsContent = GM_getValue('cachedKeywordsContent', null); if (cachedKeywordsContent == null) { fetchData(url, apiKey); } check(cachedKeywordsContent); } /** * This function is used for checking ATT&CK field */ function checkATTCK() { const status = $('#opsbar-transitions_more > span').text().trim(); const attck = $('#rowForcustomfield_10220 > div > strong > label').text(); if (status == 'Waiting for customer' && attck == '') { AJS.banner({ body: `The ATT&CK field is not filled in` }); } } /** * This function is used for popping up MSS ticket considerations when clicked "Edit" and "Resolved" button or page loading. * Ticket Considerations file is store in cloud server * @param {Object} pageData - Gets the specified fields from the jira page */ function ticketNotify(pageData) { console.log('#### Code ticketNotify run ####'); function fetchOrgNotifydict() { // 从本地存储获取缓存的文件内容和上次更新时间 const cachedContent = GM_getValue('cachedFileContent', null); GM_xmlhttpRequest({ method: 'GET', url: 'https://172.18.4.200/api/7vVKD9hF/notifys/', headers: { 'api-key': 'Tnznjha3yhJgA7YG' }, timeout: 4000, // 超过4秒未获取到文件则使用缓存文件 onload: function (response) { if (response.status === 200) { const data = JSON.parse(response.responseText)['data']; // 本地无缓存,第一次获取文件保存到本地 if (cachedContent == null) { // 更新本地存储中的文件内容和更新时间 GM_setValue('cachedFileContent', data); checkNotify(data.items, pageData); } // 如果本地存储中有缓存,并且文件内容有变化 if (cachedContent !== null && JSON.stringify(cachedContent) !== JSON.stringify(data)) { // 更新本地存储中的文件内容 GM_setValue('cachedFileContent', data); // 使用最新文件 checkNotify(data.items, pageData); } // 本地存在缓存,且内容相同则使用缓存文件 if (cachedContent !== null && JSON.stringify(cachedContent) == JSON.stringify(data)) { checkNotify(cachedContent.items, pageData); } } else { console.error('Error fetching orgNotifydict:', response.status); } }, ontimeout: function () { if (cachedContent !== null) { checkNotify(cachedContent.items, pageData); } else { showFlag('Error', '文件获取失败', '未连接到 VPN,请连接后刷新页面', 'auto'); } }, onerror: function (error) { console.error('Error:', error); } }); } fetchOrgNotifydict(); function checkNotify(Notifydict, pageData) { // get button path const buttonMap = { Edit: '#edit-issue', Resolve: '#action_id_761', None: '' }; const searchStrings = []; // 查找并高亮指定字符串的函数 function highlightTextInElement(selector, searchStrings) { const element = $(selector); if (element.length === 0) { console.error('未找到指定的元素'); return; } // 获取元素文本内容 let text = element.text().trim(); // 对每个字符串进行高亮处理 searchStrings.forEach((searchString) => { // 在文本中查找并替换匹配的字符串 text = text.replace( new RegExp(searchString, 'gi'), (match) => `<span style="background-color: yellow;">${match}</span>` ); }); // 将替换后的文本重新设置为元素的 HTML 内容 element.html(text); } function checkProperties(properties, pageData, ticketname) { const condition = (property) => { const propertyArray = property.propertiesVal.split(','); let isAllConditionsMet = false; for (const val of propertyArray) { try { if (!property.conditionOptions) { let isTrue = pageData[property.propertiesKey] .toLowerCase() .includes(val.trim().toLowerCase().replace('!', '')); if (val.trim().toLowerCase().includes('!')) { isTrue = !isTrue; } if (isTrue) { if (property.propertiesKey == 'RawLog') { searchStrings.push(val.trim()); } isAllConditionsMet = true; // 如果任何一个属性满足条件,返回 true } } switch (property.conditionOptions) { case 'contain': if (pageData[property.propertiesKey].toLowerCase().includes(val.trim().toLowerCase())) { isAllConditionsMet = true; } break; case 'not contain': if ( !pageData[property.propertiesKey].toLowerCase().includes(val.trim().toLowerCase()) ) { isAllConditionsMet = true; } break; case 'equal': if (pageData[property.propertiesKey].toLowerCase() === val.trim().toLowerCase()) { isAllConditionsMet = true; } break; case 'not equal': if (pageData[property.propertiesKey].toLowerCase() !== val.trim().toLowerCase()) { isAllConditionsMet = true; } break; default: console.log('Unknown.'); } } catch (error) { if ( error.name === 'TypeError' && error.message == "Cannot read properties of undefined (reading 'includes')" ) { console.warn(`${ticketname} 提醒未加条件,请检查配置`); } } } return isAllConditionsMet; // 如果所有属性都不满足条件,则返回 false }; properties = JSON.parse(properties); return properties.reduce((acc, property) => { return acc && condition(property); }, true); } let cachedEntry = GM_getValue('cachedEntry', null); let projectMap = {}; projectMap[cachedEntry['hk'].split('//')[1]] = 'HK'; projectMap[cachedEntry['macao'].split('//')[1]] = 'MO'; for (const notify of Notifydict) { const { ticketname, starttime, endtime, message, properties, button, status, project } = notify; const isInTimeRange = (!starttime || new Date() >= new Date(starttime)) && (!endtime || new Date() <= new Date(endtime)); const clickButton = buttonMap[button]; if (status == 'Disable' || !isInTimeRange || projectMap[window.location.host] !== project) { continue; } if (checkProperties(properties, pageData, ticketname)) { if (clickButton == '') { showFlag('warning', `${ticketname}`, `${message.replace(/\r?\n/g, '<br>')}`, 'manual'); } else { $(clickButton).on('click', () => { showFlag('warning', `${ticketname}`, `${message.replace(/\r?\n/g, '<br>')}`, 'manual'); }); } let selector; if (project == 'HK') { selector = '#field-customfield_10219 > div:first-child > div:nth-child(2)'; } else if (project == 'MO') { selector = '#field-customfield_10904 > div.twixi-wrap.verbose > div'; } highlightTextInElement(selector, searchStrings); } } } } /** * Creates a new button and adds it to the DOM. * @param {string} id - The ID attribute for the new button element. * @param {string} text - The text content to display on the new button. * @param {string} onClick - The function to call when the button is clicked. */ function addButton(id, text, onClick) { console.log(`#### Add Button: ${text} ####`); const toolbar = $('.aui-toolbar2-primary'); // 重复添加的按钮不会被显示 if ($('#' + id).length === 0) { const button = $('<a>') .attr('id', id) .addClass('aui-button toolbar-trigger') .append($('<span>').addClass('trigger-label').text(text)) .click(onClick); toolbar.append($('<div>').addClass('aui-buttons pluggable-ops').append(button)); } } function monitorList() { var summaryElements = document.querySelectorAll('.summary'); summaryElements.forEach(function (element) { if ( element.textContent.includes('WebAvailability') || element.textContent.includes('SWIFT login activity and select activity detected') ) { var audio = document.getElementById('myAudio'); audio.play(); } }); var time_to_first_response = document.querySelectorAll('.sla-tag.sla-tag-ongoing'); time_to_first_response.forEach(function (element) { console.log(element.outerText.replace('min', ''), element.outerText.replace('min', '') < 30); if (element.outerText.includes('min') && element.outerText.replace('min', '') < 30) { var audio = document.getElementById('myAudio'); audio.play(); console.log('出现特殊情况'); } }); } /** * Creates three buttons on a JIRA issue page to handle Cortex XDR alerts * The buttons allow users to generate a description of the alerts, open the alert card page and timeline page */ function cortexAlertHandler(...kwargs) { console.log('#### Code cortexAlertHandler run ####'); const { LogSourceDomain, summary } = kwargs[0]; const rawLog = $('#field-customfield_10232 > div.twixi-wrap.verbose > div > div > div > pre').text(); /** * Extracts the log information and organization name from the current JIRA issue page * @param {Object} orgDict - A dictionary that maps organization name to navigator name * @returns {Object} An object that contains the organization's name, organization's navigator URL, raw log information */ let orgDict = {}; const cachedWebsiteContent = GM_getValue('cachedWebsiteContent', null); console.log(cachedWebsiteContent); if (cachedWebsiteContent != null) { cachedWebsiteContent.forEach((item, index) => { if (item && item['category'] == 'cortex' && item['url']) { orgDict[item['name']] = item['url']; } }); console.log('===orgDict', orgDict); } else { alert('cachedWebsiteContent is empty,please connect VPN get information'); } const orgNavigator = orgDict[LogSourceDomain]; /** * Parse the relevant information from the raw log data * @param {Array} rawLog - An array of JSON strings representing the raw log data * @returns {Array} An array of objects containing the alert relevant information */ function parseLog(rawLog) { let alertInfo = []; try { const { timestamp, data, rule } = JSON.parse(rawLog); let rule_description = rule['description'].split(':')[-1]; const { cortex_xdr } = data; const { source, alert_id, name, description } = cortex_xdr; const isPANNGFW = source === 'PAN NGFW'; let dotIndex = timestamp.lastIndexOf('.'); dateTimeStr = timestamp.slice(0, dotIndex) + '+0800'; const alert = { source, alert_id, name, description, dateTimeStr, rule_description }; if (isPANNGFW) { const { action_local_ip, action_local_port, action_remote_ip, action_remote_port, action_pretty, alert_link } = cortex_xdr; alertInfo.push({ ...alert, action_local_ip, action_local_port, action_remote_ip, action_remote_port, action_pretty, alert_link }); } else { const { action_local_ip, action_file_macro_sha256, action_file_name, action_file_path, action_file_sha256, action_process_image_name, action_process_image_sha256, action_process_image_command_line, action_external_hostname, actor_process_image_name, actor_process_image_path, actor_process_image_sha256, actor_process_command_line, causality_actor_process_image_name, causality_actor_process_command_line, causality_actor_process_image_path, causality_actor_process_image_sha256, os_actor_process_image_name, os_actor_process_image_path, os_actor_process_command_line, os_actor_process_image_sha256, action_pretty, host_name, host_ip, user_name, alert_link } = cortex_xdr; const action_list = { action_file_name, action_file_path, action_file_sha256, action_process_image_name, action_process_image_sha256, action_process_image_command_line }; const actor_list = { actor_process_image_name, actor_process_image_path, actor_process_image_sha256, actor_process_command_line }; const causality_actor_list = { causality_actor_process_image_name, causality_actor_process_command_line, causality_actor_process_image_path, causality_actor_process_image_sha256 }; const os_actor_list = { os_actor_process_image_name, os_actor_process_image_path, os_actor_process_command_line, os_actor_process_image_sha256 }; function countValidProperties(obj) { const validPropsCount = Object.keys(obj).reduce((count, key) => { if (obj[key] !== undefined) { count++; } return count; }, 0); return validPropsCount; } const actionPropsCount = countValidProperties(action_list) ? countValidProperties(action_list) + 1 : 0; const actorPropsCount = countValidProperties(actor_list); const causalityPropsCount = countValidProperties(causality_actor_list); const osPropsCount = countValidProperties(os_actor_list); const maxCount = Math.max(actionPropsCount, actorPropsCount, causalityPropsCount, osPropsCount); const action_cmd_length = action_process_image_command_line ? action_process_image_command_line.length : 0; const actor_cmd_length = actor_process_command_line ? actor_process_command_line.length : 0; const causality_cmd_length = causality_actor_process_command_line ? causality_actor_process_command_line.length : 0; const os_cmd_length = os_actor_process_command_line ? os_actor_process_command_line.length : 0; const lengths = [action_cmd_length, actor_cmd_length, causality_cmd_length, os_cmd_length]; const maxLength = Math.max(...lengths); let filename; let filepath; let sha256; let cmd; if (action_cmd_length === maxLength && actionPropsCount === maxCount) { if (!WhiteFilehash(action_file_sha256 || action_process_image_sha256)) { sha256 = action_file_sha256 || action_process_image_sha256; } filename = action_file_name || action_process_image_name; filepath = action_file_path; cmd = action_process_image_command_line; } else if (actor_cmd_length === maxLength && actorPropsCount === maxCount) { if (!WhiteFilehash(actor_process_image_sha256)) { sha256 = actor_process_image_sha256; } filename = actor_process_image_name; filepath = actor_process_image_path; cmd = actor_process_command_line; } else if (causality_cmd_length === maxLength && causalityPropsCount === maxCount) { if (!WhiteFilehash(causality_actor_process_image_sha256)) { sha256 = causality_actor_process_image_sha256; } filename = causality_actor_process_image_name; filepath = causality_actor_process_image_path; cmd = causality_actor_process_command_line; } else if (os_actor_process_image_name && osPropsCount === maxCount) { if (!WhiteFilehash(os_actor_process_image_sha256)) { sha256 = os_actor_process_image_sha256; } filename = os_actor_process_image_name; filepath = os_actor_process_image_path; cmd = os_actor_process_command_line; } alertInfo.push({ ...alert, host_name, host_ip, alert_link, user_name, filename, filepath, cmd, sha256, action_pretty, action_local_ip, action_file_macro_sha256, action_external_hostname }); } } catch (error) { console.error(`Error: ${error.message}`); } return alertInfo; } const alertInfo = parseLog(rawLog); /** * Define three functions for handling alert information: * generateDescription creates a description for each alert, and displays the combined description in an alert box * openCard opens a new window to display the alert card page for each alert * openTimeline opens a new window to display the timeline page for each alert */ function generateDescription() { const alertDescriptions = []; for (const info of alertInfo) { let { source, name, action_local_ip, action_local_port, action_remote_ip, action_remote_port, action_pretty, description, alert_link, rule_description, action_external_hostname } = info; let unPanNgfw = [ 'host_name', 'host_ip', 'sha256', 'action_file_macro_sha256', 'filepath', 'filename', 'cmd', 'user_name', 'action_local_ip' ]; if (description && description.includes('xdr_data')) { console.log(rule_description); description = rule_description; } if (source === 'PAN NGFW') { const desc = `Observed ${name}\ntimestamp: ${dateTimeStr}\nSrcip: ${action_local_ip} Srcport: ${action_local_port}\nDstip: ${action_remote_ip} Dstport: ${action_remote_port}\nAction: ${action_pretty}\n${ LogSourceDomain === 'cityu' ? 'Cortex Portal: ' + alert_link + '\n' : '' }\n\nPlease help to verify if this activity is legitimate.\n`; alertDescriptions.push(desc); } else { let comment = '\nPlease help to verify if this activity is legitimate.\n'; if ( summary.toLowerCase().includes('wildfire malware') || summary.toLowerCase().includes('local analysis malware') ) { comment = '\nPlease verify if the File is legitimate. IF NOT, please Remove the File.\n'; } let desc = `Observed ${ description || name }\ntimestamp: ${dateTimeStr} \n<span class="red_highlight">action_external_hostname: ${action_external_hostname}\n</span>action: ${action_pretty}\n`; for (const key of unPanNgfw) { console.log(key); if (Object.hasOwnProperty.call(info, key)) { const value = info[key]; console.log(key, value); if (value !== undefined) { if (key == 'event_evidence') { desc += `${key}: ${value.replace(/</g, '<').replace(/>/g, '>')}\n`; } else { desc += `${key}: ${value}\n`; } } } } if (info['action_file_macro_sha256'] || info['sha256']) { desc += `<a href="https://www.virustotal.com/gui/file/${ info['action_file_macro_sha256'] || info['sha256'] }">https://www.virustotal.com/gui/file/${info['action_file_macro_sha256'] || info['sha256']}</a>\n`; } alertDescriptions.push(desc + comment); } } const alertMsg = [...new Set(alertDescriptions)].join('\n'); showDialog(alertMsg); } function openCard() { for (const info of alertInfo) { const { source, alert_id } = info; if (orgNavigator) { let cardURL; switch (source) { case 'XDR Analytics': cardURL = `${orgNavigator}card/analytics2/${alert_id}`; break; case 'Correlation': cardURL = `${orgNavigator}alerts/${alert_id}`; break; default: cardURL = `${orgNavigator}card/alert/${alert_id}`; break; } window.open(cardURL, '_blank'); } else { showFlag('error', '', `There is no <strong>${LogSourceDomain}</strong> Navigator on Cortex`, 'auto'); } } } function openTimeline() { for (const info of alertInfo) { const { source, alert_id } = info; if (orgNavigator) { let timelineURL; switch (source) { case 'Correlation': showFlag( 'error', '', `Source of the Alert is <strong>${source}</strong>, There is no Timeline on Cortex`, 'auto' ); break; default: timelineURL = `${orgNavigator}forensic-timeline/alert_id/${alert_id}`; break; } timelineURL && window.open(timelineURL, '_blank'); } else { showFlag('error', '', `There is no <strong>${LogSourceDomain}</strong> Navigator on Cortex`, 'auto'); } } } addButton('generateDescription', 'Description', generateDescription); addButton('openCard', 'Card', openCard); addButton('openTimeline', 'Timeline', openTimeline); } function HTSCAlertHandler(...kwargs) { console.log('#### Code HTSCAlertHandler run ####'); const { rawLog } = kwargs[0]; function decodeHtml(encodedString) { const tmpElement = document.createElement('span'); tmpElement.innerHTML = encodedString; return tmpElement.innerText; } const parseLog = (rawLog) => { const alertInfo = rawLog.reduce((acc, log) => { try { const formatJson = log.substring(log.indexOf('{')).trim(); // const logObj = JSON.parse(formatJson); const logObj = JSON.parse(formatJson.replace(/\\\(n/g, '\\n(')); const eventEvidence = decodeHtml(logObj.event_evidence).split('End time')[0]; const alert = { attackType: logObj.tag, hostRisk: logObj.hostRisk, srcIP: logObj.src_ip, eventEvidence, hostName: logObj.hostName, dstIP: logObj.dst_ip }; acc.push(alert); } catch (error) { console.error(`Error: ${error.message}`); } return acc; }, []); return alertInfo; }; const alertInfo = parseLog(rawLog); // console.info(`alertInfo: ${alertInfo}`); function generateDescription() { const alertDescriptions = []; for (const info of alertInfo) { const { attackType, hostRisk, srcIP, hostName, dstIP, eventEvidence } = info; const desc = `Observed ${attackType} Attack\nhostRisk: ${hostRisk}\nSrc_IP: ${srcIP}\nhostname: ${hostName}\nDst_IP: ${dstIP}\nevent_evidence: ${eventEvidence}\n\nPlease help to verify if this activity is legitimate.\n`; alertDescriptions.push(desc); } const alertMsg = [...new Set(alertDescriptions)].join('\n'); showDialog(alertMsg); } addButton('generateDescription', 'Description', generateDescription); } function VMCEFAlertHandler(...kwargs) { const { rawLog } = kwargs[0]; function parseCefLog(rawLog) { function cefToJson(cefLog) { let json = {}; let fields = cefLog.split(' '); for (let i = 0; i < fields.length; i++) { let field = fields[i].split('='); let key = field[0]; let value = field.slice(1).join('='); if (value) { if (key === 'filePath' || key === 'msg' || key === 'start' || key === 'rt') { let nextFieldIndex = i + 1; while (nextFieldIndex < fields.length && !fields[nextFieldIndex].includes('=')) { value += ' ' + fields[nextFieldIndex]; nextFieldIndex++; } } json[key] = value; } } return json; } const alertInfo = rawLog.reduce((acc, log) => { try { // Determine whether the log is empty if (Object.keys(log).length !== 0) { // Split CEF log let cef_log = log.split('|'); // Parsing CEF Header const cef_log_header = cef_log.slice(1, 7); // Parsing CEF Extends const cef_log_extends = cefToJson(cef_log[7]); acc.push({ Summary: cef_log_header[4], // for some like "server error" tickets HostName: cef_log_extends.dhost ? cef_log_extends.dhost : cef_log_extends.dvchost, HostIp: cef_log_extends.dst, UserName: cef_log_extends.duser, FileName: cef_log_extends.fname, FilePath: cef_log_extends.filePath, Sha256: cef_log_extends.fileHash, Msg: cef_log_extends.msg }); } return acc; } catch (error) { console.error(`Error: ${error.message}`); } }, []); return alertInfo; } const alertInfo = parseCefLog(rawLog); function generateDescription() { const alertDescriptions = []; for (const info of alertInfo) { const { Summary } = info; let desc = `Observed ${Summary}\n`; Object.entries(info).forEach(([index, value]) => { if (value !== undefined && index != 'Summary' && index != 'CBlink') { desc += `${index}: ${value}\n`; } }); desc += `\nPlease verify if the activity is legitimate.\n`; alertDescriptions.push(desc); } const alertMsg = [...new Set(alertDescriptions)].join('\n'); showDialog(alertMsg); } addButton('generateDescription', 'Description', generateDescription); } function CBAlertHandler(...kwargs) { console.log('#### Code CBAlertHandler run ####'); const { rawLog } = kwargs[0]; function parseLeefLog(rawLog) { const alertInfo = rawLog.reduce((acc, log) => { const cb_log = {}; try { const log_obj = log.split('\t'); log_obj.forEach((log_item) => { try { const [key, value] = log_item.split('='); cb_log[key] = value; } catch (error) { console.error(`Error: ${error.message}`); } }); if (log.trim() !== '') { acc.push({ Summary: cb_log.watchlist_name, HostName: cb_log.computer_name, HostIp: cb_log.interface_ip, UserName: cb_log.username, CmdLine: cb_log.cmdline, CBlink: cb_log.link_process, Filepath: cb_log.path, Sha256: cb_log.process_sha256 }); } } catch (error) { console.error(`Error: ${error.message}`); } return acc; }, []); return alertInfo; } const alertInfo = parseLeefLog(rawLog); function generateDescription() { const alertDescriptions = []; for (const info of alertInfo) { const { Summary } = info; let desc = `Observed ${Summary}\n`; Object.entries(info).forEach(([index, value]) => { if (value !== undefined && index != 'Summary' && index != 'CBlink') { desc += `${index}: ${value}\n`; } }); desc += `\nPlease verify if the activity is legitimate.\n`; alertDescriptions.push(desc); } const alertMsg = [...new Set(alertDescriptions)].join('\n'); showDialog(alertMsg); } function openCB() { let CBURL = ''; for (const info of alertInfo) { const { CBlink } = info; if (CBlink) { CBURL += `${CBlink}\n`; } } showFlag('info', 'CB URL:', `${CBURL}`, 'manual'); } addButton('generateDescription', 'Description', generateDescription); addButton('openCB', 'CB', openCB); } function WineventAlertHandler(...kwargs) { console.log('#### Code WineventAlertHandler run ####'); let { rawLog, summary } = kwargs[0]; var raw_alert = 0; const num_alert = $('#customfield_10300-val').text().trim(); summary = summary.replace(/[\[(].*?[\])]/g, ''); function parseLog(rawLog) { const alertInfo = rawLog.reduce((acc, log) => { try { const { win } = JSON.parse(log); raw_alert += 1; const { eventdata, system } = win; const alertHost = system.computer; const systemTime = system.systemTime; acc.push({ systemTime, summary, alertHost, eventdata }); } catch (error) { console.error(`Error: ${error.message}`); } return acc; }, []); return alertInfo; } const alertInfo = parseLog(rawLog); function generateDescription() { const alertDescriptions = []; if (raw_alert < num_alert) { let extra_message = `<span class="red_highlight">Number Of Alert : ${num_alert}, Raw Log Alert : ${raw_alert} Raw log information is Not Complete, Please Get More Alert Information From Elastic.</span>\n`; alertDescriptions.push(extra_message); } for (const info of alertInfo) { let desc = `Observed${info.summary}\nHost: ${info.alertHost}\n`; const date = new Date(info.systemTime.split('.')[0]); date.setHours(date.getHours() + 16); desc += `systemTime(<span class="red_highlight">UTC+8</span>): ${date.toISOString().split('.')[0]}\n`; for (const key in info.eventdata) { if (Object.hasOwnProperty.call(info.eventdata, key)) { const value = info.eventdata[key]; if (value !== undefined) { desc += `${key}: ${value}\n`; } } } desc += '\n' + 'Please help to verify if this activity is legitimate.' + '\n'; alertDescriptions.push(desc); } const alertMsg = [...new Set(alertDescriptions)].join('\n'); showDialog(alertMsg); } addButton('generateDescription', 'Description', generateDescription); } function FortigateAlertHandler(...kwargs) { let { rawLog, summary, LogSourceDomain } = kwargs[0]; var raw_alert = 0; const num_alert = $('#customfield_10300-val').text().trim(); summary = summary.split(']')[1].trim(); function ParseFortigateLog(rawLog) { const alertInfos = rawLog.reduce((acc, log) => { if (log == '') { return acc; } let jsonData = {}; const regex = /(\w+)=(["'].*?["']|\S+)/g; let matchresult; raw_alert += 1; while ((matchresult = regex.exec(log)) !== null) { let key = matchresult[1]; let value = matchresult[2]; if (value.startsWith('"') && value.endsWith('"')) { value = value.slice(1, -1); } else if (value.startsWith("'") && value.endsWith("'")) { value = value.slice(1, -1); } jsonData[key] = value; } acc.push(jsonData); return acc; }, []); return [...new Set(alertInfos)]; } const alertInfos = ParseFortigateLog(rawLog); function ExtractAlertInfo(ExtractAlertInfo) { const extract_alert_infos = alertInfos.reduce((acc, alertInfo) => { const { date, time, srcip, srcport, srccountry, dstip, dstport, dstcountry, hostname, url, referralurl, action, devname, user, cfgattr, msg, forwardedfor, analyticscksum, from, to, remip } = alertInfo; let arr = []; if (summary.toLowerCase().includes('infected file detected in fortigate')) { let vt_url; if (url) { vt_url = 'https://www.virustotal.com/gui/domain/' + url.split('/')[2]; } else { vt_url = 'https://www.virustotal.com/gui/ip-address/' + srcip; } let sum = 'https://www.virustotal.com/gui/search/' + analyticscksum; arr.push(`<a href="${vt_url}">${vt_url}</a>`); arr.push(`<a href="${sum}">${sum}</a>`); } else if (summary.toLowerCase().includes('connection attempt')) { let vt_url = 'https://www.virustotal.com/gui/ip-address/' + dstip; arr.push(`<a href="${vt_url}">${vt_url}</a>`); } else if (summary.toLowerCase().includes('connection to newly registered domain')) { let vt_url = 'https://www.virustotal.com/gui/domain/' + hostname; arr.push(`<a href="${vt_url}">${vt_url}</a>`); } else if (summary.toLowerCase().includes('non-office hour successful vpn login')) { let vt_url = 'https://www.virustotal.com/gui/ip-address/' + remip; arr.push(`<a href="${vt_url}">${vt_url}</a>`); } const extract_alert_info = { datetime: `${date} ${time}`, srcip: srcip ? `${srcip}:${srcport}[${srccountry}]` : undefined, dstip: dstip ? `${dstip}:${dstport}[${dstcountry}]` : undefined, hostname: hostname, devname: devname, user: user, url: url, action: action, cfgattr: cfgattr, msg: msg, referralurl: referralurl, forwardedfor: forwardedfor || undefined, analyticscksum: analyticscksum, from: from, to, remip: remip, VT: arr.length > 0 ? arr : undefined }; acc.push(extract_alert_info); return acc; }, []); return extract_alert_infos; } function ExtractAlertInfo_sonicwall(ExtractAlertInfo) { const extract_alert_infos = alertInfos.reduce((acc, alertInfo) => { acc.push({ time: alertInfo.time, msg: alertInfo.msg, src: alertInfo.src, srcZone: alertInfo.srcZone, natSrc: alertInfo.natSrc, dst: alertInfo.dst, dstZone: alertInfo.dstZone, natDst: alertInfo.natDst, proto: alertInfo.proto }); return acc; }, []); return extract_alert_infos; } let extract_alert_infos = ''; if (LogSourceDomain == 'miramar') { console.log('===miramar'); extract_alert_infos = ExtractAlertInfo_sonicwall(alertInfos); } else { extract_alert_infos = ExtractAlertInfo(alertInfos); } function generateDescription() { const alertDescriptions = []; if (raw_alert < num_alert) { let extra_message = `<span class="red_highlight">Number Of Alert : ${num_alert}, Raw Log Alert : ${raw_alert} Raw log information is Not Complete, Please Get More Alert Information From Elastic.</span>\n`; alertDescriptions.push(extra_message); } for (const info of extract_alert_infos) { let desc = `Observed ${summary}\n`; Object.entries(info).forEach(([index, value]) => { if (value !== undefined) { desc += `${index}: ${value}\n`; } }); let comment = '\nPlease help to verify if this activity is legitimate.\n'; if (summary.toLowerCase().includes('to malware ip(s)') || summary.toLowerCase().includes('to tor ip(s)')) { comment = '\nPlease verify if the IP is legitimate. If NOT, please block the dst ip\n'; } desc += comment; alertDescriptions.push(desc); } const alertMsg = [...new Set(alertDescriptions)].join('\n'); showDialog(alertMsg); } addButton('generateDescription', 'Description', generateDescription); } function CSAlertHandler(...kwargs) { let { rawLog } = kwargs[0]; var raw_alert = 0; const num_alert = $('#customfield_10300-val').text().trim(); function parseCefLog(rawLog) { function cefToJson(cefLog) { let json = {}; let fields = cefLog.split(' '); for (let i = 0; i < fields.length; i++) { let field = fields[i].split('='); let key = field[0]; let value = field.slice(1).join('='); if (value) { if (key === 'filePath' || key === 'msg' || key === 'cs5' || key === 'start' || key === 'rt') { let nextFieldIndex = i + 1; while (nextFieldIndex < fields.length && !fields[nextFieldIndex].includes('=')) { value += ' ' + fields[nextFieldIndex]; nextFieldIndex++; } } json[key] = value; } } return json; } const alertInfo = rawLog.reduce((acc, log) => { try { // Determine whether the log is empty if (Object.keys(log).length !== 0) { // Split CEF log let cef_log = log.split('|'); // Parsing CEF Header const cef_log_header = cef_log.slice(1, 7); // Parsing CEF Extends const cef_log_extends = cefToJson(cef_log[7]); raw_alert += 1; acc.push({ CreateTime: cef_log[0].split(' localhost ')[0], Summary: cef_log_header[4], // for some like "server error" tickets HostName: cef_log_extends.dhost ? cef_log_extends.dhost : cef_log_extends.dvchost, HostIp: cef_log_extends.dst, UserName: cef_log_extends.duser, FileName: cef_log_extends.fname, FilePath: cef_log_extends.filePath, Command: cef_log_extends.cs5, Sha256: cef_log_extends.fileHash, Msg: cef_log_extends.msg, CSLink: cef_log_extends.cs6 ? cef_log_extends.cs6 : cef_log_extends.cs1 }); } return acc; } catch (error) { console.error(`Error: ${error.message}`); } }, []); return alertInfo; } const alertInfo = parseCefLog(rawLog); function generateDescription() { const alertDescriptions = []; if (raw_alert < num_alert) { let extra_message = `<span class="red_highlight">Number Of Alert : ${num_alert}, Raw Log Alert : ${raw_alert} Raw log information is Not Complete, Please Get More Alert Information From Elastic.</span>\n`; alertDescriptions.push(extra_message); } for (const info of alertInfo) { const { Summary } = info; let desc = `Observed ${Summary}\n`; Object.entries(info).forEach(([index, value]) => { if (value !== undefined && index != 'Summary' && index != 'CSLink') { desc += `${index}: ${value}\n`; } }); desc += `\nPlease verify if the activity is legitimate.\n`; alertDescriptions.push(desc); } const alertMsg = [...new Set(alertDescriptions)].join('\n'); showDialog(alertMsg); } function openCS() { let CSURL = ''; let cs_url = []; for (const info of alertInfo) { const { CSLink } = info; if (CSLink && !cs_url.includes(CSLink)) { CSURL += `${CSLink.replace('hXXps', 'https').replace(/[\[\]]/g, '')}<br><br>`; } cs_url.push(CSLink); } showFlag('info', 'CS URL:', `${CSURL}`, 'manual'); } addButton('generateDescription', 'Description', generateDescription); addButton('openCS', 'CS', openCS); } function SophosAlertHandler(...kwargs) { let { rawLog } = kwargs[0]; var raw_alert = 0; const num_alert = $('#customfield_10300-val').text().trim(); function parseLog(rawLog) { const alertInfo = rawLog.reduce((acc, log) => { try { log.replace(/[\[(].*?[\])]/g, ''); const { sophos, logsource } = JSON.parse(log); raw_alert += 1; const summary = sophos.name; const createtime = sophos.rt.split('.')[0] + 'Z'; const alertHost = sophos.dhost; const alertUser = sophos.suser; const alertID = sophos.id; const alertIP = sophos?.source_info?.ip || sophos?.data?.source_info?.ip || ''; const alertExtraInfo = { 'Sha256': sophos.appSha256, 'Filename': sophos?.data?.fileName ? sophos.data.fileName : undefined, 'Processname': sophos?.data?.processName ? sophos.data.processName : undefined, 'Process': sophos?.data?.process ? sophos.data.process : undefined, 'Clean Up Result': sophos?.core_remedy_items?.items[0]?.result }; acc.push({ summary, createtime, alertHost, alertIP, alertUser, alertID, logsource, alertExtraInfo }); } catch (error) { console.log(`Error: ${error.message}`); } return acc; }, []); return alertInfo; } const alertInfo = parseLog(rawLog); function generateDescription() { const alertDescriptions = []; if (raw_alert < num_alert) { let extra_message = `<span class="red_highlight">Number Of Alert : ${num_alert}, Raw Log Alert : ${raw_alert} Raw log information is Not Complete, Please Get More Alert Information From Elastic.</span>\n`; alertDescriptions.push(extra_message); } for (const info of alertInfo) { let desc = `Observed ${info.summary}\nHost: ${info.alertHost} IP: ${info.alertIP || 'N/A'}\nUser: ${ info.alertUser }\ncreatetime:(<span class="red_highlight">GMT</span>)${info.createtime}\n`; for (const key in info.alertExtraInfo) { if (Object.hasOwnProperty.call(info.alertExtraInfo, key)) { const value = info.alertExtraInfo[key]; if (value !== undefined) { desc += `${key}: ${value}\n`; } } } if (!info.summary.includes('Failed to protect computer')) { desc += '\n' + 'Please help to verify if this activity is legitimate.' + '\n'; } alertDescriptions.push(desc); } const alertMsg = [...new Set(alertDescriptions)].join('\n'); showDialog(alertMsg); } function openSophos() { let searchID = ''; for (const info of alertInfo) { const { alertHost, alertID, logsource } = info; if (alertID || alertHost) { searchID += `<strong>[${logsource}] ${alertHost}</strong>:<br>${alertID}<br><br>`; } } showFlag('info', 'Host and Alert ID', `${searchID}`, 'manual'); GM_openInTab('https://cloud.sophos.com/manage/enterprise/alerts-list', { active: false, // 设置为 false,以在后台打开,不激活新标签页 insert: true // 设置为 true,将新标签页插入到当前标签页之后 }); } addButton('generateDescription', 'Description', generateDescription); addButton('openSophos', 'Open Sophos', openSophos); } function SpemAlertHandler(...kwargs) { const { rawLog, summary } = kwargs[0]; function parseLog(rawLog) { let logObject = {}; const alertInfo = rawLog.reduce((acc, log) => { try { logArray = log.split(','); logArray[10] = 'Action:' + logArray[10]; for (const index of logArray) { const [key, value] = index.split(/:(.+)/, 2); logObject[key] = value; } acc.push({ 'Summary': logObject['Event Description'] !== undefined ? logObject['Event Description'] : summary, 'User Name': logObject['User Name'], 'Local Host IP': logObject['Local Host IP'], 'Local Port': logObject['Local Port'], 'Remote Host IP': logObject['Remote Host IP'], 'Remote Port': logObject['Remote Port'], 'Application': logObject['Application'], 'SHA-256': logObject['SHA-256'], 'Intrusion URL': logObject['Intrusion URL'], 'Action': logObject['Action'] }); } catch (error) { console.log(`Error: ${error}`); } return acc; }, []); return alertInfo; } const alertInfo = parseLog(rawLog); function generateDescription() { const alertDescriptions = []; for (const info of alertInfo) { let desc = `Observed ${info['Summary']}\n`; Object.entries(info).forEach(([index, value]) => { if (value !== undefined && value !== ' ' && index != 'Summary') { desc += `${index}: ${value}\n`; } }); desc += `\nPlease verify if the activity is legitimate.\n`; alertDescriptions.push(desc); } const alertMsg = [...new Set(alertDescriptions)].join('\n'); showDialog(alertMsg); } addButton('generateDescription', 'Description', generateDescription); } function AwsAlertHandler(...kwargs) { const { rawLog, summary } = kwargs[0]; var raw_alert = 0; const DecoderName = $('#customfield_10807-val').text().trim().toLowerCase(); function parseLog(rawLog) { const alertInfo = rawLog.reduce((acc, log) => { try { const { aws } = JSON.parse(log); if (DecoderName == 'aws-guardduty') { let EventTime = aws.service.eventFirstSeen.split('.')[0] + 'Z'; const action = aws.service.action; if (action.actionType == 'AWS_API_CALL') { acc.push({ EventTime: EventTime, actionType: action.actionType, Api_Name: action?.awsApiCallAction?.api, userName: aws?.resource?.accessKeyDetails?.userName, RemoteIP: action?.awsApiCallAction?.remoteIpDetails?.ipAddressV4, RemoteIP_country: action?.awsApiCallAction?.remoteIpDetails?.country.countryName }); } else if (action.actionType == 'KUBERNETES_API_CALL') { acc.push({ EventTime: EventTime, actionType: action.actionType, userName: aws?.resource?.accessKeyDetails?.userName, sourceIPs: action?.kubernetesApiCallAction?.sourceIPs, requestUri: action?.kubernetesApiCallAction?.requestUri }); } else if (action.actionType == 'PORT_PROBE') { acc.push({ EventTime: EventTime, actionType: action.actionType, localPort: action?.portProbeAction?.portProbeDetails.localPortDetails.port, RemoteIP: action?.portProbeAction?.portProbeDetails.remoteIpDetails.ipAddressV4, RemoteIP_country: action?.portProbeAction?.portProbeDetails.remoteIpDetails.country.countryName }); } else if (action.actionType == 'NETWORK_CONNECTION') { console.log('===', action); acc.push({ EventTime: EventTime, actionType: action.actionType, localIp: action?.networkConnectionAction?.localIpDetails.ipAddressV4, localPortDetails: action?.networkConnectionAction?.localPortDetails.port, remoteIp: action?.networkConnectionAction?.remoteIpDetails.ipAddressV4, remotePortDetails: action?.networkConnectionAction?.remotePortDetails.port, instanceId: aws?.resource?.instanceDetails?.instanceId, platform: aws?.resource?.instanceDetails?.platform, remoteIpcountryName: action?.networkConnectionAction?.remoteIpDetails?.country?.countryName }); } } else if (summary.toLowerCase().includes('multiple sms request for same source ip')) { let headers = aws.logEvents.message.httpRequest.headers; let host, content; headers.forEach((item) => { if (item.name === 'host') { host = item.value; } if (item.name == 'content-type') { content = item.value; } }); acc.push({ log_file: aws.log_info.log_file, clientIp: aws.logEvents.message.httpRequest.clientIp, httpMethod: aws.logEvents.message.httpRequest.httpMethod, uri: aws.logEvents.message.httpRequest.uri, host: host, content_type: content }); } else { acc.push({ EventTime: aws?.eventTime, EventName: aws?.eventName, SourceIP: aws?.sourceIPAddress || aws?.internal_ip, ExternalIP: aws?.external_ip, Domain: aws?.domain, User: aws?.userIdentity?.arn, UserAgent: aws?.userAgent, PrincipalId: aws?.userIdentity?.principalId, Result: aws?.errorCode, QueryType: aws?.query_type, Action: aws?.action, requestParameters: JSON.stringify(aws?.requestParameters), responseElements: JSON.stringify(aws?.responseElements) }); } raw_alert += 1; } catch (error) { console.log(`Error: ${error}`); } return acc; }, []); return alertInfo; } const alertInfo = parseLog(rawLog); const num_alert = $('#customfield_10300-val').text().trim(); function generateDescription() { const alertDescriptions = []; if (raw_alert < num_alert) { let extra_message = `<span class="red_highlight">Number Of Alert : ${num_alert}, Raw Log Alert : ${raw_alert} Raw log information is Not Complete, Please Get More Alert Information From Elastic.</span>\n`; alertDescriptions.push(extra_message); } for (const info of alertInfo) { let desc = `Observed ${summary.split(']')[1]}\n`; Object.entries(info).forEach(([index, value]) => { if (value !== undefined && value !== ' ' && index != 'Summary') { if (index == 'EventTime') { desc += `EventTime(<span class="red_highlight">GMT</span>): ${value}\n`; } else { desc += `${index}: ${value}\n`; } } }); desc += `\nPlease verify if the activity is legitimate.\n`; alertDescriptions.push(desc); } const alertMsg = [...new Set(alertDescriptions)].join('\n'); showDialog(alertMsg); } addButton('generateDescription', 'Description', generateDescription); } function AzureAlertHandler(...kwargs) { const { rawLog } = kwargs[0]; function parseLog(rawLog) { const alertInfo = rawLog.reduce((acc, log) => { try { const { eventhub, azure } = JSON.parse(log); const { ExtendedProperties, Entities } = eventhub; let entities = {}; if (Entities) { Entities.forEach(function (entity) { if (entity.Type === 'host') { entities['host'] = entity['HostName']; } if (entity.Type === 'network-connection') { entities['SourceIP'] = entity['SourceAddress']['Address']; } }); } acc.push({ AlertType: eventhub['AlertType'], StartTimeUtc: eventhub['StartTimeUtc'], Severity: eventhub['Severity'], Intent: eventhub['Intent'], Description: eventhub['Description'], summary: azure['ThreatDescription'] || eventhub['AlertDisplayName'], Protocol: azure['Protocol'], SourceIP: azure['SourceIp'], SourcePort: azure['SourcePort'], DestinationIp: azure['DestinationIp'], DestinationPort: azure['DestinationPort'], URL: azure['Url'], Action: azure['Action'], ExtendedProperties: JSON.stringify(ExtendedProperties, null, 4), ...entities, alerturi: eventhub['AlertUri'] }); } catch (error) { console.log(`Error: ${error}`); } return acc; }, []); return alertInfo; } const alertInfo = parseLog(rawLog); function generateDescription() { const alertDescriptions = []; for (const info of alertInfo) { let desc = `Observed ${info.summary}\n`; Object.entries(info).forEach(([index, value]) => { if (value !== undefined && value !== '' && index !== 'summary') { if (index == 'StartTimeUtc') { desc += `StartTimeUtc(<span class="red_highlight">GMT</span>): ${value.split('.')[0]}\n`; } else { desc += `${index}: ${value}\n`; } } }); desc += `\nPlease verify if the activity is legitimate.\n`; alertDescriptions.push(desc); } const alertMsg = [...new Set(alertDescriptions)].join('\n'); showDialog(alertMsg); } function openAzure() { let AzureURL = ''; for (const info of alertInfo) { const { alerturi } = info; if (alerturi) { AzureURL += `${alerturi.replace('hXXps', 'https').replace(/\[|\]/g, '')}<br><br>`; } } showFlag('info', 'Azure URL:', `${AzureURL}`, 'manual'); } addButton('generateDescription', 'Description', generateDescription); addButton('openAzure', 'Azure', openAzure); } function paloaltoAlertHandler(...kwargs) { const { rawLog, summary } = kwargs[0]; var raw_alert = 0; const num_alert = $('#customfield_10300-val').text().trim(); function parseLog(rawLog) { const alertInfo = rawLog.reduce((acc, log) => { try { let logArray = log.split(','); let logType = logArray[3]; if (logType == 'GLOBALPROTECT') { acc.push({ 'Createtime': logArray[1], 'src ip': logArray[15], 'user': logArray[12] }); } if (logType == 'TRAFFIC') { acc.push({ 'Createtime': logArray[1], 'Summary': summary.split(']')[1], 'Source IP': logArray[7], 'Destination IP': logArray[8], 'Destination Port': logArray[25], 'Destination Location': logArray[42] != 0 ? logArray[42] : logArray[39] }); } if (logType == 'THREAT') { let really = false, malware_potential = []; for (let i = 0; i < logArray.length; i++) { if (logArray[i].includes('"') && i > 100) { if (really) { malware_potential.push(logArray[i]); } really = !really; } if (really) { malware_potential.push(logArray[i]); } } let vt_url = 'https://www.virustotal.com/gui/search/' + logArray[31].replace('"', '').split('/')[0]; let description = `</br>Timestamp: ${logArray[0].split(' ').slice(0, 3).join(' ')}</br> Device: ${logArray[0].split(' ').slice(3, 5).join(' ')}</br> Log Details: <ul><li>Event Time: ${logArray[1]}</li> <li>Log ID: ${logArray[2]}</li> <li>Type: ${logArray[3]}(${logArray[4]})</li> <li>Severity: ${logArray[34]}</li> <li>Rule Triggered: ${logArray[11]}</li> <li>Vulnerability: ${logArray[32]}</li> <li>Threat ID: ${logArray[34]}</li></ul> Network Information: <ul><li>Source IP: ${logArray[7]}</li> <li>Destination IP: ${logArray[8]}</li> <li>URL/filename : ${logArray[31]}</li> <li>VT : <a href="${vt_url}">${vt_url}</a></li> <li>Source Zone: ${logArray[16]}</li> <li>Destination Zone: ${logArray[17]}</li> <li>Ingress Interface: ${logArray[18]}</li> <li>Egress Interface: ${logArray[19]}</li></ul> Traffic Details: <ul><li>Protocol: ${logArray[29]}</li> <li>Application: ${logArray[14]}</li> <li>Direction: ${logArray[35]}</li> <li>Session ID: ${logArray[36]}</li></ul> Vulnerability Information:</br> <ul><li>Exploit Type: ${logArray[69]}</li> <li>Attack Vector: ${logArray[111]}</li> <li>Affected Technology: ${logArray[112]},${logArray[113]}</li> <li>Malware Potential:${malware_potential}</li> </ul>`; raw_alert += 1; acc.push(description); } } catch (error) { console.error(`Error:${error}`); } return acc; }, []); return alertInfo; } const alertInfo = parseLog(rawLog); function generateDescription() { const alertDescriptions = []; if (raw_alert < num_alert) { let extra_message = `<span class="red_highlight">Number Of Alert : ${num_alert}, Raw Log Alert : ${raw_alert} Raw log information is Not Complete, Please Get More Alert Information From Elastic.</span>\n`; alertDescriptions.push(extra_message); } for (const info of alertInfo) { let arr = summary.split(']'); let desc = `Observed ${arr[arr.length - 1]}\n`; if (typeof info == 'string') { desc += info; } else { Object.entries(info).forEach(([index, value]) => { if (value !== undefined && value !== '' && index !== 'Summary') { desc += `${index}: ${value}\n`; } }); } let comment = '\nPlease help to verify if this activity is legitimate.\n</br>'; if (summary.toLowerCase().includes('to malware ip(s)') || summary.toLowerCase().includes('to tor ip(s)')) { comment = '\nPlease verify if the IP is legitimate. If NOT, please block the dst ip\n'; } desc += comment; alertDescriptions.push(desc); } const alertMsg = [...new Set(alertDescriptions)].join('\n'); showDialog(alertMsg); } addButton('generateDescription', 'Description', generateDescription); } function ImpervaincCEFAlertHandler(...kwargs) { const { rawLog } = kwargs[0]; function parseCefLog(rawLog) { function cefToJson(cefLog) { let json = {}; let fields = cefLog.split(' '); for (let i = 0; i < fields.length; i++) { let field = fields[i].split('='); let key = field[0]; let value = field.slice(1).join('='); if (value) { if (key === 'filePath' || key === 'msg' || key === 'start' || key === 'rt' || key === 'cs1') { let nextFieldIndex = i + 1; while (nextFieldIndex < fields.length && !fields[nextFieldIndex].includes('=')) { value += ' ' + fields[nextFieldIndex]; nextFieldIndex++; } } if (value == 'n/a') { json[key] = undefined; } else { json[key] = value; } } } return json; } const alertInfo = rawLog.reduce((acc, log) => { try { // Determine whether the log is empty if (Object.keys(log).length !== 0) { // Split CEF log let cef_log = log.split('|'); let createtime = cef_log[0].split('CEF:')[0]; // Parsing CEF Header const cef_log_header = cef_log.slice(1, 7); // Parsing CEF Extends const cef_log_extends = cefToJson(cef_log[7]); acc.push({ summary: cef_log_extends.cs1, // for some like "server error" tickets createtime: createtime, username: cef_log_extends.duser, srcIP: cef_log_extends.src, dstIP: cef_log_extends.dst, dstPort: cef_log_extends.dpt, protocol: cef_log_extends.proto }); } return acc; } catch (error) { console.error(`Error: ${error.message}`); } }, []); return alertInfo; } const alertInfo = parseCefLog(rawLog); function generateDescription() { const alertDescriptions = []; for (const info of alertInfo) { const { summary } = info; let desc = `Observed ${summary}\n`; Object.entries(info).forEach(([index, value]) => { if (value !== undefined && index != 'summary' && index != 'CBlink') { desc += `${index}: ${value}\n`; } }); desc += `\nPlease verify if the activity is legitimate.\n`; alertDescriptions.push(desc); } const alertMsg = [...new Set(alertDescriptions)].join('\n'); showDialog(alertMsg); } addButton('generateDescription', 'Description', generateDescription); } function AzureGraphAlertHandler(...kwargs) { const { summary, rawLog } = kwargs[0]; var raw_alert = 0; if (summary.toLowerCase().includes('successful azure/o365 login from malware-ip')) { return; } function parseLog(rawLog) { const alertInfo = rawLog.reduce((acc, log) => { try { const { azure } = JSON.parse(log); let properties = {}; raw_alert += 1; if (azure.targetResources) { for (const resource of azure.targetResources) { if (summary.toLowerCase().includes('conditional access policy updated')) { const { initiatedBy, targetResources, activityDateTime, activityDisplayName, result } = azure; const alertExtraInfo = { userPrincipalName: initiatedBy?.user?.userPrincipalName ? initiatedBy?.user?.userPrincipalName : undefined, displayName: targetResources[0]?.displayName ? targetResources[0]?.displayName : undefined, activityDateTime: activityDateTime ? activityDateTime : undefined, activityDisplayName: activityDisplayName ? activityDisplayName : undefined, result: result ? result : undefined }; acc.push({ alertExtraInfo }); } else { if (resource.type == 'User') { const resourceProperties = { TargetUser: resource.userPrincipalName }; properties = { ...properties, ...resourceProperties }; } for (const prop of resource.modifiedProperties) { properties = { ...properties, [prop['displayName']]: prop['newValue'] }; } const activityDateTime = azure.activityDateTime.split('.')[0] + 'Z'; acc.push({ activityDateTime: activityDateTime, AppDisplayName: azure?.appDisplayName || azure?.initiatedBy?.app?.displayName, SourceUser: azure?.userPrincipalName || azure?.initiatedBy?.user?.userPrincipalName, IpAddress: azure?.ipAddress || azure?.initiatedBy?.user?.ipAddress, Location: azure?.location?.countryOrRegion && azure?.location?.state && azure?.location?.city ? `${azure?.location?.countryOrRegion}\\${azure?.location?.state}\\${azure?.location?.city}` : undefined, ...properties, Result: azure?.status?.failureReason || azure.result, AdditionalInfo: azure?.additionalDetails[0]?.value ? azure?.additionalDetails[0]?.value : undefined }); } } } else { const activityDateTime = azure.createdDateTime; acc.push({ activityDateTime: activityDateTime, AppDisplayName: azure?.appDisplayName || azure?.initiatedBy?.app?.displayName, SourceUser: azure?.userPrincipalName || azure?.initiatedBy?.user?.userPrincipalName, IpAddress: azure?.ipAddress || azure?.initiatedBy?.user?.ipAddress, Location: azure?.location?.countryOrRegion && azure?.location?.state && azure?.location?.city ? `${azure?.location?.countryOrRegion}\\${azure?.location?.state}\\${azure?.location?.city}` : undefined, ...properties, DeviceName: azure.deviceDetail.displayName || 'N/A', failureReason: azure?.status?.failureReason || azure.result }); } } catch (error) { console.log(`Error: ${error}`); } return acc; }, []); return alertInfo; } const alertInfo = parseLog(rawLog); const num_alert = $('#customfield_10300-val').text().trim(); function generateDescription() { const alertDescriptions = []; if (raw_alert < num_alert) { let extra_message = `<span class="red_highlight">Number Of Alert : ${num_alert}, Raw Log Alert : ${raw_alert} Raw log information is Not Complete, Please Get More Alert Information From Elastic.</span>\n`; alertDescriptions.push(extra_message); } if (summary.toLowerCase().includes('conditional access policy updated')) { for (const info of alertInfo) { console.log(info['alertExtraInfo']['userPrincipalName']); let desc = `Observed the user "${ info['alertExtraInfo']['userPrincipalName'] }" was on (<span class="red_highlight">GMT</span>)${ info['alertExtraInfo']['activityDateTime'].split('.')[0] }ZS Updated the conditional access policy "${info['alertExtraInfo']['displayName']}"\n\n`; for (const key in info.alertExtraInfo) { if (Object.hasOwnProperty.call(info.alertExtraInfo, key)) { const value = info.alertExtraInfo[key]; if ( value !== undefined && key != 'userPrincipalName' && key != 'displayName' && key != 'activityDateTime' ) { desc += `${key}: ${value}\n`; } } } desc += `\nIt is recommended that you verify that the user has permission to change the conditional access policy and that the action is a legitimate update known to the user. Thanks!\n`; alertDescriptions.push(desc); } } else { for (const info of alertInfo) { let desc = `Observed ${summary.split(']')[1]}\n`; console.log(info); for (const key in info) { if (Object.hasOwnProperty.call(info, key)) { const value = info[key]; if (value !== undefined && value !== '' && key != 'summary' && key != 'alerturi') { if (key == 'activityDateTime') { desc += `activityDateTime(<span class="red_highlight">GMT</span>): ${value}\n`; } else { desc += `${key}: ${value}\n`; } } } } desc += `\nPlease verify if the activity is legitimate.\n`; alertDescriptions.push(desc); } } const alertMsg = [...new Set(alertDescriptions)].join('\n'); showDialog(alertMsg); } addButton('generateDescription', 'Description', generateDescription); } function ProofpointAlertHandler(...kwargs) { const { summary, rawLog } = kwargs[0]; var raw_alert = 0; function parseLog(rawLog) { const alertInfo = rawLog.reduce((acc, log) => { try { const BraceIndex = log.toString().indexOf('{'); const lastBraceIndex = log.toString().lastIndexOf('}'); // If the braces are found if (BraceIndex !== -1) { raw_alert += 1; console.log(`${raw_alert} iteration 'is being processed`); // Intercepts a substring from the beginning of the brace to the end of the string json_text = log.toString().substr(BraceIndex, lastBraceIndex); try { let json_alert = JSON.parse(json_text); if (json_alert.hasOwnProperty('messagesDelivered')) { for (const message of json_alert['messagesDelivered']) { const { subject, sender, senderIP, recipient } = message; const alertExtraInfo = { subject: subject ? subject : undefined, sender: sender ? sender : undefined, recipient: recipient ? recipient : undefined, senderIP: senderIP ? senderIP : undefined }; acc.push({ alertExtraInfo }); } } else if (json_alert['sourcetype'].includes('clicksPermitted')) { json_alert['clickTime'] = json_alert['clickTime'].split('.')[0]; json_alert['threatTime'] = json_alert['threatTime'].split('.')[0]; acc.push({ alertExtraInfo: json_alert }); console.log('hellO'); } else { const { subject, sender, senderIP, recipient, headerFrom, messageTime, threatsInfoMap, sourcetype, spamScore, phishScore, cluster, completelyRewritten, id, QID, GUID } = json_alert; let alertExtraInfo = { sourcetype: sourcetype ? sourcetype : undefined, messageTime: messageTime ? messageTime : undefined, subject: subject ? subject : undefined, senderIP: senderIP ? senderIP : undefined, sender: sender ? sender : undefined, recipient: recipient ? recipient : undefined, headerFrom: headerFrom ? headerFrom : undefined, spamScore: spamScore ? spamScore : undefined, phishScore: phishScore ? phishScore : undefined, cluster: cluster ? cluster : undefined, completelyRewritten: completelyRewritten ? completelyRewritten : undefined, id: id ? id : undefined, QID: QID ? QID : undefined, GUID: GUID ? GUID : undefined }; alertExtraInfo = Object.assign({}, alertExtraInfo, threatsInfoMap[0]); acc.push({ alertExtraInfo }); } } catch (error) { console.log('Unable to parse JSON data, handling exception: ' + error); var split_str = json_text .split('"messagesDelivered" :')[1] .split('"messagesBlocked" :')[0] .slice(1, -2); const json_alerts = JSON.parse(split_str); for (const alert of json_alerts) { const { subject, sender, senderIP, recipient } = alert; console.log(subject, recipient); const alertExtraInfo = { subject: subject ? subject : undefined, sender: sender ? sender : undefined, recipient: recipient ? recipient : undefined, senderIP: senderIP ? senderIP : undefined }; acc.push({ alertExtraInfo }); } } } } catch (error) { console.log(`Error: ${error.message}`); } return acc; }, []); return alertInfo; } const alertInfo = parseLog(rawLog); const num_alert = $('#customfield_10300-val').text().trim(); console.log('reduce the methods iterated altogether' + num_alert + ' times'); function generateDescription() { const alertDescriptions = []; if (raw_alert < num_alert) { let extra_message = `<span class="red_highlight">Number Of Alert : ${num_alert}, Raw Log Alert : ${raw_alert} Raw log information is Not Complete, Please Get More Alert Information From Elastic.</span>\n`; alertDescriptions.push(extra_message); } for (const info of alertInfo) { let desc = `Observed ${summary.split(']')[1]}\n`; for (const key in info.alertExtraInfo) { if (Object.hasOwnProperty.call(info.alertExtraInfo, key)) { const value = info.alertExtraInfo[key]; if (value !== undefined) { if (key == 'messageTime' || key == 'clickTime' || key == 'threatTime') { desc += `${key}(<span class="red_highlight">GMT</span>): ${value.split('.')[0]}\n`; } else { desc += `${key}: ${value}\n`; } } } } desc += `\nPlease verify if the activity is legitimate.\n`; alertDescriptions.push(desc); } const alertMsg = [...new Set(alertDescriptions)].join('\n'); showDialog(alertMsg); } addButton('generateDescription', 'Description', generateDescription); } function ZscalerAlertHandler(...kwargs) { const { summary, rawLog } = kwargs[0]; var raw_alert = 0; function parseLog(rawLog) { const alertInfo = rawLog.reduce((acc, log) => { try { const BraceIndex = log.toString().indexOf('{'); const lastBraceIndex = log.toString().lastIndexOf('}'); // If the braces are found if (BraceIndex !== -1) { raw_alert += 1; // Intercepts a substring from the beginning of the brace to the end of the string json_text = log.toString().substr(BraceIndex, lastBraceIndex); const json_alert = JSON.parse(json_text); const { PrivateIP, PublicIP, Username, Customer, Hostname } = json_alert; const alertExtraInfo = { Hostname: Hostname ? Hostname : undefined, PublicIP: PublicIP ? PublicIP : undefined, PrivateIP: PrivateIP ? PrivateIP : undefined, Username: Username ? Username : undefined, Customer: Customer ? Customer : undefined }; acc.push({ alertExtraInfo }); } } catch (error) { console.log(`Error: ${error.message}`); } return acc; }, []); return alertInfo; } const alertInfo = parseLog(rawLog); const num_alert = $('#customfield_10300-val').text().trim(); function generateDescription() { const alertDescriptions = []; if (raw_alert < num_alert) { let extra_message = `<span class="red_highlight">Number Of Alert : ${num_alert}, Raw Log Alert : ${raw_alert} Raw log information is Not Complete, Please Get More Alert Information From Elastic.</span>\n`; alertDescriptions.push(extra_message); } for (const info of alertInfo) { let desc = `Observed ${summary.split(']')[1]}\n`; for (const key in info.alertExtraInfo) { if (Object.hasOwnProperty.call(info.alertExtraInfo, key)) { const value = info.alertExtraInfo[key]; if (value !== undefined) { desc += `${key}: ${value}\n`; } } } desc += `\nPlease verify if the ip is legitimate.\n`; alertDescriptions.push(desc); } const alertMsg = [...new Set(alertDescriptions)].join('\n'); //Can achieve automatic deduplication showDialog(alertMsg); } addButton('generateDescription', 'Description', generateDescription); } function PulseAlertHandler(...kwargs) { var { summary, rawLog } = kwargs[0]; var raw_alert = 0; if (rawLog == '') { var rawLog = $('#customfield_10219-val').text().trim().split('\n'); } function parseLog(rawLog) { const alertInfo = rawLog.reduce((acc, log) => { try { if (log.includes('PulseSecure')) { var firstIndex = log.indexOf('PulseSecure:'); let time_text = ''; if (summary.toLowerCase().includes('suspicious geolocation ip login success')) { time_text = log.toString().substr(0, firstIndex); } else { time_text = log.toString().substr(firstIndex + 13); const first_bar = time_text.indexOf(':'); time_text = time_text.toString().substr(0, first_bar + 6); } const lastIndex = log.toString().lastIndexOf('Vendor)'); let alert_text = log .toString() .substr(lastIndex + 7) .replace('[][] -', ''); const lastIndex_ = alert_text.toString().lastIndexOf(' - '); alert_text = alert_text.substr(lastIndex_ + 2); let first = log.indexOf('- '); let second = log.indexOf(' - ['); let vpn_name = log.toString().substring(first + 2, second) + ' '; const alert_content = '\n' + vpn_name + alert_text + ' On ' + time_text + '\n'; acc.push(alert_content); raw_alert += 1; } } catch (error) { console.log(`Error: ${error.message}`); } return acc; }, []); return alertInfo; } const alertInfo = parseLog(rawLog); const num_alert = $('#customfield_10300-val').text().trim(); function generateDescription() { const alertDescriptions = []; if (raw_alert < num_alert) { let extra_message = `<span class="red_highlight">Number Of Alert : ${num_alert}, Raw Log Alert : ${raw_alert} Raw log information is Not Complete, Please Get More Alert Information From Elastic.</span>\n`; alertDescriptions.push(extra_message); } let desc = `Observed ${summary.split(']')[1]}\n`; desc += alertInfo; desc += `\n\nPlease verify if the login is legitimate.\n`; alertDescriptions.push(desc); const alertMsg = [...new Set(alertDescriptions)].join('\n'); //Can achieve automatic deduplication showDialog(alertMsg); } addButton('generateDescription', 'Description', generateDescription); } function Risky_Countries_AlertHandler(...kwargs) { var { summary, rawLog } = kwargs[0]; function parseLog(rawLog) { const alertInfo = rawLog.reduce((acc, log) => { try { const json_alert = JSON.parse(log); if (json_alert.hasOwnProperty('azure')) { const { createdDateTime, userDisplayName, userPrincipalName, ipAddress, appDisplayName, deviceDetail, status } = json_alert['azure']; const { failureReason, additionalDetails } = status; const { displayName, operatingSystem } = deviceDetail; const alertExtraInfo = { createdEventDateTime: createdDateTime ? createdDateTime : undefined, userDisplayName: userDisplayName ? userDisplayName : undefined, userPrincipalName: userPrincipalName ? userPrincipalName : undefined, appDisplayName: appDisplayName ? appDisplayName : undefined, ipAddress: ipAddress ? ipAddress : undefined, operatingSystem: operatingSystem ? operatingSystem : undefined, DeviceName: displayName ? displayName : 'N/A', failureReason: failureReason ? failureReason : undefined, additionalDetails: additionalDetails ? additionalDetails : undefined }; acc.push({ alertExtraInfo }); } if (json_alert.hasOwnProperty('office_365')) { let alertExtraInfo; if (json_alert['office_365'].hasOwnProperty('Data')) { console.log(JSON.parse(json_alert['office_365']['Data'])); let data = JSON.parse(json_alert['office_365']['Data']); alertExtraInfo = { CreationEventTime: data['wsrt'] ? data['wsrt'] : undefined, Username: data['f3u'] ? data['f3u'] : undefined, Workload: data['wl'] ? data['wl'] : undefined, Reason: data['ad'] ? data['ad'] : undefined }; } else if (!json_alert['office_365'].hasOwnProperty('ClientIP')) { let data = json_alert['office_365']; alertExtraInfo = { CreationEventTime: data['CreationTime'] ? data['CreationTime'] : undefined, Operation: data['Operation'] ? data['Operation'] : undefined, ResultStatus: data['ResultStatus'] ? data['ResultStatus'] : undefined, UserId: data['UserId'] ? data['UserId'] : undefined, ObjectId: data['ObjectId'] ? data['ObjectId'] : undefined, UserKey: data['UserKey'] ? data['UserKey'] : undefined }; } else { const { CreationTime, Operation, Workload, ClientIP, UserId, ResultStatusDetail, UserAgent, ActorIpAddress, DeviceProperties, UserKey } = json_alert['office_365']; let devicename = ''; DeviceProperties.forEach((item) => { if (item.Name === 'DisplayName') { devicename = item.Value; } }); alertExtraInfo = { CreationEventTime: CreationTime ? CreationTime : undefined, Operation: Operation ? Operation : undefined, Workload: Workload ? Workload : undefined, UserId: UserId ? UserId : undefined, ClientIP: ClientIP ? ClientIP : undefined, ActorIpAddress: ActorIpAddress ? ActorIpAddress : undefined, UserAgent: UserAgent ? UserAgent : undefined, DeviceName: devicename ? devicename : 'N/A', UserKey: UserKey ? UserKey : undefined, ResultStatusDetail: ResultStatusDetail ? ResultStatusDetail : undefined }; } acc.push({ alertExtraInfo }); } } catch (error) { console.log(`Error: ${error.message}`); } return acc; }, []); return alertInfo; } const alertInfo = parseLog(rawLog); function generateDescription() { const alertDescriptions = []; console.log(alertInfo); for (const info of alertInfo) { const lastindex = summary.lastIndexOf(']'); let desc = `Observed ${summary.substr(lastindex + 1)}\n`; for (const key in info.alertExtraInfo) { if (Object.hasOwnProperty.call(info.alertExtraInfo, key)) { const value = info.alertExtraInfo[key]; if (value !== undefined) { if (key == 'CreationEventTime') { desc += `CreationEventTime(<span class="red_highlight">GMT</span>): ${value}\n`; } else { desc += `${key}: ${value}\n`; } } } } desc += `\nPlease verify if the activity is legitimate.\n`; alertDescriptions.push(desc); } const alertMsg = [...new Set(alertDescriptions)].join('\n'); showDialog(alertMsg); } addButton('generateDescription', 'Description', generateDescription); } function Agent_Disconnect_AlertHandler(...kwargs) { var { summary, rawLog } = kwargs[0]; const LogSource = $('#customfield_10204-val').text().trim().split('\n'); function parseLog(LogSource) { const alertInfo = LogSource.reduce((acc, log) => { try { log = log.replace(/\s/g, ''); if (log == 'Show' || log == 'Hide' || log.length == 0) { console.log('ss'); } else { acc.push(log); console.log(log); } } catch (error) { console.log(`Error: ${error.message}`); } return acc; }, []); return alertInfo; } let alertInfo = [...new Set(parseLog(LogSource))]; function generateDescription() { const alertDescriptions = []; const lastindex = summary.lastIndexOf(']'); let desc = `Observed ${summary.substr(lastindex + 1)}, kindly please help to check it.\n`; desc += `\nagent name: ${alertInfo.join(',')}`; alertDescriptions.push(desc); const alertMsg = [...new Set(alertDescriptions)].join('\n'); showDialog(alertMsg); } function openMDE() { let KQL = ''; KQL += `name=${alertInfo.join(' or name=')} \n`; showFlag('info', 'KQL:', `${KQL}`, 'manual'); } addButton('generateDescription', 'Description', generateDescription); addButton('openKQL', 'KQL', openMDE); } function MdbAlertHandler(...kwargs) { var { summary, rawLog } = kwargs[0]; if (rawLog.length == 0 || rawLog.length == 1) { rawLog = $('#customfield_10219-val').text().trim().split('\n'); } function parseLog(rawLog) { const alertInfo = rawLog.reduce((acc, log) => { try { if (log.length == 0) { return acc; } if (summary.toLowerCase().includes('syslog: user missed the password more than one time')) { let log_ = log.split(';')[1].split(' '); let time_host = log.split(' sshd')[0].split(' '); let user = ''; if (log_.length > 7) { user = log_[8].split('=')[1]; } let description = `Observed user<span class='black_highlight'> ${user}</span> multiple ssh login failed from ${ log_[6].split('=')[1] }\nCreateTime: ${time_host .slice(0, time_host.length - 1) .join(' ')}\nHostname: <span class='black_highlight'> ${ time_host[time_host.length - 1] }</span>\n`; acc.push(description); } if (summary.toLowerCase().includes('sshd: insecure connection attempt')) { let log_ = log.split(' '); console.log('log', log_); let description = `Observed insecure connection attempt from ${ log_[log_.length - 3] }\nCreateTime: ${log_.slice(0, log_.length - 11).join(' ')}\n`; acc.push(description); } if ( summary .toLowerCase() .includes('anomaly: suspected lateral movement - linux containing session opened') ) { let log_ = log.split('>')[1] + '\n'; console.log('log', log_); acc.push(log_); } } catch (error) { console.log(`Error: ${error.message}`); } return acc; }, []); return alertInfo; } const alertInfo = parseLog(rawLog); function generateDescription() { const alertDescriptions = []; if (summary.toLowerCase().includes('anomaly: suspected lateral movement - linux containing session opened')) { const Log_source = $('#customfield_10204-val').text().trim(); alertDescriptions.push(`Observed session opened on <span class='black_highlight'>${Log_source}</span>\n`); } for (const info of alertInfo) { alertDescriptions.push(info); } if (summary.toLowerCase().includes('sshd: insecure connection attempt')) { alertDescriptions.push('Kindly help to verify if the connection is legitimate\n'); } if (summary.toLowerCase().includes('syslog: user missed the password more than one time')) { alertDescriptions.push('Kindly help to verify if the login is legitimate\n'); } if (summary.toLowerCase().includes('anomaly: suspected lateral movement - linux containing session opened')) { alertDescriptions.push('Kindly help to verify if the session is legitimate\n'); } const alertMsg = [...new Set(alertDescriptions)].join('\n'); showDialog(alertMsg); } addButton('generateDescription', 'Description', generateDescription); } function AlicloudAlertHandler(...kwargs) { var { summary, rawLog } = kwargs[0]; var raw_alert = 0; function parseLog(rawLog) { const alertInfo = rawLog.reduce((acc, log) => { try { const BraceIndex = log.toString().indexOf('{'); const lastBraceIndex = log.toString().lastIndexOf('}'); if (BraceIndex !== -1) { raw_alert += 1; // Intercepts a substring from the beginning of the brace to the end of the string json_text = log.toString().substr(BraceIndex, lastBraceIndex); let time_1 = log.toString().substr(0, BraceIndex).split(' '); let time = time_1.slice(time_1.length - 4, time_1.length - 2).join(' '); time = time_1[0] + ' ' + time; try { const json_alert = JSON.parse(json_text); let { eventId, uuid, eventName, resourceName, sourceIpAddress, userIdentity, intranet_ip, internet_ip, instance_id, extend_content, detail, requestParameters, responseElements } = json_alert['alicloud']; let alertExtraInfo = { createTime: time, eventId: eventId ? eventId : undefined, uuid: uuid ? uuid : undefined, eventName: eventName ? eventName : undefined, InstanceId: resourceName ? resourceName : undefined, sourceIpAddress: sourceIpAddress ? sourceIpAddress : undefined, userName: userIdentity?.userName ? userIdentity?.userName : undefined, internet_ip: internet_ip ? internet_ip : undefined, intranet_ip: intranet_ip ? intranet_ip : undefined, instance_id: instance_id ? instance_id : undefined, extend_content: extend_content ? extend_content : undefined, responseElements: responseElements ? JSON.stringify(responseElements) : undefined }; console.log('===', requestParameters, time); if (detail != undefined) { detail = JSON.parse(detail); alertExtraInfo = Object.assign({}, alertExtraInfo, detail); } if (requestParameters != undefined) { alertExtraInfo = Object.assign({}, alertExtraInfo, requestParameters); } console.log(alertExtraInfo); acc.push({ alertExtraInfo }); } catch (error) { console.log('Unable to parse JSON data, handling exception: ' + error); } } } catch (error) { console.log(`Error: ${error.message}`); } return acc; }, []); return alertInfo; } const alertInfo = parseLog(rawLog); function generateDescription() { const alertDescriptions = []; for (const info of alertInfo) { const lastindex = summary.lastIndexOf(']'); let desc = `Observed ${summary.substr(lastindex + 1)}\n`; for (const key in info.alertExtraInfo) { if (Object.hasOwnProperty.call(info.alertExtraInfo, key)) { const value = info.alertExtraInfo[key]; if (value !== undefined) { desc += `${key}: ${value}\n`; } } } desc += `\nPlease verify if the activity is legitimate.\n`; alertDescriptions.push(desc); } const alertMsg = [...new Set(alertDescriptions)].join('\n'); showDialog(alertMsg); } addButton('generateDescription', 'Description', generateDescription); } function DstAlertHandler(...kwargs) { var rawLog = $('#field-customfield_10904').text().trim().split('\n'); function parseLog(rawLog) { const alertInfo = rawLog.reduce((acc, log) => { try { const json_alert = JSON.parse(log); const { system, eventdata } = json_alert['win']; const alertExtraInfo = { computer: system?.computer ? system?.computer : undefined, commandLine: eventdata?.commandLine ? eventdata?.commandLine : undefined }; acc.push({ alertExtraInfo }); } catch (error) { console.log(`Error: ${error.message}`); } return acc; }, []); return alertInfo; } const alertInfo = parseLog(rawLog); function generateDescription() { const alertDescriptions = []; for (const info of alertInfo) { let desc = ``; for (const key in info.alertExtraInfo) { if (Object.hasOwnProperty.call(info.alertExtraInfo, key)) { const value = info.alertExtraInfo[key]; if (value !== undefined) { desc += `${key}: ${value}\n`; } } } alertDescriptions.push(desc); } const alertMsg = [...new Set(alertDescriptions)].join('\n'); showDialog(alertMsg); } addButton('generateDescription', 'Description', generateDescription); } function ThreatMatrixAlertHandler(...kwargs) { var { summary, rawLog } = kwargs[0]; function parseLog(rawLog) { const alertInfo = rawLog.reduce((acc, log) => { try { const json_alert = JSON.parse(log); console.log(json_alert['threatmatrix']); const { account_telephone, account_login, application_name, customer_event_type, input_ip_address, event_datetime, input_ip_city, input_ip_geo, input_ip_isp, input_ip_organization, policy, tmx_risk_rating, request_result } = json_alert['threatmatrix']; const alertExtraInfo = { account_telephone: account_telephone ? account_telephone : undefined, account_login: account_login ? account_login : undefined, application_name: application_name ? application_name : undefined, customer_event_type: customer_event_type ? customer_event_type : undefined, input_ip_address: input_ip_address ? input_ip_address : undefined, input_ip_city: input_ip_city ? input_ip_city : undefined, input_ip_geo: input_ip_geo ? input_ip_geo : undefined, input_ip_isp: input_ip_isp ? input_ip_isp : undefined, input_ip_organization: input_ip_organization ? input_ip_organization : undefined, policy: policy ? policy : undefined, tmx_risk_rating: tmx_risk_rating ? tmx_risk_rating : undefined, request_result: request_result ? request_result : undefined, event_datetime: event_datetime ? event_datetime.split('.')[0] : undefined }; acc.push({ alertExtraInfo }); } catch (error) { console.log(`Error: ${error.message}`); } return acc; }, []); return alertInfo; } const alertInfo = parseLog(rawLog); function generateDescription() { const alertDescriptions = []; for (const info of alertInfo) { const lastindex = summary.lastIndexOf(']'); let desc = `Observed ${summary.substr(lastindex + 1)}\n`; for (const key in info.alertExtraInfo) { if (Object.hasOwnProperty.call(info.alertExtraInfo, key)) { const value = info.alertExtraInfo[key]; if (value !== undefined) { desc += `${key}: ${value}\n`; } } } desc += `\nPlease verify if the login is legitimate.\n`; alertDescriptions.push(desc); } const alertMsg = [...new Set(alertDescriptions)].join('\n'); showDialog(alertMsg); } addButton('generateDescription', 'Description', generateDescription); } function DarktraceAlertHandler(...kwargs) { var { summary, rawLog } = kwargs[0]; var raw_alert = 0; var breach_Url; function parseLog(rawLog) { const alertInfo = rawLog.reduce((acc, log) => { try { const BraceIndex = log.toString().indexOf('{'); const lastBraceIndex = log.toString().lastIndexOf('}'); const logarray = log.toString().split(' '); if (BraceIndex !== -1) { raw_alert += 1; // Intercepts a substring from the beginning of the brace to the end of the string json_text = log.toString().substr(BraceIndex, lastBraceIndex); const json_alert = JSON.parse(json_text); let alertExtraInfo = {}, Resource_paths = []; breach_Url = json_alert['breachUrl'] + '<br>' + json_alert['incidentEventUrl']; let year = ' 20' + $('#created-val').text().trim().split('/')[2].split(' ')[0]; //动态产生工单的年份 let time_str = logarray.slice(0, 3).join(' ') + year; if (!time_str.includes(':')) { time_str = logarray.slice(0, 4).join(' ').replace(' ', ' ') + year; } if (json_alert.hasOwnProperty('model')) { const { device, triggeredComponents, model } = json_alert; let User_agent = '', Message; alertExtraInfo = { AlertTime: formatCurrentDateTime(time_str), hostname: device?.hostname ? device?.hostname : undefined, ip: device?.ip ? device?.ip : undefined, credentials: device?.credentials ? device?.credentials : undefined, subnetlabel: device?.ips ? device?.ips[0].subnetlabel : undefined, typename: device?.typename ? device?.typename : undefined, User_agent: User_agent ? User_agent : undefined, saas_info: device?.customFields?.saasinfo ? device.customFields.saasinfo.saas_info : undefined, Message: Message ? Message : undefined, description: model?.description ? model?.description.replace(/\\\n/g, ' ') : undefined }; triggeredComponents[0]['triggeredFilters'].forEach((item) => { if (item['filterType'] == 'User agent' && item['id'] == 'O') { User_agent = item['arguments']['value']; console.log('value', item['arguments']['value']); } else if (item['id'] == 'C') { Message = item['trigger']['value']; } else if ( item['filterType'].includes('IP') || item['filterType'] == 'Resource Location' || item['filterType'] == 'Event' || item['filterType'] == 'Connection hostname' ) { alertExtraInfo[item['filterType']] = item['trigger']['value']; } }); } else { const { summary, breachDevices, details } = json_alert; let values; alertExtraInfo = { AlertTime: formatCurrentDateTime(time_str), hostname: breachDevices[0]?.hostname ? breachDevices[0]?.hostname : undefined, host_ip: breachDevices[0]?.ip ? breachDevices[0]?.ip : undefined, summary: summary ? summary : undefined }; details.forEach((item) => { if (item[0].header == 'Endpoint Details') { values = item[0].contents[0].values; item[0].contents.forEach((i) => { if (i.key == 'IP addresses associated with hostnames') { console.log(i); alertExtraInfo[i.type] = JSON.stringify(i.values); } }); } item.forEach((ii) => { if ( ii.header == 'Activity Details' || ii.header == 'Details of Accessing Users' || ii.header == 'Resource Access Details' ) { ii.contents.forEach((i) => { if (i['key'] == 'Resource paths include' || i['key'] == 'Resource path') { i['values'].forEach((iii) => { Resource_paths.push(iii); }); } else if ( i['key'].includes('Source IPs') || i['key'].includes('Actors include') ) { alertExtraInfo[i.key] = JSON.stringify(i.values); } }); } }); }); Resource_paths = [...new Set(Resource_paths)].join('\n'); alertExtraInfo['Resource_paths'] = Resource_paths ? Resource_paths : undefined; alertExtraInfo['Endpoint Details'] = values ? values : undefined; } acc.push({ alertExtraInfo }); } } catch (error) { console.log(`Error: ${error.message}`); } return acc; }, []); return alertInfo; } const alertInfo = parseLog(rawLog); const num_alert = $('#customfield_10300-val').text().trim(); function generateDescription() { const alertDescriptions = []; if (raw_alert < num_alert) { let extra_message = `<span class="red_highlight">Number Of Alert : ${num_alert}, Raw Log Alert : ${raw_alert} Raw log information is Not Complete, Please Get More Alert Information From Elastic.</span>\n`; alertDescriptions.push(extra_message); } for (const info of alertInfo) { const lastindex = summary.lastIndexOf(']'); let ss = summary.substr(lastindex + 1).split('::'); let desc = `Observed ${ss[ss.length - 1]}\n\n`; for (const key in info.alertExtraInfo) { if (Object.hasOwnProperty.call(info.alertExtraInfo, key)) { const value = info.alertExtraInfo[key]; if (value !== undefined) { desc += `${key}: ${value}\n`; } } } desc += `\nPlease help to verify if this activity is legitimate.\n`; alertDescriptions.push(desc); } const alertMsg = [...new Set(alertDescriptions)].join('\n'); showDialog(alertMsg); } function breachUrl() { showFlag('info', 'breach Url:', `${breach_Url.replace('hXXps[:]', 'https:')}`, 'manual'); } addButton('generateDescription', 'Description', generateDescription); addButton('breachUrl', 'breachUrl', breachUrl); } function SangforAlertHandler(...kwargs) { var { summary, rawLog } = kwargs[0]; function parseLog(rawLog) { const alertInfo = rawLog.reduce((acc, log) => { try { if (log.length == 0) { return acc; } const regex = /(\b\w+=)([^=\s].*?)(?=\s+\w+=|$)/g; let match; const matches = {}; while ((match = regex.exec(log)) !== null) { let item = match[0].split('='); matches[item[0]] = item.slice(1, item.length).join('='); } console.log(matches); var pattern = /event_evidence.*?(?=suffer_classify1_id_name)/g; console.log(log.match(pattern)); let logArray = log.split(' ').filter((item) => item !== ''); //Remove extra whitespace from the string const DecoderName = $('#customfield_10807-val').text().trim().toLowerCase(); if (DecoderName == 'cyberark_cef') { let data_json = { 'Event time': logArray.slice(0, 3).join(' '), 'event_desc': matches.event_desc ? matches.event_desc : undefined, 'dhost': matches.dhost ? matches.dhost : undefined, 'dst': matches.dst ? matches.dst : undefined, 'duser': matches.duser ? matches.duser : undefined, 'shost': matches.shost ? matches.shost : undefined, 'src': matches.src ? matches.src : undefined, 'suser': matches.suser ? matches.suser : undefined }; data_json[matches.cs3Label] = matches.cs3 ? matches.cs3 : undefined; acc.push(data_json); } else if (DecoderName == 'trellix_cef') { let data_json = { filePath: matches.filePath ? matches.filePath : undefined, rt: matches.rt ? matches.rt : undefined, duser: matches.duser ? matches.duser : undefined, msg: matches.msg ? matches.msg : undefined, act: matches.act ? matches.act : undefined, suser: matches.suser ? matches.suser.replace(/[<>]/g, '') : undefined, fileType: matches.fileType ? matches.fileType : undefined, subject: matches.subject ? matches.subject : undefined }; data_json[matches.cs1Label] = matches.cs1 ? matches.cs1 : undefined; data_json[matches.cs4Label] = matches.cs4 ? matches.cs4 : undefined; data_json[matches.flexString2Label] = matches.flexString2 ? matches.flexString2 : undefined; acc.push(data_json); } else if (DecoderName == 'impervainc_cef') { console.log('===', matches); console.log('===start ', formatCurrentDateTime(parseInt(matches.start), 'impervainc_cef')); let data_json = { start_time: matches.start ? formatCurrentDateTime(parseInt(matches.start), 'impervainc_cef') : undefined, end_time: matches.end ? formatCurrentDateTime(parseInt(matches.end), 'impervainc_cef') : undefined, dhost: matches.dhost ? matches.dhost : undefined, AlertTime: matches.rt ? matches.rt : undefined, src: matches.src ? matches.src : undefined, sptPort: matches.spt ? matches.spt : undefined, dstIP: matches.dst ? matches.dst : undefined, dstPort: matches.dpt ? matches.dpt : undefined, protocol: matches.proto ? matches.proto : undefined, request: matches.request ? matches.request : undefined, requestClientApplication: matches.requestClientApplication ? matches.requestClientApplication : undefined, msg: matches.msg ? matches.msg : undefined }; data_json[matches.cs1Label] = matches.cs1 ? matches.cs1 : undefined; data_json[matches.cs2Label] = matches.cs2 ? matches.cs2 : undefined; data_json[matches.cs3Label] = matches.cs3 ? matches.cs3 : undefined; data_json[matches.cs4Label] = matches.cs4 ? matches.cs4 : undefined; data_json[matches.cs5Label] = matches.cs5 ? matches.cs5 : undefined; data_json[matches.cs6Label] = matches.cs6 ? matches.cs6 : undefined; data_json[matches.cs7Label] = matches.cs7 ? matches.cs7 : undefined; data_json[matches.cs8Label] = matches.cs8 ? matches.cs8 : undefined; data_json[matches.cs9Label] = matches.cs9 ? matches.cs9 : undefined; acc.push(data_json); } else if (DecoderName == 'checkpoint_cef') { let data_json = { Signature: matches.Signature ? matches.Signature : undefined, cp_severity: matches.cp_severity ? matches.cp_severity : undefined, src: matches.src ? matches.src : undefined, dst: matches.dst ? matches.dst : undefined, origin: matches.origin ? matches.origin : undefined }; data_json[matches.cs2Label] = matches.cs2 ? matches.cs2 : undefined; data_json[matches.cs3Label] = matches.cs3 ? matches.cs3 : undefined; data_json[matches.cs4Label] = matches.cs4 ? matches.cs4 : undefined; data_json[matches.flexNumber1Label] = matches.flexNumber1 ? matches.flexNumber1 : undefined; data_json[matches.flexNumber2Label] = matches.flexNumber2 ? matches.flexNumber2 : undefined; data_json[matches.flexString2Label] = matches.flexString2 ? matches.flexString2 : undefined; acc.push(data_json); } else if (DecoderName == 'incapsula_cef') { let data_json = { requestClientApplication: matches.requestClientApplication ? matches.requestClientApplication : undefined, request: matches.request ? matches.request : undefined, requestMethod: matches.requestMethod ? matches.requestMethod : undefined, postbody: matches.postbody ? matches.postbody : undefined, qstr: matches.qstr ? matches.qstr : undefined, act: matches.act ? matches.act : undefined, sip: matches.sip ? matches.sip : undefined, spt: matches.spt ? matches.spt : undefined, xff: matches.xff ? matches.xff : undefined, cpt: matches.cpt ? matches.cpt : undefined, src: matches.src ? matches.src : undefined }; data_json[matches.cs9Label] = matches.cs9 ? matches.cs9 : undefined; acc.push(data_json); } else if (window.location.href.includes('macaumss')) { acc.push({ 'Event time': logArray.slice(0, 3).join(' '), 'event_desc': matches.event_desc ? matches.event_desc : undefined, 'dev_name': matches.dev_name ? matches.dev_name : undefined, 'attack_ip': matches.attack_ip ? matches.attack_ip : undefined, 'suffer_ip': matches.suffer_ip ? matches.suffer_ip : undefined, 'suffer_port': matches.suffer_port ? matches.suffer_port : undefined, 'status_code': matches.status_code ? matches.status_code : undefined, 'x_forwarded_for': matches.x_forwarded_for ? matches.x_forwarded_for : undefined, 'event_evidence': log.match(pattern) ? log.match(pattern)[0] : undefined, 'attack_type_name': matches.attack_type_name ? matches.attack_type_name : undefined }); } else { acc.push({ 'Event time': logArray.slice(0, 3).join(' '), 'event_desc': matches.event_desc ? matches.event_desc : undefined, 'dev_name': matches.dev_name ? matches.dev_name : undefined, 'suffer_ip': matches.suffer_ip ? matches.suffer_ip : undefined, 'attack_ip': matches.attack_ip ? matches.attack_ip : undefined, 'event_evidence': matches.event_evidence ? matches.event_evidence : undefined, 'url': matches.url ? matches.url : undefined, 'suggest': matches.suggest ? matches.suggest : undefined }); } } catch (error) { console.log(`Error: ${error.message}`); } return acc; }, []); return alertInfo; } const alertInfo = parseLog(rawLog); function generateDescription() { const alertDescriptions = []; for (const info of alertInfo) { const lastindex = summary.lastIndexOf(']'); let desc; if (summary.includes('-')) { desc = `Observed ${summary.substr(lastindex + 1).split('-')[1]}\n`; } else { desc = `Observed ${summary.substr(lastindex + 1)}\n`; } for (const key in info) { if (Object.hasOwnProperty.call(info, key)) { const value = info[key]; if (value !== undefined) { if (key == 'event_evidence') { desc += `${key}: ${value.replace(/</g, '<').replace(/>/g, '>')}\n`; } else if (key == 'start_time' || key == 'end_time' || key == 'AlertTime') { desc += `${key}(<span class="red_highlight">GMT+8</span>): ${value.split('.')[0]}\n`; } else { desc += `${key}: ${value}\n`; } } } } desc += `\nPlease verify if the activity is legitimate.\n`; alertDescriptions.push(desc); } const alertMsg = [...new Set(alertDescriptions)].join('\n'); showDialog(alertMsg); } addButton('generateDescription', 'Description', generateDescription); } function RadwareAlertHandler(...kwargs) { var { summary, rawLog } = kwargs[0]; function parseLog(rawLog) { const alertInfo = rawLog.reduce((acc, log) => { try { const json_alert = JSON.parse(log); const { device_ip, device_name, device_abbr, detected_by, asset_name, asset_type, asset_ip, account_uid, account_name, acc_site_name, end_time, start_time } = json_alert['radware']; alertExtraInfo = { start_time: start_time._date_time ? start_time._date_time : undefined, end_time: end_time._date_time ? end_time._date_time : undefined, device_ip: device_ip ? device_ip : undefined, device_name: device_name ? device_name : undefined, device_abbr: device_abbr ? device_abbr : undefined, detected_by: detected_by ? detected_by : undefined, asset_name: asset_name ? asset_name : undefined, asset_type: asset_type ? asset_type : undefined, asset_ip: asset_ip ? asset_ip : undefined, account_uid: account_uid ? account_uid : undefined, account_name: account_name ? account_name : undefined, acc_site_name: acc_site_name ? acc_site_name : undefined }; acc.push({ alertExtraInfo }); } catch (error) { console.log(`Error: ${error.message}`); } return acc; }, []); return alertInfo; } const alertInfo = parseLog(rawLog); function generateDescription() { const alertDescriptions = []; for (const info of alertInfo) { const lastindex = summary.lastIndexOf(']'); let desc = `Observed ${summary.substr(lastindex + 1)}\n`; for (const key in info.alertExtraInfo) { if (Object.hasOwnProperty.call(info.alertExtraInfo, key)) { const value = info.alertExtraInfo[key]; if (value !== undefined) { if (key == 'start_time' || key == 'end_time') { desc += `${key}(<span class="red_highlight">GMT</span>): ${value.split('.')[0] + 'Z'}\n`; } else { desc += `${key}: ${value}\n`; } } } } desc += `\nPlease verify if the activity is legitimate.\n`; alertDescriptions.push(desc); } const alertMsg = [...new Set(alertDescriptions)].join('\n'); showDialog(alertMsg); } addButton('generateDescription', 'Description', generateDescription); } function CarbonAlertHandler(...kwargs) { var { summary, rawLog } = kwargs[0]; var raw_alert = 0; const num_alert = $('#customfield_10300-val').text().trim(); function parseLog(rawLog) { const alertInfo = rawLog.reduce((acc, log) => { try { const BraceIndex = log.toString().indexOf('{'); const lastBraceIndex = log.toString().lastIndexOf('}'); if (BraceIndex !== -1) { json_text = log.toString().substr(BraceIndex, lastBraceIndex); const json_alert = JSON.parse(json_text); const { reason, device_os_version, device_username, device_location, device_external_ip, device_internal_ip, device_name, process_pid, process_name, process_sha256, process_guid, process_cmdline, process_username, netconn_remote_ip, netconn_remote_port, parent_guid, parent_pid, parent_name, parent_sha256, parent_username, netconn_local_ip, netconn_local_port, first_event_timestamp } = json_alert; alertExtraInfo = { EventTime: first_event_timestamp.split('.')[0], device_name: device_name ? device_name : undefined, device_os_version: device_os_version ? device_os_version : undefined, device_username: device_username ? device_username : undefined, device_location: device_location ? device_location : undefined, device_external_ip: device_external_ip ? device_external_ip : undefined, device_internal_ip: device_internal_ip ? device_internal_ip : undefined, process_guid: process_guid ? process_guid : undefined, process_pid: process_pid ? process_pid : undefined, process_name: process_name ? process_name : undefined, process_sha256: process_sha256 ? process_sha256 : undefined, process_cmdline: process_cmdline ? process_cmdline : undefined, process_username: process_username ? process_username : undefined, parent_guid: parent_guid ? parent_guid : undefined, parent_pid: parent_pid ? parent_pid : undefined, parent_name: parent_name ? parent_name : undefined, parent_sha256: parent_sha256 ? parent_sha256 : undefined, parent_username: parent_username ? parent_username : undefined, netconn_remote_ip: netconn_remote_ip ? netconn_remote_ip : undefined, netconn_remote_port: netconn_remote_port ? netconn_remote_port : undefined, netconn_local_ip: netconn_local_ip ? netconn_local_ip : undefined, netconn_local_port: netconn_local_port ? netconn_local_port : undefined, reason: reason ? reason : undefined }; raw_alert += 1; acc.push({ alertExtraInfo }); } } catch (error) { console.log(`Error: ${error.message}`); } return acc; }, []); return alertInfo; } const alertInfo = parseLog(rawLog); function generateDescription() { const alertDescriptions = []; if (raw_alert < num_alert) { let extra_message = `<span class="red_highlight">Number Of Alert : ${num_alert}, Raw Log Alert : ${raw_alert} Raw log information is Not Complete, Please Get More Alert Information From Elastic.</span>\n`; alertDescriptions.push(extra_message); } for (const info of alertInfo) { const lastindex = summary.lastIndexOf(']'); let desc = `Observed ${summary.substr(lastindex + 1)}\n`; for (const key in info.alertExtraInfo) { if (Object.hasOwnProperty.call(info.alertExtraInfo, key)) { const value = info.alertExtraInfo[key]; if (key == 'EventTime') { desc += `EventTime(<span class="red_highlight">GMT</span>): ${value + 'Z'}\n`; } else if (value !== undefined) { desc += `${key}: ${value}\n`; } } } desc += `\nPlease verify if the activity is legitimate.\n`; alertDescriptions.push(desc); } const alertMsg = [...new Set(alertDescriptions)].join('\n'); showDialog(alertMsg); } addButton('generateDescription', 'Description', generateDescription); } function MultipleAccountAlertHandler(...kwargs) { var { summary, rawLog } = kwargs[0]; function parseLog(rawLog) { const alertInfo = rawLog.reduce((acc, log) => { try { const json_alert = JSON.parse(log)['win']; const { targetUserName, targetDomainName, subjectUserName, subjectDomainName, subjectLogonId } = json_alert['eventdata']; const { systemTime, computer, message } = json_alert['system']; alertExtraInfo = { Eventtime: systemTime ? systemTime : undefined, computer: computer ? computer : undefined, targetUserName: targetUserName ? targetUserName : undefined, targetDomainName: targetDomainName ? targetDomainName : undefined, subjectUserName: subjectUserName ? subjectUserName : undefined, subjectDomainName: subjectDomainName ? subjectDomainName : undefined, message: message ? message.split('\r\n\r\n')[0] : undefined }; acc.push({ alertExtraInfo }); } catch (error) { console.log(`Error: ${error.message}`); } return acc; }, []); return alertInfo; } const alertInfo = parseLog(rawLog); function generateDescription() { const alertDescriptions = []; const single = []; const lastindex = summary.lastIndexOf(']'); let desc = `Observed ${summary.substr(lastindex + 1)}\n`; for (const info of alertInfo) { let desc_ = '', single_ = ''; for (const key in info.alertExtraInfo) { if (Object.hasOwnProperty.call(info.alertExtraInfo, key)) { const value = info.alertExtraInfo[key]; if (value !== undefined) { if (key == 'Eventtime') { desc_ += `${key}(<span class="red_highlight">GMT</span>): ${value.split('.')[0] + 'Z'}\n`; } else if ( key == 'subjectUserName' || key == 'subjectDomainName' || key == 'computer' || key == 'message' || key == 'targetDomainName' ) { single_ += `${key}: ${value}\n`; } else { desc_ += `${key}: ${value}\n`; } } } } alertDescriptions.push(desc_); single.push(single_); } desc += [...new Set(single)].join('\n'); desc += '\n'; desc += [...new Set(alertDescriptions)].join('\n'); desc += `Please verify if the activity is legitimate.\n`; showDialog(desc); } addButton('generateDescription', 'Description', generateDescription); } /** * Create Description and Open MDE and MDE365 button * @param {...any} kwargs - Include LogSourceDomain, Labels, LogSource, TicketAutoEscalate, Status, RawLog, Summary fields */ function MDE365AlertHandler(...kwargs) { console.log('#### Code MDE365lertHandler run ####'); const { rawLog, LogSourceDomain, summary } = kwargs[0]; var raw_alert = 0; const num_alert = $('#customfield_10300-val').text().trim(); let alertInfo_MDE = [], alertInfo_365 = []; function GMT8(params) { let date = new Date(params); date.setHours(date.getHours() + 16); // 获取当前的小时数并加上8小时 const year = date.getUTCFullYear(); const month = String(date.getUTCMonth() + 1).padStart(2, '0'); const day = String(date.getUTCDate()).padStart(2, '0'); const hours = String(date.getUTCHours()).padStart(2, '0'); const minutes = String(date.getUTCMinutes()).padStart(2, '0'); const seconds = String(date.getUTCSeconds()).padStart(2, '0'); const formattedDate = `${year}-${month}-${day}T${hours}:${minutes}:${seconds}`; return formattedDate; } function parseLog(rawLog) { const alertInfo = rawLog.reduce((acc, log) => { let logObj = ''; if (log != '') { try { if (log.charAt(log.length - 1) == '}') { const formatJson = log.substring(log.indexOf('{')).trim(); logObj = JSON.parse(formatJson.replace(/\\\(n/g, '\\n(')); } else { const formatJson = log.substring(log.indexOf('{')).trim() + '"}]}}'; logObj = JSON.parse(formatJson.replace(/\\\(n/g, '\\n(')); } if (logObj['integration'] == 'Wazuh-MDE') { raw_alert += 1; const { mde } = logObj; const { title, id, computerDnsName, relatedUser, evidence, alertCreationTime } = mde; let dotIndex = alertCreationTime.lastIndexOf('.'); let dateTimeStr = GMT8(alertCreationTime.slice(0, dotIndex)); const alert = { title, id, computerDnsName, dateTimeStr }; const userName = relatedUser ? relatedUser.userName : 'N/A'; let extrainfo = ''; let processCommandLine = ''; if (evidence) { const tmp = []; for (const evidenceItem of evidence) { let description = ''; if (evidenceItem.entityType === 'File') { console.log('===', WhiteFilehash(evidenceItem.sha1)); if (WhiteFilehash(evidenceItem.sha1) || WhiteFilehash(evidenceItem.sha256)) { description = `filename: ${evidenceItem.fileName}\nfilePath: ${evidenceItem.filePath}`; tmp.push(description); } else { description = `filename: ${evidenceItem.fileName}\nfilePath: ${evidenceItem.filePath}\nsha1: ${evidenceItem.sha1}`; tmp.push(description); } } if (evidenceItem.entityType === 'Process') { if (evidenceItem.processCommandLine !== undefined) { processCommandLine = evidenceItem.processCommandLine.replace( /\r\n\r\n+/g, '\n' ); console.log(processCommandLine); } if ( evidenceItem.processCommandLine !== undefined && evidenceItem.processCommandLine.includes('EncodedCommand') ) { let cmd_length = evidenceItem.processCommandLine.split(' ').length; description = `Decode_Cmd: ${atob( evidenceItem.processCommandLine .split(' ') [cmd_length - 1].replace(/['"]/g, '') )}`; tmp.push(description); } if (WhiteFilehash(evidenceItem.sha1) || WhiteFilehash(evidenceItem.sha256)) { description = `cmd: ${processCommandLine}\naccount: ${evidenceItem.accountName}`; tmp.push(description); } else { description = `cmd: ${processCommandLine}\naccount: ${evidenceItem.accountName}\nsha1: ${evidenceItem.sha1}`; tmp.push(description); } } if (evidenceItem.entityType === 'Url') { description += `Url: ${evidenceItem.url}`; tmp.push(description); } if (evidenceItem.entityType === 'Ip') { description += `IP: ${evidenceItem.ipAddress}`; tmp.push(description); } } const uniqueDescriptions = Array.from(new Set(tmp)); extrainfo = uniqueDescriptions.join('\n'); } alertInfo_MDE.push({ ...alert, userName, extrainfo }); } else { raw_alert += 1; const alerts = logObj['incidents']['alerts'][0]; console.log(alerts); let entities = {}; if (alerts !== undefined) { alerts['entities'].forEach(function (entity) { if (entity.processCommandLine !== undefined) { processCommandLine = entity.processCommandLine.replace(/\r\n\r\n+/g, '\n'); console.log(processCommandLine); } if (entity['entityType'] == 'User' || entity['entityType'] == 'Mailbox') { entities['user'] = `${entity['domainName']}\\\\${entity['accountName']}`; entities['userPrincipalName'] = entity['userPrincipalName']; } if (entity['entityType'] == 'CloudApplication') { entities['applicationId'] = entity['applicationId']; entities['applicationName'] = entity['applicationName']; } if (entity['entityType'] == 'Process') { if (!entities['process']) { entities['process'] = []; } const fileEntry = { filename: entity['fileName'], filePath: entity['filePath'], cmd: processCommandLine }; if (processCommandLine.includes('EncodedCommand')) { let cmd_length = processCommandLine.split(' ').length; fileEntry['Decode_Cmd'] = atob( processCommandLine.split(' ')[cmd_length - 1].replace(/['"]/g, '') ); } if ( Object.keys(entity).includes('sha256') && (WhiteFilehash(entity['sha256']) || WhiteFilehash(entity['sha1'])) ) { entities['process'].push(fileEntry); } else { fileEntry['sha256'] = entity['sha256']; entities['process'].push(fileEntry); } } if (entity['entityType'] == 'File') { if (!entities['file']) { entities['file'] = []; } const fileEntry = { filename: entity['fileName'], filePath: entity['filePath'] }; if ( Object.keys(entity).includes('sha256') && (WhiteFilehash(entity['sha256']) || WhiteFilehash(entity['sha1'])) ) { entities['file'].push(fileEntry); } else { fileEntry['sha256'] = entity['sha256']; entities['file'].push(fileEntry); } } if (entity['entityType'] == 'Ip') { if (!entities['ip']) { entities['ip'] = []; } entities['ip'].push({ ip: entity['ipAddress'] }); } if (entity['entityType'] == 'Url') { if (!entities['url']) { entities['url'] = []; } entities['url'].push({ url: entity['url'] }); } }); } let creationTime = GMT8(alerts.creationTime.split('.')[0]); let title = alerts?.title; if (summary.toLowerCase().includes(title.toLowerCase())) { title = undefined; } alertInfo_365.push({ creationTime: creationTime, Title: title, summary: logObj['incidents'].incidentName, host: alerts?.devices[0]?.deviceDnsName, user: entities.user, userPrincipalName: entities.userPrincipalName, process: entities.process, file: entities.file, ip: entities.ip, url: entities.url, alertid: alerts?.alertId, incidenturi: logObj['incidents'].incidentUri, severity: logObj['incidents'].severity, description: alerts['description'], applicationId: entities.applicationId, applicationName: entities.applicationName }); } } catch (error) { console.error(`Error: ${error.message}`); } } return acc; }, []); return alertInfo; } const alertDescriptions = []; parseLog(rawLog); function generateDescription_MDE() { for (const info of alertInfo_MDE) { const { title, computerDnsName, userName, extrainfo, dateTimeStr } = info; const desc = `Observed ${title}\nalertCreationTime(<span class="red_highlight">GMT+8</span>): ${dateTimeStr}\nHost: ${computerDnsName}\nusername: ${userName}\n${extrainfo}\n\nPlease help to verify if it is legitimate.\n`; alertDescriptions.push(desc); } } function generateDescription_365() { if (summary.includes('M365 Defender High Severity Alerts: Logon from a risky country involving one user')) { const ticketnumber = $('#key-val').text(); for (const info of alertInfo) { let desc = `Dear Customer, Reasons for escalating: Observed Logon from a risky country involving one user in [time] Here is information about this login: creationTime(<span class="red_highlight"">GMT</span>): ${info.creationTime} source IP: ${info.ip[0].ip} user: ${info.user} active: Microsoft 365 userPrincipalName: ${info.userPrincipalName} Device type: UserAgent: location: logging status: LoginStatus: MfaRequired: the user suddenly logged in from [Location1] but the user used to be logged in from [Location2], aberdeen. Please confirm whether the login behavior of the user is normal.if not, could block the ip. Suggestion: We suggest to confirm whether the behavior of this customer logging in at ${info.ip[0].ip}: is normal or not, if not, we suggest to block the IP and change the user's password and perform a full scan on the user's commonly used PCs, thank you! Severity: ${info.severity} Correlation ticket: ${ticketnumber} `; alertDescriptions.push(desc); } } else { for (const info of alertInfo_365) { let desc = `Observed ${info.summary}\n`; try { for (let key in info) { if (info.hasOwnProperty(key)) { if (Array.isArray(info[key])) { info[key].forEach((item) => { for (let subKey in item) { if (item.hasOwnProperty(subKey) && item[subKey] !== '') { desc += `${subKey}: ${item[subKey]}\n`; } } }); } else { if ( info[key] !== undefined && info[key] !== ' ' && key !== 'summary' && key !== 'alertid' && key !== 'incidenturi' && key !== 'severity' ) { if (key == 'creationTime') { desc += `creationTime(<span class="red_highlight">GMT+8</span>): ${info[key]}\n`; } else { desc += `${key}: ${info[key]}\n`; } } } } } } catch (error) { console.error(`Error: ${error}`); } let MDEURL = ''; if (LogSourceDomain == 'wkcda') { if (info.alertid && !MDEURL.includes(info.alertid)) { MDEURL += `https://security.microsoft.com/alerts/${info.alertid}<br>`; } if (info.incidenturi) { let incident_url = info.incidenturi.replace('hXXps[:]', 'https:') + '<br>'; MDEURL += incident_url; } desc += `MDE URL: \n${MDEURL}\n`; } desc += `\nPlease verify if the activity is legitimate.\n`; alertDescriptions.push(desc); } } } function generateDescription() { if (raw_alert < num_alert) { let extra_message = `<span class="red_highlight">Number Of Alert : ${num_alert}, Raw Log Alert : ${raw_alert} Raw log information is Not Complete, Please Get More Alert Information From Elastic.</span>\n`; alertDescriptions.push(extra_message); } generateDescription_MDE(); generateDescription_365(); const alertMsg = [...new Set(alertDescriptions)].join('\n'); showDialog(alertMsg); } function openMDE() { let MDEURL = ''; for (const info of alertInfo_MDE) { const { id } = info; if (id) { MDEURL += `https://security.microsoft.com/alerts/${id}<br>`; } } for (const info of alertInfo_365) { const { alertid, incidenturi } = info; if (alertid && !MDEURL.includes(alertid)) { MDEURL += `https://security.microsoft.com/alerts/${alertid}<br>`; } if (incidenturi) { let incident_url = incidenturi.replace('hXXps[:]', 'https:') + '<br>'; MDEURL += incident_url; } } showFlag('info', 'MDE URL:', `${MDEURL}`, 'manual'); let url = 'https://security.microsoft.com/homepage?¤t='; url += LogSourceDomain; for (let i = 0; i < MDEURL.length; i++) { let mde_url = `&url${i}=${MDEURL[i]}`; url += mde_url; console.log(MDEURL[i]); } let MDE_Assist_ = localStorage.getItem('MDE_Assist'); if (MDE_Assist_ != 0) { GM_openInTab(url, { active: false, // 设置为 false,以在后台打开,不激活新标签页 insert: true // 设置为 true,将新标签页插入到当前标签页之后 }); } } addButton('generateDescription', 'Description', generateDescription); addButton('openMDE', 'MDE', openMDE); } function WindowsSysAlertHandler(...kwargs) { var { summary, rawLog } = kwargs[0]; function parseLog(rawLog) { const alertInfo = rawLog.reduce((acc, log) => { try { if (log != '') { let log_data = {}, sub = ''; log.split('#010').forEach((element, index) => { if (element.includes('#013')) { element = element.replace(/#013/g, ''); } if (element.includes('#009')) { let e = element.replace(/#009/g, '').split(':'); log_data[e[0]] = e[1]; } if (element.includes('=')) { let e = element.replace(/#013/g, '').split('='); log_data[e[0]] = e[1]; } if (element.includes(':#013')) { sub = element.split(':')[0]; } if ( element.includes(':#009') && (element.includes('Account') || element.includes('Security ID') || element.includes('Logon ID')) ) { let e = element.replace(/#009/g, ' ').replace(/#013/g, '').split(': '); log_data[sub + e[0].trim()] = e[1]; } if (element.includes(':#009')) { let e = element.replace(/#009/g, ' ').replace(/#013/g, '').split(': '); log_data[e[0].trim()] = e[1]; } }); const regex = /(\S+\s+\S+\s+\S+\s+\S+\s+)(.*)/g; alertExtraInfo = { Event_time: regex.exec(log.split('#010')[0])[2], ComputerName: log_data.ComputerName ? log_data.ComputerName : undefined, EventCode: log_data.EventCode ? log_data.EventCode : undefined, SourceName: log_data.SourceName ? log_data.SourceName : undefined, CreatorAccountDomain: log_data['Creator SubjectAccount Domain'] ? log_data['Creator SubjectAccount Domain'] : undefined, CreatorAccountName: log_data['Creator SubjectAccount Name'] ? log_data['Creator SubjectAccount Name'] : undefined, Type: log_data.Type ? log_data.Type : undefined, Keywords: log_data.Keywords ? log_data.Keywords : undefined, Message: log_data.Message ? log_data.Message : undefined, CreatorProcessID: log_data['Creator Process ID'] ? log_data['Creator Process ID'] : undefined, CreatorProcessName: log_data['Creator Process Name'] ? log_data['Creator Process Name'] : undefined, NewProcessID: log_data['New Process ID'] ? log_data['New Process ID'] : undefined, NewProcessName: log_data['New Process Name'] ? log_data['New Process Name'] : undefined, ProcessCommandLine: log_data['Process Command Line'] ? log_data['Process Command Line'] : undefined, ProcessCommandLine: log_data['Process Command Line'] ? log_data['Process Command Line'] : undefined, SecurityID: log_data['Security ID'] ? log_data['Security ID'] : undefined, ServiceAccount: log_data['Service Account'] ? log_data['Service Account'] : undefined, ServiceFileName: log_data['Service File Name'] ? log_data['Service File Name'] : undefined, ServiceName: log_data['Service Name'] ? log_data['Service Name'] : undefined, ServiceStartType: log_data['Service Start Type'] ? log_data['Service Start Type'] : undefined, ServiceType: log_data['Service Type'] ? log_data['Service Type'] : undefined }; acc.push({ alertExtraInfo }); } } catch (error) { console.log(`Error: ${error.message}`); } return acc; }, []); return alertInfo; } const alertInfo = parseLog(rawLog); function generateDescription() { const alertDescriptions = []; for (const info of alertInfo) { const lastindex = summary.lastIndexOf(']'); let desc = `Observed ${summary.substr(lastindex + 1)}\n`; for (const key in info.alertExtraInfo) { if (Object.hasOwnProperty.call(info.alertExtraInfo, key)) { const value = info.alertExtraInfo[key]; if (value !== undefined) { if (key == 'start_time' || key == 'end_time') { desc += `${key}(<span class="red_highlight">GMT</span>): ${value.split('.')[0] + 'Z'}\n`; } else { desc += `${key}: ${value}\n`; } } } } desc += `\nPlease verify if the activity is legitimate.\n`; alertDescriptions.push(desc); } const alertMsg = [...new Set(alertDescriptions)].join('\n'); showDialog(alertMsg); } addButton('generateDescription', 'Description', generateDescription); } function ClarotyAlertHandler(...kwargs) { var { summary, rawLog } = kwargs[0]; var raw_alert = 0; const num_alert = $('#customfield_10300-val').text().trim(); function parseLog(rawLog) { const alertInfo = rawLog.reduce((acc, log) => { try { if (log.length == 0) { return acc; } const regex = /(\b\w+=)([^=\s].*?)(?=\s+\w+=|$)/g; let match; const matches = {}; while ((match = regex.exec(log)) !== null) { let item = match[0].split('='); matches[item[0]] = item.slice(1, item.length).join('='); } raw_alert += 1; console.log(matches); let logArray = log.split(' ').filter((item) => item !== ''); //Remove extra whitespace from the string acc.push({ 'Event time': logArray.slice(0, 3).join(' '), 'Extra information': logArray.slice(3, 8).join(' '), 'CtdSourceIp': matches.CtdSourceIp ? matches.CtdSourceIp : undefined, 'CtdDestinationIp': matches.CtdDestinationIp ? matches.CtdDestinationIp : undefined, 'CtdMessage': matches.CtdMessage ? matches.CtdMessage : undefined, 'CtdCategory': matches.CtdCategory ? matches.CtdCategory : undefined, 'CtdSourceZone': matches.CtdSourceZone ? matches.CtdSourceZone : undefined, 'CtdDestinationZone': matches.CtdDestinationZone ? matches.CtdDestinationZone : undefined, 'CtdAlertLink': matches.CtdAlertLink ? matches.CtdAlertLink : undefined }); } catch (error) { console.log(`Error: ${error.message}`); } return acc; }, []); return alertInfo; } const alertInfo = parseLog(rawLog); function generateDescription() { const alertDescriptions = []; if (raw_alert < num_alert) { let extra_message = `<span class="red_highlight">Number Of Alert : ${num_alert}, Raw Log Alert : ${raw_alert} Raw log information is Not Complete, Please Get More Alert Information From Elastic.</span>\n`; alertDescriptions.push(extra_message); } for (const info of alertInfo) { const lastindex = summary.lastIndexOf(']'); let desc = `Observed ${summary.substr(lastindex + 1)}\n`; for (const key in info) { if (Object.hasOwnProperty.call(info, key)) { const value = info[key]; if (value !== undefined) { desc += `${key}: ${value}\n`; } } } desc += `\nPlease verify if the activity is legitimate.\n`; alertDescriptions.push(desc); } const alertMsg = [...new Set(alertDescriptions)].join('\n'); showDialog(alertMsg); } addButton('generateDescription', 'Description', generateDescription); } function FireeyeAlertHandler(...kwargs) { var { summary, rawLog } = kwargs[0]; var raw_alert = 0; const num_alert = $('#customfield_10300-val').text().trim(); function parseLog(rawLog) { const alertInfo = rawLog.reduce((acc, log) => { try { if (log.length == 0) { return acc; } const regex = /(\b\w+=)([^=\s].*?)(?=\s+\w+=|$)/g; let match; const matches = {}; while ((match = regex.exec(log)) !== null) { let item = match[0].split('='); matches[item[0]] = item.slice(1, item.length).join('='); } raw_alert += 1; let logArray = log.split(' ').filter((item) => item !== ''); //Remove extra whitespace from the string acc.push({ 'Event time': logArray.slice(0, 3).join(' '), 'Vlan': matches.cn1 ? matches.cn1 : undefined, 'Sid': matches.cn2 ? matches.cn2 : undefined, 'CncHost': matches.cs5 ? matches.cs5 : undefined, 'CncPort': matches.cn3 ? matches.cn3 : undefined, 'Sname': matches.cs1 ? matches.cs1 : undefined, 'anomaly': matches.cs2 ? matches.cs2 : undefined, 'Link': matches.cs4 ? matches.cs4 : undefined, 'Channel': matches.cs6 ? matches.cs6 : undefined, 'request': matches.request ? matches.request : undefined, 'requestClientApplication': matches.requestClientApplication ? matches.requestClientApplication : undefined, 'requestMethod': matches.requestMethod ? matches.requestMethod : undefined, 'dst': matches.dst ? matches.dst : undefined, 'dpt': matches.dpt ? matches.dpt : undefined, 'src': matches.src ? matches.src : undefined, 'spt': matches.spt ? matches.spt : undefined, 'dvchost': matches.dvchost ? matches.dvchost : undefined, 'dvc': matches.dvc ? matches.dvc : undefined }); } catch (error) { console.log(`Error: ${error.message}`); } return acc; }, []); return alertInfo; } const alertInfo = parseLog(rawLog); function generateDescription() { const alertDescriptions = []; if (raw_alert < num_alert) { let extra_message = `<span class="red_highlight">Number Of Alert : ${num_alert}, Raw Log Alert : ${raw_alert} Raw log information is Not Complete, Please Get More Alert Information From Elastic.</span>\n`; alertDescriptions.push(extra_message); } for (const info of alertInfo) { const lastindex = summary.lastIndexOf(']'); let desc = `Observed ${summary.substr(lastindex + 1)}\n`; for (const key in info) { if (Object.hasOwnProperty.call(info, key)) { const value = info[key]; if (value !== undefined) { desc += `${key}: ${value}\n`; } } } desc += `\nPlease verify if the activity is legitimate.\n`; alertDescriptions.push(desc); } const alertMsg = [...new Set(alertDescriptions)].join('\n'); showDialog(alertMsg); } addButton('generateDescription', 'Description', generateDescription); } function WebAccesslogAlertHandler(...kwargs) { var { summary, rawLog } = kwargs[0]; var raw_alert = 0; function parseLog(rawLog) { const alertInfo = rawLog.reduce((acc, log) => { try { if (log.length == 0) { return acc; } const regex = /(\b\w+=)"([^"]*?)"/g; const regex_ = /"(.*?)"/g; let match; const matches = {}; while ((match = regex.exec(log)) !== null) { let item = match[0].split('='); matches[item[0]] = item.slice(1, item.length).join('='); } let match_; const matches_ = []; while ((match_ = regex_.exec(log)) !== null) { matches_.push(match_[0]); } console.log(matches); console.log(matches_); let logArray = log.split(' ').filter((item) => item !== ''); //Remove extra whitespace from the string console.log(logArray); acc.push({ 'Event time': logArray.slice(3, 5).join(' '), 'Source_IP': logArray[0] ? logArray[0] : undefined, // 'request_uri': matches.request_uri ? matches.request_uri : undefined, 'URL': matches_[0] ? matches_[0] : undefined, 'User-Agent': matches_[2] ? matches_[2] : undefined, 'upstream_status': logArray[8] ? logArray[8] : undefined, 'upstream_addr': matches.upstream_addr ? matches.upstream_addr : undefined, 'sn': matches.sn ? matches.sn : undefined, 'http_referrer': matches.http_referrer ? matches.http_referrer : undefined, 'http_cookie': matches.http_cookie ? matches.http_cookie : undefined, 'location': matches.location ? matches.location : undefined }); } catch (error) { console.log(`Error: ${error.message}`); } return acc; }, []); return alertInfo; } const alertInfo = parseLog(rawLog); console.log(alertInfo); function generateDescription() { const alertDescriptions = []; for (const info of alertInfo) { const lastindex = summary.lastIndexOf(']'); let desc = `Observed ${summary.substr(lastindex + 1)}\n`; for (const key in info) { if (Object.hasOwnProperty.call(info, key)) { const value = info[key]; if (value !== undefined && value !== '-' && value !== '"-"') { desc += `${key}: ${value}\n`; } } } desc += `\nPlease verify if the activity is legitimate.\n`; alertDescriptions.push(desc); } const alertMsg = [...new Set(alertDescriptions)].join('\n'); showDialog(alertMsg); } addButton('generateDescription', 'Description', generateDescription); } function FireeyeEtpAlertHandler(...kwargs) { const { rawLog, summary } = kwargs[0]; var raw_alert = 0; function parseLog(rawLog) { const alertInfo = rawLog.reduce((acc, log) => { try { const { meta, alert, email } = JSON.parse(log)['fireeye']; acc.push({ timestamp: alert['timestamp'], accepted: email['timestamp']['accepted'], last_malware: meta['last_malware'], alert_type: meta['alert_type'], status: email['status'], source_ip: email['source_ip'], rcpt_to: email['smtp']['rcpt_to'], mail_from: email['smtp']['mail_from'], etp_message_id: email['etp_message_id'], To: email['headers']['to'], From: email['headers']['from'], Subject: email['headers']['subject'], attachment: email['attachment'] }); raw_alert += 1; } catch (error) { console.log(`Error: ${error}`); } return acc; }, []); return alertInfo; } const alertInfo = parseLog(rawLog); const num_alert = $('#customfield_10300-val').text().trim(); function generateDescription() { const alertDescriptions = []; if (raw_alert < num_alert) { let extra_message = `<span class="red_highlight">Number Of Alert : ${num_alert}, Raw Log Alert : ${raw_alert} Raw log information is Not Complete, Please Get More Alert Information From Elastic.</span>\n`; alertDescriptions.push(extra_message); } for (const info of alertInfo) { let desc = `Observed ${summary.split(']')[1]}\n`; Object.entries(info).forEach(([index, value]) => { if (value !== undefined && value !== ' ' && index != 'Summary') { if (index == 'timestamp') { desc += `timestamp(<span class="red_highlight">GMT</span>): ${value.split('.')[0]}Z\n`; } else if (index == 'accepted') { desc += `accepted(<span class="red_highlight">GMT</span>): ${value}Z\n`; } else { desc += `${index}: ${value}\n`; } } }); desc += `\nPlease verify if the activity is legitimate.\n`; alertDescriptions.push(desc); } const alertMsg = [...new Set(alertDescriptions)].join('\n'); showDialog(alertMsg); } addButton('generateDescription', 'Description', generateDescription); } function SentinelOneAlertHandler(...kwargs) { const { rawLog, summary } = kwargs[0]; var raw_alert = 0; function parseLog(rawLog) { const alertInfo = rawLog.reduce((acc, log) => { try { console.log('===sentinel_one'); const sentinel_one = JSON.parse(log)['sentinel_one']; acc.push({ timestamp: sentinel_one.threatInfo.createdAt.split('.')[0], accountName: sentinel_one.accountName, agentDomain: sentinel_one.agentDomain, agentIpV4: sentinel_one.agentIpV4, agentOsName: sentinel_one.agentOsName, agentMitigationMode: sentinel_one.agentMitigationMode, filePath: sentinel_one.threatInfo.filePath, sha1: sentinel_one.threatInfo.sha1, confidenceLevel: sentinel_one.threatInfo.filePath, threatName: sentinel_one.threatInfo.threatName, processUser: sentinel_one.threatInfo.processUser }); raw_alert += 1; } catch (error) { console.log(`Error: ${error}`); } return acc; }, []); return alertInfo; } const alertInfo = parseLog(rawLog); const num_alert = $('#customfield_10300-val').text().trim(); function generateDescription() { const alertDescriptions = []; if (raw_alert < num_alert) { let extra_message = `<span class="red_highlight">Number Of Alert : ${num_alert}, Raw Log Alert : ${raw_alert} Raw log information is Not Complete, Please Get More Alert Information From Elastic.</span>\n`; alertDescriptions.push(extra_message); } for (const info of alertInfo) { let desc = `Observed ${summary.split(']')[1]}\n`; Object.entries(info).forEach(([index, value]) => { if (value !== undefined && value !== ' ' && index != 'Summary') { if (index == 'timestamp') { desc += `timestamp(<span class="red_highlight">GMT</span>): ${value.split('.')[0]}Z\n`; } else { desc += `${index}: ${value}\n`; } } }); desc += `\nPlease verify if the activity is legitimate.\n`; alertDescriptions.push(desc); } const alertMsg = [...new Set(alertDescriptions)].join('\n'); showDialog(alertMsg); } addButton('generateDescription', 'Description', generateDescription); } function LHG_CS_AlertHandler(DecoderName) { let ORG = $('#customfield_10002-val').text().trim(); console.log(ORG.split(' ')[ORG.split(' ').length - 1]); const elements = document.querySelectorAll('.user-hover.user-avatar'); const userList = ['kitty.li', 'anson.cho', 'ray.tan', 'philip.ng']; console.log(elements[0].textContent.toLowerCase()); // 对每个元素执行操作 let ClientComment = false; for (const dataItem of userList) { if (elements[0].textContent.toLowerCase().includes(dataItem.toLowerCase())) { ClientComment = true; break; } } //判断工单是否升级, if (ORG.split(' ')[ORG.split(' ').length - 1] == 'None' && DecoderName == 'crowdstrike_cef') { $('#opsbar-opsbar-transitions').on('click', () => { let userConfirmed = confirm('LHG的所有 Crowdstrike 告警均需要升级,即使是误报也需要升级'); }); } else { if (!ClientComment) { $('#opsbar-opsbar-transitions').on('click', () => { let userConfirmed = confirm( '只有这四个客户回复philip.ng,ray.tan,anson.cho,kitty.li,才可关单,若以上四个客户已允许close,可忽略此提示' ); }); } } } function RealMonitorMe() { let ORG = $('#customfield_10002-val').text().trim(); let status = $('#opsbar-transitions_more').text().trim(); if ($('#customfield_10302-val').text().trim().includes('\n')) { let rules = $('#customfield_10302-val').text().trim().split(' \n')[1].split('\n'); if (rules.length - 1 >= 3 && status == 'Work in progress') { confirm( `检测到该工单的RuleName有${ rules.length - 1 }个,(如果同一张tickets出现三个告警及以上,需要往cortex群里发,如果是误报请描述原因,谢谢)` ); } } const intervalId = setInterval(() => { var element_one = document.getElementById('opsbar-opsbar-transitions'); var first = element_one ? element_one.textContent || element_one.innerText : null; if (first == 'Resolved') { clearInterval(intervalId); } if (first == 'Waiting for customer' && ORG.split(' ')[ORG.split(' ').length - 1] == 'None') { console.log('===发生了改变', first); confirm('请注意,该工单变为Waiting for customer,请检查该工单是否已添加ORG'); first = 'Waiting for customer'; clearInterval(intervalId); } }, 500); } function formatCurrentDateTime(dateStr, decoder_name) { if (dateStr) { var date = new Date(dateStr); var localOffset = date.getTimezoneOffset(); if (decoder_name == 'impervainc_cef') { var targetDate = new Date(date.getTime() + (480 + localOffset) * 60000); } else { var targetDate = new Date(date.getTime() + (960 + localOffset) * 60000); } var year = targetDate.getFullYear(); var month = ('0' + (targetDate.getMonth() + 1)).slice(-2); var day = ('0' + targetDate.getDate()).slice(-2); var hours = ('0' + targetDate.getHours()).slice(-2); var minutes = ('0' + targetDate.getMinutes()).slice(-2); var seconds = ('0' + targetDate.getSeconds()).slice(-2); return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; } const pad = (num) => (num < 10 ? '0' : '') + num; const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; const date_ = new Date(); const day_ = date_.getDate(); const month_ = months[date_.getMonth()]; const year_ = date_.getFullYear().toString().slice(-2); // 取最后两位 const hours_ = date_.getHours(); const minutes_ = date_.getMinutes(); const ampm = hours_ >= 12 ? 'PM' : 'AM'; const hour = hours_ % 12 || 12; // Convert to 12-hour format and handle 0 case return `${pad(day_)}/${month_}/${year_} ${pad(hour)}:${pad(minutes_)} ${ampm}`; } function MonitorDev() { function formatDate() { const date = new Date(); const day = String(date.getDate()).padStart(2, '0'); // 日期补齐两位数 const month = date.toLocaleString('en-US', { month: 'short' }); // 获取月份缩写 const year = String(date.getFullYear()).slice(-2); // 取年份的后两位 let hours = date.getHours(); const minutes = String(date.getMinutes()).padStart(2, '0'); const ampm = hours >= 12 ? 'PM' : 'AM'; hours = hours % 12; // 将24小时制转换为12小时制 hours = hours ? hours : 12; // 如果是0点,将其转换为12 hours = String(hours).padStart(2, '0'); // 补齐小时为两位数 return `${day}/${month}/${year} ${hours}:${minutes} ${ampm}`; } let white = JSON.parse(localStorage.getItem('whitelist')); if (window.location.href.includes('/portal/2/create/100')) { const interval = setInterval(() => { var iframe = document.getElementById('rw_iframe'); var iframeDocument = iframe.contentDocument || iframe.contentWindow.document; var element = iframeDocument.getElementById('summary'); if (element) { let summary = 'Whitelist ' + white['summary'].replace('Wazuh', white['LogSourceDomain']); iframeDocument.getElementById('summary').value = summary; iframeDocument.getElementById('s2id_labels').innerHTML = `<ul class="select2-choices"> <li class="select2-search-choice"> <div>` + white['LogSourceDomain'] + `</div> <a href="#" class="select2-search-choice-close" tabindex="-1"></a></li><li class="select2-search-field"> <input type="text" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" class="select2-input" id="s2id_autogen1" style="width: 10px;"> </li></ul>`; iframeDocument.getElementById('labels').value = white['LogSourceDomain']; iframeDocument.getElementById('customfield_14601').value = formatDate(); iframeDocument.getElementById('customfield_14600').value = formatDate(); iframeDocument.getElementById('customfield_14610').value = 'Yes'; iframeDocument.getElementById('customfield_14609').value = 'Yes'; iframeDocument.getElementById('customfield_14608').value = 'Yes'; clearInterval(interval); } }, 600); } let cachedEntry = GM_getValue('cachedEntry', null); if (window.location.href.includes('/servlet/desk/portal/2') && window.location.href.includes('DEV')) { window.location.href = `${cachedEntry['hk']}/browse/` + window.location.href.split('portal/2/')[1]; localStorage.setItem('Dev_link', window.location.href.split('portal/2/')[1]); } if (window.location.href.includes(localStorage.getItem('Dev_link'))) { document.getElementById('edit-issue').click(); const interval = setInterval(() => { const components = document.querySelector('#components-textarea'); if (components) { $('#components-textarea').val(white['Component']); $('#components-textarea').click(); $('#issuelinks-issues-textarea').val(white['MSS'].split('browse/')[1]); $('#tab-0').click(); localStorage.removeItem('Dev_link'); clearInterval(interval); } }, 500); } } function WhiteFilehash(filehash) { if (filehash == undefined) { return 0; } const cachedWhitehashContent = GM_getValue('cachedWhitehashContent', null); for (const f of cachedWhitehashContent) { if (filehash.includes(f['hash'].toLowerCase())) { console.log('命中了', filehash); return true; } } } function RealTimeMonitoring() { // Filter page: audio control registration and regular issues table update if ( (window.location.href.includes('filter=15200') || window.location.href.includes('filter=26405') || window.location.href.includes('filter=13300')) && !window.location.href.includes('MSS') ) { console.log('#### Code includes filter run ####'); const NotifyControls = createNotifyControls(); if (window.location.href.includes('filter=15200') || window.location.href.includes('filter=26405')) { setInterval(() => { notifyKey = []; $('.aui-button.aui-button-primary.search-button').click(); setTimeout(() => { checkupdate(NotifyControls); }, 10000); }, 180000); } if (window.location.href.includes('filter=13300')) { setInterval(() => { notifyKey = []; $('.aui-button.aui-button-primary.search-button').click(); setTimeout(() => { monitorList(); }, 10000); }, 60000); } } if (window.location.href.includes('login.microsoftonline.com')) { setTimeout(() => { switch_user_microsoft(); }, 2000); } if (window.location.href.includes('security.microsoft.com/homepage?¤t=')) { setTimeout(() => { security_microsoft(); }, 3000); } // Issue page: Alert Handler const generation_description = setInterval(() => { var LogSourceDomain = $('#customfield_10223-val').text().trim(); let rawLog = $('#field-customfield_10219 > div:first-child > div:nth-child(2)').text().trim().split('\n'); if (rawLog == '') { rawLog = $('#field-customfield_10904 > div:first-child > div:nth-child(2)').text().trim().split('\n'); } const summary = $('#summary-val').text().trim(); if ($('#issue-content').length && !$('#generateDescription').length) { console.log('#### Code Issue page: Alert Handler ####'); const handlers = { 'cortex-xdr-json': cortexAlertHandler, 'mde-api-json': MDE365AlertHandler, 'sangfor-ccom-json': HTSCAlertHandler, 'carbonblack': CBAlertHandler, 'carbonblack_cef': VMCEFAlertHandler, 'windows_eventchannel': WineventAlertHandler, 'fortigate-firewall-v5': FortigateAlertHandler, 'crowdstrike_cef': CSAlertHandler, 'sophos': SophosAlertHandler, 'sepm-security': SpemAlertHandler, 'sepm-traffic': SpemAlertHandler, 'vmwarecarbonblack_cef': VMCEFAlertHandler, 'aws-cloudtrail': AwsAlertHandler, 'aws-cisco-umbrella': AwsAlertHandler, 'm365-defender-json': MDE365AlertHandler, 'azureeventhub': AzureAlertHandler, 'azuregraphapi-json': AzureGraphAlertHandler, 'paloalto-firewall': paloaltoAlertHandler, 'impervainc_cef': SangforAlertHandler, 'proofpoint_tap': ProofpointAlertHandler, 'zscaler-zpa-json': ZscalerAlertHandler, 'pulse-secure': PulseAlertHandler, 'aws-guardduty': AwsAlertHandler, 'alicloud-json': AlicloudAlertHandler, 'darktrace-json': DarktraceAlertHandler, 'sangfor_cef': SangforAlertHandler, 'cyberark_cef': SangforAlertHandler, 'radware-json': RadwareAlertHandler, 'carbonblack_cloud': CarbonAlertHandler, 'windows-syslog': WindowsSysAlertHandler, 'claroty_cef': ClarotyAlertHandler, 'office-365': Risky_Countries_AlertHandler, 'fireeye': FireeyeAlertHandler, 'web-accesslog': WebAccesslogAlertHandler, 'checkpoint_cef': SangforAlertHandler, 'incapsula_cef': SangforAlertHandler, 'fireeye-etp-json': FireeyeEtpAlertHandler, 'sentinelone-json': SentinelOneAlertHandler, 'sonicwall': FortigateAlertHandler, 'trellix_cef': SangforAlertHandler }; let DecoderName = $('#customfield_10807-val').text().trim().toLowerCase(); if (DecoderName == '') { DecoderName = $('#customfield_10906-val').text().trim().toLowerCase(); } if (DecoderName.includes('m365-defender-json')) { let decoder_name = []; DecoderName.split(' ').forEach((element, index) => { if (element != 'hide\n' && element != '' && element != 'show\n' && element != '\n') { decoder_name.push(element); } }); if (decoder_name[0].includes('m365-defender-json\n')) { DecoderName = 'm365-defender-json'; } } const handler = handlers[DecoderName]; if (handler) { handler({ LogSourceDomain: LogSourceDomain, rawLog: rawLog, summary: summary }); } const No_Decoder_handlers = { 'detect aad, o365 sign-in from risky countries': Risky_Countries_AlertHandler, 'successful azure/o365 login from malware-ip': Risky_Countries_AlertHandler, 'rarely country signin from o365': Risky_Countries_AlertHandler, 'agent disconnected': Agent_Disconnect_AlertHandler, 'suspicious geolocation ip login success': PulseAlertHandler, 'login success from malware ip(s)': ThreatMatrixAlertHandler, 'multiple account being disabled or deleted in short period of time': MultipleAccountAlertHandler, 'multiple sms request for same source ip': AwsAlertHandler }; const Summary = $('#summary-val').text().trim(); let No_Decoder_handler = null; Object.keys(No_Decoder_handlers).forEach((key) => { if (Summary.toLowerCase().includes(key)) { No_Decoder_handler = No_Decoder_handlers[key]; } }); if (No_Decoder_handler !== null) { No_Decoder_handler({ LogSourceDomain: LogSourceDomain, rawLog: rawLog, summary: Summary }); } if (LogSourceDomain == '') { LogSourceDomain = $('#customfield_10846-val').text().trim(); } const Log_Domain_handlers = { mdb: MdbAlertHandler, //这里面有点工单为decoder name:sshd dst: DstAlertHandler }; const Log_Domain_handler = Log_Domain_handlers[LogSourceDomain]; if (Log_Domain_handler) { Log_Domain_handler({ LogSourceDomain: LogSourceDomain, rawLog: rawLog, summary: summary }); } clearInterval(generation_description); } }, 1000); // Issue page: check Keywords and ATT&CK and Org setTimeout(() => { if ($('#issue-content').length && !$('.aui-banner-error').length) { console.log('#### Code Issue page: check Keywords ####'); checkKeywords(); checkATTCK(); } }, 4500); // Issue page: Edit Notify setTimeout(() => { let LogSourceDomain, Source, Labels, LogSource, DecoderName, TicketAutoEscalate, Status, RawLog, Summary, AgentName; let cachedEntry = GM_getValue('cachedEntry', null); if (window.location.host === cachedEntry['hk'].split('//')[1]) { // for HK LogSourceDomain = $('#customfield_10223-val').text().trim(); Source = $('#customfield_10113-val').text().trim(); Labels = $('.labels-wrap .labels li a span').text(); LogSource = $('#customfield_10204-val').text().trim(); DecoderName = $('#customfield_10807-val').text().trim().toLowerCase(); TicketAutoEscalate = $('#customfield_12202-val').text().trim(); Status = $('#status-val > span').text().trim(); RawLog = $('#field-customfield_10219 > div:first-child > div:nth-child(2)').text().trim() || $('#customfield_10219-val').text().trim() || $('#field-customfield_10232 > div.twixi-wrap.verbose > div > div > div > pre').text(); Summary = $('#summary-val').text().trim(); AgentName = $('#customfield_10805-val').text().trim(); } else if (window.location.host === cachedEntry['macao'].split('//')[1]) { // for MO LogSourceDomain = $('#customfield_10846-val').text().trim(); Source = $('#customfield_10872-val').text().trim(); Labels = $('#labels-212244-value').text().trim(); LogSource = $('#customfield_10854-val').text().trim(); DecoderName = $('#customfield_10906-val').text().trim(); TicketAutoEscalate = $('#customfield_10893-val').text().trim(); Status = $('#status-value > span').text().trim(); RawLog = $('#field-customfield_10904 > div.twixi-wrap.verbose > div').text().trim(); Summary = $('#summary-val').text().trim(); AgentName = $('#customfield_10802-val').text().trim(); } const pageData = { LogSourceDomain, Source, Labels, LogSource, DecoderName, TicketAutoEscalate, Status, RawLog, Summary, AgentName }; // If it pops up once, it will not be reminded again if ( ($('#issue-content').length && !$('#generateTicketNotify').length && window.location.href.includes('MSS')) || window.location.href.includes('OPS') ) { addButton('towhitelist', 'WhiteList', ToWhitelist); ticketNotify(pageData); } }, 1000); // Issue page: Norm Alert setTimeout(() => { var LogSourceDomain = $('#customfield_10223-val').text().trim(); let DecoderName = $('#customfield_10807-val').text().trim().toLowerCase(); if (DecoderName == '') { DecoderName = $('#customfield_10906-val').text().trim().toLowerCase(); } if (LogSourceDomain.includes('lhg')) { LHG_CS_AlertHandler(DecoderName); } }, 3500); // Issue page: Quick Reply setInterval(() => { if (document.querySelector('#reply') == null) { QuickReply(); } }, 3000); } (function () { ('use strict'); RealTimeMonitoring(); registerSearchMenu(); registerExceptionMenu(); registerCustomQuickReplyMenu(); addCss(); MonitorDev(); AJS.whenIType('zv').execute(function () { document.getElementById('opsbar-transitions_more').click(); const interval = setInterval(() => { const element = document.querySelector('#action_id_761'); if (element) { document.getElementById('action_id_761').click(); clearInterval(interval); } }, 100); // 每100毫秒检查一次 }); AJS.whenIType('zx').execute(function () { document.getElementById('edit-issue').click(); const interval = setInterval(() => { const tabsMenu = document.querySelector('#horizontal'); const elements = tabsMenu.querySelectorAll('*'); const elementsArray = Array.from(elements); const reviewElement = elementsArray.find((element) => element.outerText.trim() === 'Review'); if (reviewElement) { const menuItem = reviewElement.querySelector('.menu-item a'); const idValue = menuItem.id; const element = document.querySelector('#' + idValue); if (element) { document.getElementById(idValue).click(); $('#customfield_17201').val(formatCurrentDateTime()); const metaElement = document .querySelector('meta[name="ajs-remote-user-fullname"]') .getAttribute('content'); $('#customfield_17203-field').val(metaElement); document.getElementById('customfield_17203-field').click(); clearInterval(interval); } } }, 500); const intervals = setInterval(() => { const element1 = document.querySelector('#showing-1-of-1-matching-users'); console.log(element1); if (element1) { document.querySelector('#showing-1-of-1-matching-users li').click(); clearInterval(intervals); } }, 500); }); RealMonitorMe(); })();