From ee7a7e1f37aa25afde68bae601c5d6a75de077cc Mon Sep 17 00:00:00 2001 From: Bar Katzir <37335599+bakatzir@users.noreply.github.com> Date: Thu, 27 Sep 2018 09:16:47 +0300 Subject: [PATCH] re-write mcafee atd in python (#2162) * re-write mcafee atd in python * remove unnecessary auxiliary function * support more inputs of detonation playbooks using generic pooling, handle cases in which analysis time is very short. * CR - function naming convention, unite send_req and send_req_raw, etc. --- Integrations/integration-McAfee-ATD.yml | 1267 +++++++++++------------ 1 file changed, 621 insertions(+), 646 deletions(-) diff --git a/Integrations/integration-McAfee-ATD.yml b/Integrations/integration-McAfee-ATD.yml index 662a3f661980..6c652bc001bd 100644 --- a/Integrations/integration-McAfee-ATD.yml +++ b/Integrations/integration-McAfee-ATD.yml @@ -5,9 +5,10 @@ name: McAfee Advanced Threat Defense display: McAfee Advanced Threat Defense category: Forensics & Malware Analysis image: data:image/png;base64,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 -description: 'Integrated advanced threat detection: Enhancing protection from network edge to endpoint' -detaileddescription: |- - When entering a user to use the API, please make sure the user has capability of "Allow Multiple Logins" +description: 'Integrated advanced threat detection: Enhancing protection from network + edge to endpoint' +detaileddescription: ' When entering a user to use the API, please make sure the + user has capability of "Allow Multiple Logins"' configuration: - display: Server URL (e.g. https://192.168.0.1) name: baseUrl @@ -36,687 +37,662 @@ configuration: required: false script: script: |- - //GLOBALS// - var BASE = params.baseUrl; - // handle '/' at the end of the url - if (BASE[BASE.length - 1] === '/') { - BASE = BASE.substring(0, BASE.length - 1); + ''' IMPORTS ''' + import string + import requests + import json + import re + import base64 + import shutil + + # disable insecure warnings + requests.packages.urllib3.disable_warnings() + + if not demisto.params().get("proxy", True): + del os.environ["HTTP_PROXY"] + del os.environ["HTTPS_PROXY"] + del os.environ["http_proxy"] + del os.environ["https_proxy"] + + ''' PREREQUISITES ''' + def load_server_url(): + ''' Cleans and loads the server url from the configuration ''' + url = demisto.params()['baseUrl'] + url = re.sub('/[\/]+$/', '', url) + url = re.sub('\/$', '', url) + return url + + def load_proxy(): + ''' Loads the system configured proxy if enabled in configuration ''' + proxy = {} + if demisto.params()['proxy']: + proxy['http'] = os.environ['http_proxy'] + proxy['https'] = os.environ['https_proxy'] + return proxy + + ''' GLOBALS ''' + USERNAME = demisto.params()['username'] + PASSWORD = demisto.params()['password'] + USE_SSL = not demisto.params()['unsecure'] + BASE_URL = load_server_url() + PROXY = load_proxy() + LOGINHEADERS = { + 'Accept': 'application/vnd.ve.v1.0+json', + 'Content-Type': 'application/json', + 'VE-SDK-API': base64.b64encode(USERNAME + ':' + PASSWORD) } - - var USERNAME = params.username; - var PASSWORD = params.password; - var UNSECURE = params.unsecure; - var PROXY = params.proxy; - - //DICTIONARIES// - var LOGINHEADERS = { - 'Accept': ['application/vnd.ve.v1.0+json'], - 'Content-Type': ['application/json'], - 'VE-SDK-API': [Base64.encode(USERNAME + ':' + PASSWORD)] - }; - var HEARTBEATHEADERS = { - 'Accept': ['application/vnd.ve.v1.0+json'], - 'Content-Type': ['application/json'] - }; - - //HELPER FUNCTIONS// - function stringArrToIntArr(stringArr){ - var intArr = []; - if (stringArr.length > 0){ - for (index = 0; index < stringArr.length; index++) { - if(stringArr[index]){ - intArr.push(parseInt(stringArr[index])); - } - } - } - else{ - intArr = [parseInt(stringArr)] - } - return intArr; - } - - function resToMD(body, title){ - return tblToMd(title, body, Object.keys(body)); - } - - function castToInt(val){ - if (typeof val === 'string') { - return parseInt(val); - } else { - return val; - } + HEARTBEATHEADERS = { + 'Accept': 'application/vnd.ve.v1.0+json', + 'Content-Type': 'application/json' } - function getSessionCredentials(){ - res = sendRequest('/php/session.php','GET', LOGINHEADERS); - if (res) { - return res.results; - } - } - - function getHeaders(){ - var sess = getSessionCredentials(); - return {'Accept': ['application/vnd.ve.v1.0+json'], - 'VE-SDK-API':[Base64.encode(sess.session + ':' + sess.userId)] - }; - } - - function sendRequestRaw(uri, method, headers, body){ - var res = http( - BASE+uri, - { - Method: method, - Headers: headers, - Body: body - }, - UNSECURE, - PROXY - ); - if (res.StatusCode < 200 || res.StatusCode >= 300) { - throw 'Failed to use uri ' + BASE+uri + ', request status code: ' + res.StatusCode + ' and Body: ' + res.Body + '.'; - } - - var uriStr = String(uri); - if (uriStr.indexOf("session") === -1) { - logout(); + ''' HELPERS ''' + def string_arr_to_int_arr(stringArr): + ''' Converts a string array to int array ''' + intArr = [] + if isinstance(stringArr, list): + for index in range(len(stringArr)): + if stringArr[index]: + intArr.append(int(stringArr[index])) + else: + intArr = [int(stringArr)] + return intArr + + def cast_to_int(val): + ''' Casts a string to int ''' + if isinstance(val, str): + return int(val) + else: + return val + + def get_session_credentials(): + res = http_request('php/session.php','get', LOGINHEADERS) + if (res): + return res['results'] + + def get_headers(): + sess = get_session_credentials() + return { + 'Accept': 'application/vnd.ve.v1.0+json', + 'VE-SDK-API': base64.b64encode(sess['session'] + ':' + sess['userId']) } - return res; - } - function sendRequest(uri, method, headers, body){ - body = sendRequestRaw(uri,method, headers, body).Body; - var res = JSON.parse(body); - if (res.success) { - if (res.success === 'false') { - throw 'ATD Api call to '+uri+' failed with request body: '+body; - } + def http_request(uri, method, headers = {}, body = {}, params={}, files={}): + ''' Makes an API call with the supplied uri, method, headers, body ''' + url = '%s/%s' % (BASE_URL, uri) + res = requests.request( + method, + url, + headers=headers, + data=body, + verify=USE_SSL, + params=params, + files=files + ) + if res.status_code < 200 or res.status_code >= 300: + return_error('Got status code ' + str(res.status_code) + ' with body ' + res.content + ' with headers ' + str(res.headers)) + uriStr = str(uri) + if (uriStr.find("session") == -1): + logout() + result = res.content + if not uri.startswith('php/showreport.php?'): + result = json.loads(result) + if 'success' in result: + if (result['success'] == 'false'): + return_error('ATD Api call to ' + uri + ' failed with request body: ' + body) + return result + + + + ''' FUNCTIONS ''' + def heart_beat(): + return http_request('php/heartbeat.php','get', API_HEADERS, HEARTBEATHEADERS) + + def test_get_session(): + res = http_request('php/session.php','get', LOGINHEADERS) + + def prettify_current_user_res(currentUser): + prettyCurrentUser = { + 'APIVersion': currentUser['apiVersion'], + 'IsAdmin': 'True' if (currentUser['isAdmin'] == '1') else 'False', + 'SessionId': currentUser['session'], + 'UserId': currentUser['userId'] } - return res; - } - - //COMMAND FUNCTIONS// - - function verifyHash(){ - var body = {}; - holder = {}; - holder.md5 = args.hash; - body.data = JSON.stringify(holder); - return sendRequest('/php/atdHashLookup.php','POST', getHeaders(), body); - } - - function heartBeat(){ - return sendRequest('/php/heartbeat.php','GET', getHeaders(), HEARTBEATHEADERS); - } - - function prettifyCurrentUserRes(currentUser){ - var prettyCurrentUser = { - 'APIVersion': currentUser.apiVersion, - 'IsAdmin': currentUser.isAdmin === '1' ? 'True' : 'False', - 'SessionId': currentUser.session, - 'UserId': currentUser.userId - }; - return prettyCurrentUser; - } - - function getSession(){ - var res = sendRequest('/php/session.php','GET', LOGINHEADERS); - var md = tableToMarkdown('ATD Current User',prettifyCurrentUserRes(res.results), - ['APIVersion', 'IsAdmin', 'SessionId', 'UserId']); - return { - Type: entryTypes.note, - Contents: res.results, - ContentsFormat: formats.json, - ReadableContentsFormat: formats.markdown, - HumanReadable: md, - EntryContext: { - "ATD.Session(val.SessionId==obj.SessionId)": prettifyCurrentUserRes(res.results) + return prettyCurrentUser + + def get_session(): + res = http_request('php/session.php','get', LOGINHEADERS) + md = tableToMarkdown('ATD Current User',prettify_current_user_res(res['results']), + ['APIVersion', 'IsAdmin', 'SessionId', 'UserId']) + demisto.results({ + 'Type': entryTypes['note'], + 'ContentsFormat': formats['json'], + 'Contents': res['results'], + 'ReadableContentsFormat': formats['markdown'], + 'HumanReadable': md, + 'EntryContext': { + "ATD.Session(val.SessionId==obj.SessionId)": prettify_current_user_res(res['results']) } - }; - } - - function prettifyListUsersRes(users){ - var prettyUsers = []; - for (i = 0; i < users.length; i++) { - var user = users[i]; - prettyUsers[i] = { - 'FullName': user.fullName, - 'UserId': user.idx, - 'LoginId': user.loginId, - 'UserType': user.userType - }; - } - return prettyUsers; - } - - function listUsers (userType){ - userType = userType ? userType : 'STAND_ALONE'; - var result = sendRequest('/php/briefUserList.php?userType='+userType,'GET', getHeaders()); - var users = result.results; - return users; - } - - function listUsersCommand(){ - var users = listUsers(args.userType); - - var prettyUsers = prettifyListUsersRes(users); - var md = tableToMarkdown('ATD User List', prettyUsers, - ['FullName', 'UserId', 'LoginId', 'UserType']); - return { - Type: entryTypes.note, - Contents: users, - ContentsFormat: formats.json, - HumanReadable: md, - EntryContext: { - "ATD.Users(val.UserId==obj.UserId)": prettyUsers, + }) + + def prettify_list_users_res(users): + prettyUsers = [] + + for i in range(len(users)): + user = users[i] + prettyUsers.append({ + 'FullName': user['fullName'], + 'UserId': user['idx'], + 'LoginId': user['loginId'], + 'UserType': user['userType'] + }) + + return prettyUsers + + def list_users(userType): + userType = userType if userType else 'STAND_ALONE' + result = http_request('php/briefUserList.php?userType='+userType,'get', API_HEADERS) + users = result['results'] + return users + + def list_users_command(): + users = list_users(demisto.args()['userType']) + + prettyUsers = prettify_list_users_res(users) + md = tableToMarkdown( + 'ATD User List', + prettyUsers, + ['FullName', 'UserId', 'LoginId', 'UserType'] + ) + + demisto.results({ + 'Type': entryTypes['note'], + 'ContentsFormat': formats['json'], + 'Contents': users, + 'ReadableContentsFormat': formats['markdown'], + 'HumanReadable': md, + 'EntryContext': { + "ATD.Users(val.UserId==obj.UserId)": prettyUsers, } - }; - } - - function prettifyListProfilesRes(profiles){ - var prettyProfiles = []; - for (i = 0; i < profiles.length; i++){ - prettyProfiles[i] = { - 'Name': profiles[i].name, - 'AnalyzerProfileId': profiles[i].vmProfileid, - 'Description': profiles[i].vmDesc, - 'Sandbox': profiles[i].sandbox === 1 ? 'True' : 'False', - 'Internet': profiles[i].internet === 1 ? 'True' : 'False', - 'LocalBlackList': profiles[i].locBlackList === 1 ? 'True' : 'False' + }) + + def prettify_list_profiles_res(profiles): + prettyProfiles = [] + for i in range(len(profiles)): + prettyProfiles.append({ + 'Name': profiles[i]['name'], + 'AnalyzerProfileId': profiles[i]['vmProfileid'], + 'Description': profiles[i]['vmDesc'], + 'Sandbox': 'True' if profiles[i]['sandbox'] == 1 else 'False', + 'Internet': 'True' if profiles[i]['internet'] == 1 else 'False', + 'LocalBlackList': 'True' if profiles[i]['locBlackList'] == 1 else 'False' + }) + return prettyProfiles + + def list_profiles(): + res = http_request('php/vmprofiles.php','get', API_HEADERS) + md = tableToMarkdown( + 'ATD Analyzers Profile List',prettify_list_profiles_res(res['results']), + ['Name','AnalyzerProfileId','Description', + 'Sandbox','Internet','LocalBlackList']); + + + demisto.results({ + 'Type': entryTypes['note'], + 'ContentsFormat': formats['json'], + 'Contents': res['results'], + 'ReadableContentsFormat': formats['markdown'], + 'HumanReadable': md, + 'EntryContext': { + "ATD.ListAnalyzerProfiles(val.AnalyzerProfileId==obj.AnalyzerProfileId)": prettify_list_profiles_res(res['results']) } + }) + + def prettify_task_status_by_taskId_res(taskStatus): + prettyTaskStatus = { + 'taskId': taskStatus['taskid'], + 'jobId': taskStatus['jobid'], + 'status': taskStatus['status'], + 'filename': taskStatus['filename'], + 'MD5': taskStatus['md5'], + 'submitTime': taskStatus['submitTime'] } - return prettyProfiles; - } - - function listProfiles(){ - var res = sendRequest('/php/vmprofiles.php','GET', getHeaders()); - var md = tableToMarkdown('ATD Analyzers Profile List',prettifyListProfilesRes(res.results), - ['Name','AnalyzerProfileId','Description', - 'Sandbox','Internet','LocalBlackList']); - - return {Type: entryTypes.note, - Contents: res.results, - ContentsFormat: formats.json, - HumanReadable: md, - EntryContext: { - "ATD.ListAnalyzerProfiles(val.AnalyzerProfileId==obj.AnalyzerProfileId)": - prettifyListProfilesRes(res.results) - } - }; - } - - function prettifyTaskStatusByTaskIdRes(taskStatus){ - var prettyTaskStatus = { - 'taskId': taskStatus.taskid, - 'jobId': taskStatus.jobid, - 'status': taskStatus.status, - 'filename': taskStatus.filename, - 'MD5': taskStatus.md5, - 'submitTime': taskStatus.submitTime - } - return prettyTaskStatus; - } - - function checkTaskStatusByTaskId(taskIds){ - var res; - var multipleResults = []; - var tasks = []; - var requestSuffix; - - for (i = 0; i < taskIds.length; i++) { - requestSuffix = 'iTaskId=' + taskIds[i]; - res = sendRequest('/php/samplestatus.php?'+requestSuffix,'GET', getHeaders()); - // when you use TaskID, you get results in res.results - tasks.push(prettifyTaskStatusByTaskIdRes(res.results)); - multipleResults.push(res.results); - } - - var status = res.results.status; //backward compatability + return prettyTaskStatus + + def check_task_status_by_taskId(taskIds): + res = {} + multipleResults = [] + tasks = [] + requestSuffix = '' + + for i in range(len(taskIds)): + requestSuffix = 'iTaskId=' + str(taskIds[i]) + res = http_request('php/samplestatus.php?' + requestSuffix ,'get', API_HEADERS) + # when you use TaskID, you get results in res.results + tasks.append(prettify_task_status_by_taskId_res(res['results'])) + multipleResults.append(res['results']) + + status = res['results']['status'] #backward compatability return { - status: status, - tasks: tasks, - multipleResults: multipleResults - }; - } - - function checkTaskStatusByJobId(jobIds){ - var taskIds = []; - for (i = 0; i < jobIds.length; i++) { - taskIds.push((sendRequest('/php/getTaskIdList.php?jobId='+jobIds[i],'GET', getHeaders())).result.taskIdList); - } - return checkTaskStatusByTaskId(taskIds); - } - - function checkTaskStatusCommand(){ - var ids = []; - var result; - - if ( (!args.jobId && !args.taskId) || (args.jobId && args.taskId) ){ - throw 'You must specify one (and only one) of the following: jobId, taskId.'; + 'status': status, + 'tasks': tasks, + 'multipleResults': multipleResults } - if (args.jobId) { - ids = stringArrToIntArr(argToList(args.jobId)); - result = checkTaskStatusByJobId(ids); - } - - if (args.taskId) { - ids = stringArrToIntArr(argToList(args.taskId)); - result = checkTaskStatusByTaskId(ids); - } - - var md = tableToMarkdown('ATD Sandbox Task Status', result.tasks, Object.keys(result.tasks[0])); - - return { - Type: entryTypes.note, - Contents: result.multipleResults, - ContentsFormat: formats.json, - HumanReadable: md, - EntryContext: { - "ATD.status": result.status, //backward compatability - "ATD.Task(val.taskId==obj.taskId)": result.tasks + def check_task_status_by_jobId(jobIds): + taskIds = [] + for i in range(len(jobIds)): + taskIds.append((http_request('php/getTaskIdList.php?jobId='+jobIds[i],'get', API_HEADERS))['result']['taskIdList']) + return check_task_status_by_taskId(taskIds) + + def check_task_status_command(): + ids = [] + result = {} + args = demisto.args() + + if ( ('jobId' not in args and 'taskId' not in args) or ('jobId' in args and 'taskId' in args) ): + return_error('You must specify one (and only one) of the following: jobId, taskId.') + + if ('jobId' in args): + ids = string_arr_to_int_arr(argToList(args['jobId'])) + result = check_task_status_by_jobId(ids) + + elif ('taskId' in args): + ids = string_arr_to_int_arr(argToList(args['taskId'])) + result = check_task_status_by_taskId(ids) + + md = tableToMarkdown( + 'ATD Sandbox Task Status', + result['tasks'], + (result['tasks'][0]).keys() + ) + + demisto.results({ + 'Type': entryTypes['note'], + 'ContentsFormat': formats['json'], + 'Contents': result['multipleResults'], + 'ReadableContentsFormat': formats['markdown'], + 'HumanReadable': md, + 'EntryContext': { + "ATD.status": result['status'], #backward compatability + "ATD.Task(val.taskId==obj.taskId)": result['tasks'] } - }; - } - - function getTaskIds(jobIds){ - var results = []; - var res; - for (i = 0; i < jobIds.length; i++) { - res = sendRequest('/php/getTaskIdList.php?jobId='+jobIds[i],'GET', getHeaders()); - results.push(res); - } - return results; - } - - function getTaskIdsCommand(){ - var jobIds = stringArrToIntArr(argToList(args.jobId)); - var results = getTaskIds(jobIds); - - var multipleMd = []; - var ec = []; - for (i = 0; i < results.length; i++) { - multipleMd.push({ - taskId: results[i].result.taskIdList, - jobId: jobIds[i] - }); - ec.push({ - taskId: results[i].result.taskIdList, - jobId: jobIds[i] - }); - } - - var md = tblToMd('ATD TaskIds and JobIds List', multipleMd, ["taskId", "jobId"]); - return { - Type: entryTypes.note, - Contents: results, - ContentsFormat: formats.json, - HumanReadable: md, - EntryContext: { - "ATD.Task(val.jobId==obj.jobId)": ec + }) + + def get_taskIds(jobIds): + results = [] + res = {} + for i in range(len(jobIds)): + res = http_request('php/getTaskIdList.php?jobId=' + str(jobIds[i]),'get', API_HEADERS) + results.append(res) + return results + + def get_taskIds_command(): + jobIds = string_arr_to_int_arr(argToList(demisto.args()['jobId'])) + results = get_taskIds(jobIds) + + multipleMd = [] + ec = [] + for i in range(len(results)): + multipleMd.append({ + 'taskId': results[i]['result']['taskIdList'], + 'jobId': jobIds[i] + }) + ec.append({ + 'taskId': results[i]['result']['taskIdList'], + 'jobId': jobIds[i] + }) + + md = tblToMd('ATD TaskIds and JobIds List', multipleMd, ['taskId', 'jobId']) + + demisto.results({ + 'Type': entryTypes['note'], + 'ContentsFormat': formats['json'], + 'Contents': results, + 'ReadableContentsFormat': formats['markdown'], + 'HumanReadable': md, + 'EntryContext': { + "ATD.Task(val.jobId==obj.jobId)": ec } - }; - } - - function prettifyFileUploadRes(fileUploadRes){ - var prettyFileUpload = { - 'taskId': fileUploadRes.results[0].taskId, - 'jobId': fileUploadRes.subId, - 'messageId': fileUploadRes.fileId, - 'url': fileUploadRes.results[0].url, - 'srcIp': fileUploadRes.results[0].srcIp, - 'destIp': fileUploadRes.results[0].destIp, - 'MD5': fileUploadRes.results[0].md5, - 'SHA1': fileUploadRes.results[0].sha1, - 'SHA256': fileUploadRes.results[0].sha256, + }) + + def prettify_file_upload_res(fileUploadRes): + prettyFileUpload = { + 'taskId': fileUploadRes['results'][0]['taskId'], + 'jobId': fileUploadRes['subId'], + 'messageId': fileUploadRes['results'][0]['messageId'], + 'url': fileUploadRes['results'][0]['url'], + 'srcIp': fileUploadRes['results'][0]['srcIp'], + 'destIp': fileUploadRes['results'][0]['destIp'], + 'MD5': fileUploadRes['results'][0]['md5'], + 'SHA1': fileUploadRes['results'][0]['sha1'], + 'SHA256': fileUploadRes['results'][0]['sha256'], } return prettyFileUpload; - } - - function fileUploadRaw(body, fileEntryId, filenameToUpload) { - var uri = '/php/fileupload.php' - - - if (typeof fileEntryId !== undefined) { //checking that it's a file upload and not url - if (typeof filenameToUpload == undefined) { //first priority for the file name is user's argument - //second priority for the file name is the file name in the context - var filenameDq = dq(invContext, 'File(val=val.EntryID==="' + fileEntryId +'")=val.Name'); - if (filenameDq && filenameDq[0]) { - filenameToUpload = filenameDq; - } - else { - filenameToUpload = fileEntryId; //last priority for the file name is demisto's entryID - } - } - } - - res = httpMultipart( - BASE+uri, - fileEntryId, - { - Method: 'POST', - Headers: getHeaders(), - }, - body, - UNSECURE, - PROXY, - false, - 'amas_filename', - filenameToUpload - ); - if (res.StatusCode < 200 || res.StatusCode >= 300) { - throw 'Failed to use uri ' + BASE+uri + ', request status code: ' + res.StatusCode + ' and Body: ' + res.Body + '.'; - } - - var result = res.Body; - var uriStr = String(uri); - if (uriStr.indexOf("session") === -1) { - logout(); - } - return result; - }; - function fileUpload(submitType, sample, vmProfileList, + def file_upload_raw(body, fileEntryId, filenameToUpload): + uri = 'php/fileupload.php' + if len(filenameToUpload) == 0: # first priority for the file name is user's argument + #second priority for the file name is the file name in the context + filenameDq = demisto.dt(demisto.context(), 'File(val=val.EntryID=="' + fileEntryId +'")=val.Name') + if (filenameDq and filenameDq[0]): + filenameToUpload = filenameDq + else: + filenameToUpload = fileEntryId # last priority for the file name is demisto's entryID + + with open(demisto.getFilePath(fileEntryId)['path'], 'rb') as f: + file_up = {'amas_filename': f} + res = http_request( + uri, + 'post', + API_HEADERS, + body, + '', + files=file_up, + ) + + if (res['success'] == False): + return_error('Failed to upload sample due to: ' + res['errorMessage']) + return res + + def url_upload_raw(body): + uri = 'php/fileupload.php' + res = http_request( + uri, + 'post', + API_HEADERS, + body + ) + + if (res['success'] == False): + return_error('Failed to upload sample due to: ' + res['errorMessage']) + return res + + def file_upload(submitType, sample, vmProfileList, skipTaskId, analyzeAgain, xMode, messageId, - filePriorityQ, srcIp, destIp, fileName){ - var body = {}; - body.data = {}; - var data = {}; - data.data = {}; - - data.data.vmProfileList = vmProfileList; - data.data.submitType = submitType; - data.data.messageId = messageId; - data.data.srcIp = srcIp; - data.data.destIp = destIp; - data.data.url = (submitType == '0') ? '' : sample; - data.data.skipTaskId = castToInt(skipTaskId); - data.data.analyzeAgain = analyzeAgain; - data.data.xMode = xMode; - data.filePriorityQ = filePriorityQ ? filePriorityQ : 'run_now'; - - body.data = JSON.stringify(data); - var file = (submitType == '0') ? sample : undefined; - var filenameToUpload = (submitType == '0' && fileName) ? fileName : undefined; - var resultObj = fileUploadRaw(body, file, filenameToUpload); - resultObj = JSON.parse(resultObj); - if (resultObj.success === false){ - throw 'Command failed due to: ' + resultObj.errorMessage; - } - + filePriorityQ, srcIp, destIp, fileName): + body = {} + body['data'] = {} + data = {} + data['data'] = {} + + data['data']['vmProfileList'] = vmProfileList + data['data']['submitType'] = submitType + data['data']['messageId'] = messageId + data['data']['srcIp'] = srcIp + data['data']['destIp'] = destIp + data['data']['url'] = '' if submitType == '0' else sample + data['data']['skipTaskId'] = cast_to_int(skipTaskId) + data['data']['analyzeAgain'] = analyzeAgain + data['data']['xMode'] = xMode + data['data']['filePriorityQ'] = filePriorityQ if filePriorityQ else 'run_now' + + body['data'] = json.dumps(data) + file = sample if submitType == '0' else '' + filenameToUpload = fileName if (submitType == '0' and fileName) else '' + if (submitType == '0'): + resultObj = file_upload_raw(body, file, filenameToUpload) + elif (submitType == '1'): + resultObj = url_upload_raw(body) return{ - taskId: resultObj.results[0].taskId, - resultObj: resultObj - }; - } - - function fileUploadCommand(){ - var sample = args.entryID ? args.entryID : args.url; - var vmProfileList = args.vmProfileList ? castToInt(args.vmProfileList) : null; - - var result = fileUpload(castToInt(args.submitType), sample, - vmProfileList, castToInt(args.skipTaskId), - castToInt(args.analyzeAgain), castToInt(args.xMode), args.messageId, - args.filePriorityQ, args.srcIp, args.destIp, args.fileName); - - var md = tableToMarkdown('ATD sandbox sample submission', prettifyFileUploadRes(result.resultObj), - ['taskId', 'jobId', 'messageId', 'url', 'destIp', 'srcIp', 'MD5', 'SHA1', 'SHA256']); + 'taskId': resultObj['results'][0]['taskId'], + 'resultObj': resultObj + } - return { - Type: entryTypes.note, - Contents: result.resultObj, - ContentsFormat: formats.json, - HumanReadable: md, - EntryContext: { - "ATD.Task(val.taskId==obj.taskId)": prettifyFileUploadRes(result.resultObj), - "ATD.taskId": result.resultObj.results[0].taskId //backward compatabillity + def file_upload_command(): + args = demisto.args() + + if (('entryID' in args and 'url' in args) or ('entryID' not in args and 'url' not in args)): + return_error('You must submit one and only one of the following: url, entryID') + if (('entryID' in args and args['submitType'] != '0') or ('url' in args and args['submitType'] != '1')): + return_error('In order to detonate a file submitType must be 0 and an entryID of a file must be given.\n' + + 'In order to detonate a url submitType must be 1 and a url must be given.') + + sample = args['entryID'] if 'entryID' in args else args['url'] + vmProfileList = cast_to_int(args['vmProfileList']) if 'vmProfileList' in args else None + analyzeAgain = cast_to_int(args['analyzeAgain']) if 'analyzeAgain' in args else None + skipTaskId = cast_to_int(args['skipTaskId']) if 'skipTaskId' in args else None + xMode = cast_to_int(args['xMode']) if 'xMode' in args else None + messageId = args['messageId'] if 'messageId' in args else None + filePriorityQ = args['filePriorityQ'] if 'filePriorityQ' in args else None + srcIp = args['srcIp'] if 'srcIp' in args else None + destIp = args['destIp'] if 'destIp' in args else None + fileName = args['fileName'] if 'fileName' in args else None + + result = file_upload(cast_to_int(args['submitType']), sample, vmProfileList, + skipTaskId, analyzeAgain, xMode, messageId, filePriorityQ, + srcIp, destIp, fileName) + md = tableToMarkdown('ATD sandbox sample submission', prettify_file_upload_res(result['resultObj']), + ['taskId', 'jobId', 'messageId', 'url', 'destIp', 'srcIp', 'MD5', 'SHA1', 'SHA256']) + + demisto.results({ + 'Type': entryTypes['note'], + 'ContentsFormat': formats['json'], + 'Contents': result['resultObj'], + 'ReadableContentsFormat': formats['markdown'], + 'HumanReadable': md, + 'EntryContext': { + "ATD.Task(val.taskId==obj.taskId)": prettify_file_upload_res(result['resultObj']), + "ATD.taskId": result['taskId'] # backward compatabillity } - }; - } - - function buildReportContext(reportSummary, uploadData, status, threshold){ - var context = {}; - - if ((reportSummary) && (reportSummary.Subject)) { - var subject = reportSummary.Subject; - context = { DBotScore: {Vendor: 'McAfee-Advanced-Threat-Defense', Score: 0 }}; - if ( subject.FileType ) {//file - context.DBotScore.Indicator = subject.md5; - context.DBotScore.Type = 'hash'; - if (reportSummary.Verdict.Severity > threshold) {//default threshold for McAfee ATD is 3 - context.DBotScore.Score = 3; - - addMalicious(context, outputPaths.file, { - Type : subject.Type, - MD5 : subject.md5, + }) + + def build_report_context(reportSummary, uploadData, status, threshold): + context = {} + if ((reportSummary) and (reportSummary['Subject'])): + subject = reportSummary['Subject'] + context = { 'DBotScore': {'Vendor': 'McAfee-Advanced-Threat-Defense', 'Score': 0 }} + if ('FileType' in subject): # file + context['DBotScore']['Indicator'] = subject['md5'] + context['DBotScore']['Type'] = 'hash' + if (reportSummary['Verdict']['Severity'] > threshold): # default threshold for McAfee ATD is 3 + context['DBotScore']['Score'] = 3 + + addMalicious(context, outputPaths['file'], { + Type : subject['Type'], + MD5 : subject['md5'], SHA1 : subject['sha-1'], SHA256 : subject['sha-256'], - Size : subject.size, - Name : subject.Name, + Size : subject['size'], + Name : subject['Name'], Malicious: {Vendor: 'McAfee-Advanced-Threat-Defense', - Description: 'Severity: ' + reportSummary.Verdict.Severity} - }); - } - else { - context.DBotScore.Score = 1; - } - } - if (uploadData){ - - if (reportSummary.Ips){ - var ip_addresses = []; - for (i=0; i < reportSummary.Ips.length; i++){ - ip_addresses.push(reportSummary.Ips[i].Ipv4); - }; - context["IP.Address"] = ip_addresses; - } + Description: 'Severity: ' + reportSummary['Verdict']['Severity'] + } + }) - context["ATD.Task(val.taskId===obj.taskId)"] = - { + else: + context['DBotScore']['Score'] = 1 + + context['IP'] = {} + if ('Ips' in reportSummary): + ip_addresses = [] + for i in range(len(reportSummary['Ips'])): + ip_addresses.append(reportSummary['Ips'][i]['Ipv4']) + context['IP']['Address'] = ip_addresses + + if (uploadData): + context['ATD'] = {} + context['ATD']['Task(val.taskId==obj.taskId)'] = { 'status': status, - 'taskId': uploadData.taskId, - 'jobId': uploadData.subId, - 'messageId': uploadData.messageId, - 'url': uploadData.url, - 'srcIp': uploadData.srcIp, - 'destIp': uploadData.destIp, - 'MD5': uploadData.md5, - 'SHA1': uploadData.sha1, - 'SHA256': uploadData.sha256, + 'taskId': uploadData['taskId'], + 'jobId': uploadData['subId'], + 'messageId': uploadData['messageId'], + 'url': uploadData['url'], + 'srcIp': uploadData['srcIp'], + 'destIp': uploadData['destIp'], + 'MD5': uploadData['md5'], + 'SHA1': uploadData['sha1'], + 'SHA256': uploadData['sha256'], 'Report': { - 'Attachments': reportSummary.Attachments, - 'Environment': reportSummary.Environment, - 'Environment': reportSummary.Environment, - 'Ips': reportSummary.Ips, - 'Verdict':reportSummary.Verdict, - 'Data': reportSummary.Data, - 'Selectors': reportSummary.Selectors, + 'Attachments': reportSummary['Attachments'], + 'Environment': reportSummar['Environment'], + 'Environment': reportSummary['Environment'], + 'Ips': reportSummary['Ips'], + 'Verdict':reportSummary['Verdict'], + 'Data': reportSummary['Data'], + 'Selectors': reportSummary['Selectors'], } } - } - } - return context; - } - - function getReport(uriSuffix, filename, type, uploadData, status, threshold){ - var jres = sendRequest('/php/showreport.php?'+uriSuffix+'&iType=json', 'GET', getHeaders()); - var summary = jres.Summary; - summary.VerdictDescription = summary.Verdict.Description; - summary.VerdictSeverity = summary.Verdict.Severity; - - var ec = buildReportContext(summary, uploadData, status, threshold); - var jresString = JSON.stringify(jres); - - if (type === 'json'){ - summary = formatTableValues(summary); - var md = resToMD(summary,'ATD Sandbox Report'); + return context + + def get_report(uriSuffix, filename, report_type, uploadData, status, threshold): + jres = json.loads(http_request('php/showreport.php?' + uriSuffix + '&iType=json', 'get', API_HEADERS)) + summary = jres['Summary'] + summary['VerdictDescription'] = summary['Verdict']['Description'] + summary['VerdictSeverity'] = summary['Verdict']['Severity'] + ec = build_report_context(summary, uploadData, status, threshold) + jresString = json.dumps(jres) + if (report_type == 'json'): + md = tableToMarkdown('McAfee ATD Sandbox Report', summary, summary.keys(), None, True) return{ - content: jresString, - md: md, - ec: ec - }; - } - - var res = sendRequestRaw('/php/showreport.php?'+uriSuffix+'&iType='+type, 'GET', getHeaders()); - if (type === 'pdf' || type === 'zip') { - if(type === 'pdf' && !getSessionCredentials().isAdmin){ - return 'No permission to download PDF'; - } - else{ - filename = filename + '.' + type; - return{ - content: res.Bytes, - filename: filename, - ec: ec - }; - } - } - if (type === 'sample') { - if (res.Body.substring(11,16) === 'false') { - return 'No permission to download sample' + 'content': jresString, + 'md': md, + 'ec': ec } - else{ - return{ - content: res.Bytes, - filename: filename + '.zip', - ec: ec - }; - } - } - return res; - } - function getReportCommand(){ - var uriSuffix = jobOrTaskId(); - var type = args.type ? args.type : 'pdf'; - var threshold = args.threshold; + res = http_request('php/showreport.php?' + uriSuffix + '&iType=' + report_type, 'get', API_HEADERS) - var filename = args.jobId; - if ((!filename) || (filename.length === 0)) { - filename = args.taskId; - } - try{ - return returnReport(uriSuffix, filename, type, threshold); - } - catch(error){ - if (error.message === 'EOF'){ - throw "The submission doesn't exist in McAfee ATD"; - } - } - } - - function jobOrTaskId(){ - uriSuffix = ''; - if ( (!args.jobId && !args.taskId) || (args.jobId && args.taskId) ){ - throw 'You must specify one (and only one) of the following: jobId, taskId.'; - } + if (report_type == 'pdf' or report_type == 'zip'): + if(report_type == 'pdf' and not get_session_credentials()['isAdmin']): + return 'No permission to download PDF' + else: + filename = str(filename) + '.' + report_type + return{ + 'content': res, + 'filename': filename, + 'ec': ec + } + if (report_type == 'sample'): + return{ + 'content': res, + 'filename': filename + '.zip', + 'ec': ec + } + return res - if (args.jobId) { - uriSuffix = 'jobId='+ args.jobId; - } - if (args.taskId) { - uriSuffix = 'iTaskId='+ args.taskId; - } - return uriSuffix; - } + def get_report_command(): + uriSuffix = job_or_taskId(); + args = demisto.args() + report_type = args['type'] if 'type' in args else 'pdf' + threshold = args['threshold'] - function detonate(submitType ,sample, timeout, type, threshold, fileName){ - var result = fileUpload(submitType, sample, fileName); - var taskId = result.taskId; - var uploadData = result.resultObj.results[0]; + filename = args['jobId'] if 'jobId' in args else args['taskId'] - var status; - var start = (new Date).getTime(); - var diff = 0; + return_report(uriSuffix, filename, report_type, '', '', threshold) - while (diff < timeout) { - status = checkTaskStatusByTaskId([taskId]).status; - if (status === 'Completed'){ - var uriSuffix = 'iTaskId='+ taskId; - return returnReport(uriSuffix, taskId, type, uploadData, status, threshold); - } - diff = ( (new Date).getTime() - start ) / 1000; - } - throw ("Timeout due to no answer after " + args.timeout + - " seconds. Check the status using '!atd-check-status' in a while and if 'completed' execute '!atd-get-report'."); - } + def job_or_taskId(): + uriSuffix = '' + args = demisto.args() + if ( ('jobId' not in args and 'taskId' not in args) or ('jobId' in args and 'taskId' in args) ): + return_error('You must specify one (and only one) of the following: jobId, taskId.') - function returnReport(uriSuffix, taskId, type, uploadData, status, threshold){ - var res = getReport(uriSuffix, taskId, type, uploadData, status, threshold); - if(type === 'json'){ - return { - Type: entryTypes.note, - Contents: res.content, - ContentsFormat: formats.json, - HumanReadable: res.md, - EntryContext: res.ec - }; - } - else if (type === 'pdf' || type === 'zip'){ - return { - Type: 9, - FileID: saveFile(res.content), - Contents: res.filename, - File: res.filename, - EntryContext: res.ec - }; - } - else if (type === 'sample'){ - //used to retrieve a sample from McAfee ATD to demisto - return { - Type: 3, - FileID: saveFile(res.content), - Contents: res.filename, - File: res.filename, - EntryContext: res.ec - }; - } - else{ - return res; - } - } + if 'jobId' in args: + uriSuffix = 'jobId=' + str(args['jobId']) + else: + uriSuffix = 'iTaskId=' + str(args['taskId']) - function logout(){ - res = sendRequest('/php/session.php','DELETE', getHeaders()); - if (res) { - return res.results; - } - } + return uriSuffix; - // The command input arg holds the command sent from the user. - switch (command) { - // This is the call made when pressing the integration test button. - case 'test-module': - getSession(); - return 'ok'; - case 'atd-login': - return getSession(); - case 'atd-list-analyzer-profiles': - return listProfiles(); - case 'atd-list-user': - return listUsersCommand(); - //case 'atd-verify-blacklisted-whitelisted-hashs': - // return verifyHash(); - case 'atd-check-status': - return checkTaskStatusCommand(); - case 'atd-get-task-ids': - return getTaskIdsCommand(); - case 'atd-file-upload': - return fileUploadCommand(); - case 'atd-get-report': - return getReportCommand(); - case 'detonate-file': //deprecated, please use relevant detonation playbook - return detonate(0, args.upload, args.timeout, args.format, args.threshold); - //submit type for regular file is 0 - case 'detonate-url': //deprecated, please use relevant detonation playbook - return detonate(1, args.url, args.timeout, args.format, args.threshold, args.fileName); - //submit type for url submission is 1 - //case 'detonate-file-remote': - //return detonate(3, args.url, args.timeout, args.format, args.threshold); - //submit type for url-download is 3 - default: - } - type: javascript + def detonate(submitType ,sample, timeout, report_type, threshold, fileName): + sys.exit(0) + result = file_upload(submitType, sample, fileName) + taskId = result['taskId'] + uploadData = result['resultObj']['results'][0] + + status = '' + start = datetime.utcnow() + diff = 0; + + while (diff < timeout): + status = checkTaskStatusByTaskId([taskId])['status'] + if (status == 'Completed'): + uriSuffix = 'iTaskId=' + taskId + return_report(uriSuffix, taskId, report_type, uploadData, status, threshold) + diff = ( datetime.utcnow() - start ) / 1000 + return_error("Timeout due to no answer after " + demisto.args()['timeout'] + + " seconds. Check the status using '!atd-check-status' in a while and if 'completed' execute '!atd-get-report'.") + + def return_report(uriSuffix, taskId, report_type, uploadData, status, threshold): + + res = get_report(uriSuffix, taskId, report_type, uploadData, status, threshold) + + if report_type == 'json': + demisto.results({ + 'Type': entryTypes['note'], + 'ContentsFormat': formats['json'], + 'Contents': res['content'], + 'ReadableContentsFormat': formats['markdown'], + 'HumanReadable': res['md'], + 'EntryContext': res['ec'] + }) + + elif report_type == 'pdf' or report_type == 'zip': + file_type = entryTypes['entryInfoFile'] + result = fileResult(res['filename'], res['content'], file_type) # will be saved under 'InfoFile' in the context. + result['EntryContext'] = res['ec'] + demisto.results(result) + + + elif report_type == 'sample': + # used to retrieve a sample from McAfee ATD to demisto + file_type = entryTypes['file'] + result = fileResult(res['filename'], res['content'], file_type) # will be saved under 'File' in the context, can be farther investigated. + demisto.results(result) + + else: + demisto.results(res) + + def logout(): + res = http_request('/php/session.php','delete', API_HEADERS) + + ''' EXECUTION ''' + LOG('command is %s' % (demisto.command(), )) + API_HEADERS = get_headers() + + try: + if demisto.command() == 'test-module': + test_get_session() + demisto.results('ok') + + if demisto.command() == 'atd-login': + get_session() + + elif demisto.command() == 'atd-list-analyzer-profiles': + list_profiles() + + elif demisto.command() == 'atd-list-user': + list_users_command() + + elif demisto.command() == 'atd-check-status': + check_task_status_command() + + elif demisto.command() == 'atd-get-task-ids': + get_taskIds_command() + + elif demisto.command() == 'atd-file-upload': + file_upload_command() + + elif demisto.command() == 'atd-get-report': + get_report_command() + + elif demisto.command() == 'detonate-file': #deprecated, please use 'ATD - Detonate File' playbook + detonate(0, demisto.args()['upload'], demisto.args()['timeout'], demisto.args()['format'], demisto.args()['threshold'], demisto.args['fileName']) + #submit type for regular file is 0 + + elif demisto.command() == 'detonate-url': #deprecated, please use 'Detonate URL - McAfee ATD_python' playbook + detonate(1, demisto.args()['url'], demisto.args()['timeout'], demisto.args()['format'], demisto.args()['threshold'], demisto.args['fileName']) + #submit type for url submission is 1 + + #elif demisto.command() == 'detonate-file-remote': + #return detonate(3, args.url, args.timeout, args.format, args.threshold); + #submit type for url-download is 3 + + except Exception, e: + LOG(e.message) + LOG.print_log() + return_error(e.message) + type: python commands: - name: atd-file-upload arguments: @@ -995,7 +971,6 @@ script: type: number description: Returns the current session details - name: detonate-file - deprecated: true arguments: - name: upload required: true @@ -1102,9 +1077,8 @@ script: - contextPath: IP.Address description: IP's relevant to the sample type: string - description: Deprecated, please use the 'McAfee ATD Detonate File' playbook instead + description: Deprecated, please use detonate playbook instead. - name: detonate-url - deprecated: true arguments: - name: url required: true @@ -1209,7 +1183,7 @@ script: - contextPath: IP.Address description: IP's relevant to the sample type: string - description: Deprecated, please use the 'McAfee ATD Detonate URL' playbook instead + description: Deprecated, please use detonate playbook instead. - name: atd-check-status arguments: - name: taskId @@ -1245,3 +1219,4 @@ script: type: string description: Checks the analysis status of up to 100 jobIDs/taskIDs runonce: false +releaseNotes: "Moved McAfee-Advanced-Threat-Defense integration to python" \ No newline at end of file