Guest User

Untitled

a guest
Sep 13th, 2018
94
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 15.60 KB | None | 0 0
  1. #########################################################################################
  2. # LogRhythm | Cisco AMP for Endpoints - Get Events from API
  3. #########################################################################################
  4. #
  5. # LogRhythm - AHP
  6. # 26th April, 2018
  7. #
  8. # Version 1.5
  9. #
  10. # This script should be deployed in conjuction with the
  11. # LogRhythm - Cisco AMP for Endpoints Configuration Guide
  12. #
  13. # Change Log:
  14. #
  15. # Version | Date | Developer Name | Changes
  16. # 1.0 | 12th April, 2018 | Andy Habibi-Parker | First workable script
  17. # 1.1 | 16th April, 2018 | Andy Habibi-Parker | Added external log file
  18. # 1.2 | 24th April, 2018 | Andy Habibi-Parker | Added additional log output
  19. # 1.3 | 25th April, 2018 | Andy Habibi-Parker | Script is now HA aware
  20. # 1.4 | 26th April, 2018 | Andy Habibi-Parker | Script is now Proxy aware
  21. # 1.5 | 29th May, 2018 | Andy Habibi-Parker | Fixed Proxy detection bug
  22. #
  23. #########################################################################################
  24.  
  25. # ################################
  26. # Define Parameters for the script
  27. # ################################
  28. [CmdletBinding()]
  29. param(
  30. [Parameter(Mandatory = $true)] $CredentialsFile,
  31. $logfile = " ",
  32. $MaxLogFileSizeBytes = 10 * 1000 * 1000,
  33. [switch]$DebugOutput
  34. )
  35.  
  36. # If we're in debug mode, tell Powershell to write output to console
  37. if ($DebugOutput) {
  38. $DebugPreference = "Continue"
  39. }
  40.  
  41. function Write-Log {
  42. [CmdletBinding()]
  43. param(
  44. [Parameter()]
  45. [ValidateNotNullOrEmpty()]
  46. [ValidateSet('Information', 'Warning', 'Error')]
  47. [string]$Severity = 'Information',
  48.  
  49. [Parameter()]
  50. [ValidateNotNullOrEmpty()]
  51. [string]$Message
  52. )
  53.  
  54. [pscustomobject]@{
  55. Time = (Get-Date -Format "dd-MMM-yyyy HH:mm:ss.fff")
  56. Severity = $Severity
  57. Message = $Message
  58. } | Export-Csv -Path $logfile -Append -NoTypeInformation
  59. }
  60.  
  61. # Check if we're a HA System Monitor
  62. $HAservice = Get-Service -Name LifeKeeper -ErrorAction SilentlyContinue
  63.  
  64. if ($HAservice.Length -gt 0) {
  65. if ((Get-Service -Name LifeKeeper).Status -eq 'Running') {
  66. $ServiceStatus = (Get-Service -Name "LifeKeeper").Status
  67. $HA = $true
  68. $StateFile = "D:\LogRhythmHA\LogRhythm System Monitor\AMP4EP\State\AMP4EP.pos"
  69. $EventsFile = "D:\LogRhythmHA\LogRhythm System Monitor\AMP4EP\Events\AMP4EP.txt"
  70. $logFile = "D:\LogRhythmHA\LogRhythm System Monitor\AMP4EP\Log\AMP4EP.log"
  71. Write-Log -Message ("This is a HA system. LifeKeeper service found: " + "LifeKeeper -" + $ServiceStatus) -Severity Information
  72.  
  73. # Check if we're the active HA System Monitor
  74. if ($HA -eq $true -and ((Get-Service -Name "scsm").Status -ne 'Running')) {
  75. Write-Log -Message ("This is not the active HA node. Exiting") -Severity Warning
  76. exit
  77. }
  78. else {
  79. Write-Log -Message ("This is the active HA node") -Severity Information
  80. }
  81. }
  82. else {
  83. $logFile = "D:\LogRhythmHA\LogRhythm System Monitor\AMP4EP\Log\AMP4EP.log"
  84. Write-Log -Message ("This is a HA node but the LifeKeeper service is not running. Exiting") -Severity Warning
  85. exit
  86. }
  87. }
  88. else {
  89. $StateFile = "C:\Program Files\LogRhythm\LogRhythm System Monitor\AMP4EP\State\AMP4EP.pos"
  90. $EventsFile = "C:\Program Files\LogRhythm\LogRhythm System Monitor\AMP4EP\Events\AMP4EP.txt"
  91. $logFile = "C:\Program Files\LogRhythm\LogRhythm System Monitor\AMP4EP\Log\AMP4EP.log"
  92. Write-Log -Message ("This is not a HA system") -Severity Information
  93. }
  94.  
  95. # Check if log file exists
  96. if (Test-Path $logFile) {
  97.  
  98. # Check if the log file is larger than the Max allowable log file size
  99. if ((Get-Item $logFile).Length -ge $MaxLogFileSizeBytes) {
  100.  
  101. # If so, clear the log file to start fresh
  102. Clear-Content $logFile
  103. Write-Debug ("Log File " + $logFile + " exceeded " + $MaxLogFileSizeBytes.ToString() + " bytes; truncating.")
  104. Write-Log -Message ("Log File " + $logFile + " exceeded " + $MaxLogFileSizeBytes.ToString() + " bytes; truncating.") -Severity Information
  105. }
  106. }
  107.  
  108. # Check if the credentials file exists
  109. if (Test-Path $CredentialsFile) {
  110. Write-Debug ("Credentials file found: " + $CredentialsFile)
  111. Write-Log -Message ("Credentials file found: " + $CredentialsFile) -Severity Information
  112. try {
  113. $Credentials = Import-Clixml -Path $CredentialsFile
  114. $Clientid = $Credentials.Username
  115. $Apikey = $Credentials.GetNetworkCredential().Password
  116. }
  117. catch {
  118. Write-Error ("The credentials within the credentials file are corrupt. Please recreate the file: " + $CredentialsFile)
  119. Write-Log -Message ("The credentials within the credentials file are corrupt. Please recreate the file: " + $CredentialsFile) -Severity Error
  120. exit
  121. }
  122. }
  123. else {
  124. Write-Error ("Could not find credentials file: " + $CredentialsFile + ". Exiting")
  125. Write-Log -Message ("Could not find credentials file: " + $CredentialsFile + ". Exiting") -Severity Error
  126. Exit
  127. }
  128.  
  129. # Datetime format for the state file
  130. $StateFileFormat = "yyyy-MM-ddTHH:mm:ss"
  131.  
  132. # Define a default start time for message logs
  133. $DefaultStartTime = (Get-Date).AddDays(-7).ToUniversalTime()
  134.  
  135. # Start by using the default start time
  136. $StartTime = $DefaultStartTime
  137.  
  138. # Check if the state file exists
  139. if (Test-Path $StateFile) {
  140. Write-Debug ("State file " + $StateFile + " exists.")
  141. Write-Log -Message ("State file " + $StateFile + " exists.") -Severity Information
  142.  
  143. try {
  144. $StateContent = Get-Content $StateFile
  145.  
  146. # Attempt to parse the state file
  147. $StartTime = [datetime]::ParseExact($StateContent, $StateFileFormat, $null).ToUniversalTime()
  148. }
  149. catch {
  150.  
  151. # If the state file doesn't contain a valid date, use the default
  152. $StartTime = $DefaultStartTime
  153. Write-Debug "Failed to parse date from the state file"
  154. Write-Debug $_.Exception
  155.  
  156. Write-Log -Message "Failed to parse date from the state file" -Severity Error
  157. Write-Log -Message $_.Exception -Severity Error
  158. }
  159. }
  160. else {
  161. Write-Debug "State file did not exist, using default start time"
  162. Write-Log -Message "State file did not exist, using default start time" -Severity Information
  163. }
  164.  
  165.  
  166. Write-Debug ("Requesting AMP4EP logs from " + ($StartTime.ToString($StateFileFormat)))
  167. Write-Log -Message ("Requesting AMP4EP logs from " + ($StartTime.ToString($StateFileFormat))) -Severity Information
  168.  
  169. # Base64 encode the username and password for authorization header
  170. $EncodedUTF8 = [System.Text.Encoding]::UTF8.GetBytes($Clientid + ":" + $Apikey)
  171. $EncodedPassword = [System.Convert]::ToBase64String($EncodedUTF8)
  172.  
  173. $Header = @{ 'Authorization' = "Basic $($EncodedPassword)"; 'accept' = 'application/json'; 'Content-type' = 'application/json'; 'Accept-Encoding' = 'gzip, deflate' }
  174.  
  175. $APIendpoint = "https://api.amp.cisco.com"
  176. $Filter1 = ("/v1/events")
  177.  
  178. $Uri = ($APIendpoint + $Filter1)
  179. $Uri += "?start_date=" + ($StartTime.ToString($StateFileFormat))
  180.  
  181. if (!(Test-Path $StateFile)) {
  182. $Uri += "&offset=500"
  183. }
  184.  
  185. Write-Debug ("Calling AMP4EP API: " + $Uri)
  186. Write-Log -Message ("Calling AMP4EP API: " + $Uri) -Severity Information
  187.  
  188. $proxyUri = [Uri]$null
  189. $proxy = [System.Net.WebRequest]::GetSystemWebProxy()
  190. if ($proxy) {
  191. $proxy.Credentials = [System.Net.CredentialCache]::DefaultCredentials
  192. $proxyUri = $proxy.GetProxy($Uri)
  193. }
  194.  
  195. if ($proxyUri.AbsoluteUri -ne $Uri) {
  196. Write-Debug ("Using proxy: " + $proxyUri)
  197. Write-Log -Message ("Using proxy: " + $proxyUri) -Severity Information
  198.  
  199. try {
  200. $Response = Invoke-RestMethod -Uri $Uri -Headers $Header -Method GET -UseDefaultCredentials -Proxy $proxyUri -ProxyUseDefaultCredentials
  201. }
  202. catch {
  203. Write-Error "Failed to call the AMP4EP API. Exiting"
  204. Write-Debug $_.Exception
  205.  
  206. Write-Log -Message "Failed to call the AMP4EP API. Exiting" -Severity Error
  207. Write-Log -Message $_.Exception -Severity Error
  208. exit
  209. }
  210.  
  211. }
  212. else {
  213. try {
  214. Write-Debug ("No proxy server detected")
  215. Write-Log -Message ("No proxy server detected") -Severity Information
  216. $Response = Invoke-RestMethod -Uri $Uri -Headers $Header -Method GET
  217. }
  218. catch {
  219. Write-Error "Failed to call the AMP4EP API. Exiting"
  220. Write-Debug $_.Exception
  221.  
  222. Write-Log -Message "Failed to call the AMP4EP API. Exiting" -Severity Error
  223. Write-Log -Message $_.Exception -Severity Error
  224. exit
  225. }
  226. }
  227.  
  228. # Which properties do we want from the output?
  229. $Properties = $(
  230. #Non-Array Extract
  231. @{ Name = "Date"; Expression = { "Date=" + $_.date } },
  232. @{ Name = "Timestamp"; Expression = { "Timestamp=" + $_.timestamp } },
  233. @{ Name = "EventID"; Expression = { "EventID=" + $_.id } },
  234. @{ Name = "Event_Type"; Expression = { "Event_Type=" + $_.event_type } },
  235. @{ Name = "Event_TypeID"; Expression = { "Event_TypeID=" + $_.event_type_id } },
  236. @{ Name = "Detection"; Expression = { "Detection=" + $_.detection } },
  237. @{ Name = "DetectionID"; Expression = { "DetectionID=" + $_.detection_id } },
  238. @{ Name = "Group_GUIDs"; Expression = { "Group_GUIDs=" + $_.group_guids } },
  239.  
  240. # Computer Array Extract
  241. @{ Name = "Computer_Connector_GUID"; Expression = { "Computer_Connector_GUID=" + $_.computer.connector_guid } },
  242. @{ Name = "Computer_Hostname"; Expression = { "Computer_Hostname=" + $_.computer.hostname } },
  243. @{ Name = "Computer_External_IP"; Expression = { "Computer_External_IP=" + $_.computer.external_ip } },
  244. @{ Name = "Computer_User"; Expression = { "Computer_User=" + $_.computer.user } },
  245. @{ Name = "Computer_Active"; Expression = { "Computer_Active=" + $_.computer.active } },
  246. @{ Name = "Network_Addr_IP"; Expression = { "Network_Addr_IP=" + $_.computer.network_addresses.ip } },
  247. @{ Name = "Network_Addr.MAC"; Expression = { "Network_Addr_MAC=" + $_.network_addresses.mac } },
  248. @{ Name = "Links_Computer"; Expression = { "Links_Computer=" + $_.computer.links.computer } },
  249. @{ Name = "Links_Computer_Trajectory"; Expression = { "Links_Trajectory=" + $_.computer.links.trajectory } },
  250. @{ Name = "Links_Computer_Group"; Expression = { "Links_Group=" + $_.computer.links.group } },
  251.  
  252. #File Array Extract
  253. @{ Name = "File_Disposition"; Expression = { "File_Disposition=" + $_.file.disposition } },
  254. @{ Name = "File_Name"; Expression = { "File_Name=" + $_.file.file_name } },
  255. @{ Name = "File_Path"; Expression = { "File_Path=" + $_.file.file_path } },
  256. @{ Name = "File_Identity_SHA1"; Expression = { "File_Identity_SHA1=" + $_.file.identity.sha1 } },
  257. @{ Name = "File_Identity_SHA256"; Expression = { "File_Identity_SHA256=" + $_.file.identity.sha256 } },
  258. @{ Name = "File_Parent_Disposition"; Expression = { "File_Parent_Disposition=" + $_.file.Parent.disposition } },
  259. @{ Name = "File_Parent_File_Name"; Expression = { "File_Parent_File_Name=" + $_.file.Parent.file_name } },
  260. @{ Name = "File_Parent_Identity_SHA1"; Expression = { "File_Parent_Identity_SHA1=" + $_.file.Parent.identity.sha1 } },
  261. @{ Name = "File_Parent_Identity_SHA256"; Expression = { "File_Parent_Identity_SHA256=" + $_.file.Parent.identity.sha256 } },
  262.  
  263. #Scan Array Extract
  264. @{ Name = "Scan_Description"; Expression = { "Scan_Description=" + $_.scan.description } },
  265. @{ Name = "Scan_Clean"; Expression = { "Scan_Clean=" + $_.scan.clean } },
  266. @{ Name = "Scanned_Files"; Expression = { "Scanned_Files=" + $_.scan.scanned_files } },
  267. @{ Name = "Scanned_Processes"; Expression = { "Scanned_Processes=" + $_.scan.scanned_processes } },
  268. @{ Name = "Scanned_Paths"; Expression = { "Scanned_Paths=" + $_.scan.scanned_paths } },
  269. @{ Name = "Malicious_Detections"; Expression = { "Malicious_Detections=" + $_.scan.malicious_detections } }
  270.  
  271. #Vulnerabilities Array Extract
  272. @{ Name = "Vuln_Name"; Expression = { "Vuln_Name=" + $_.vulnerabilities.Name } },
  273. @{ Name = "Vuln_Version"; Expression = { "Vuln_Version=" + $_.vulnerabilities.version } },
  274. @{ Name = "Vuln_CVEs"; Expression = { "Vuln_CVEs=" + $_.vulnerabilities.cve } },
  275. @{ Name = "Vuln_Scores"; Expression = { "Vuln_Scores=" + $_.vulnerabilities.score } },
  276. @{ Name = "CVE_URLs"; Expression = { "CVE_URLs=" + $_.vulnerabilities.url } },
  277.  
  278. #Network_Info Array Extract
  279. @{ Name = "Dirty_URL"; Expression = { "Dirty_URL=" + $_.network_info.dirty_url } },
  280. @{ Name = "Remote_IP"; Expression = { "Remote_IP=" + $_.network_info.remote_ip } },
  281. @{ Name = "Remote_Port"; Expression = { "Remote_Port=" + $_.network_info.remote_port } },
  282. @{ Name = "Local_IP"; Expression = { "Local_IP=" + $_.network_info.local_ip } },
  283. @{ Name = "Local_Port"; Expression = { "Local_Port=" + $_.network_info.local_port } },
  284.  
  285. #Generic_IOC Array Extract
  286. @{ Name = "IOC_Desc"; Expression = { "IOC_Desc=" + $_.generic_ioc.description } },
  287. @{ Name = "IOC_Short_Desc"; Expression = { "IOC_Short_Desc=" + $_.generic_ioc.short_description } }
  288. )
  289.  
  290. # Check if events file exists
  291. if (Test-Path $EventsFile) {
  292.  
  293. # Check if the events file is larger than the Max allowable log file size
  294. if ((Get-Item $EventsFile).Length -ge $MaxLogFileSizeBytes) {
  295.  
  296. # If so, clear the log file to start fresh
  297. Clear-Content $EventsFile
  298. Write-Debug ("Events File " + $EventsFile + " exceeded " + $MaxLogFileSizeBytes.ToString() + " bytes; truncating.")
  299. Write-Log -Message ("Events File " + $EventsFile + " exceeded " + $MaxLogFileSizeBytes.ToString() + " bytes; truncating.") -Severity Information
  300. }
  301. }
  302.  
  303. # Pull out the properties we want and sort by time
  304. $Output = $Response.data | Select-Object $Properties | Sort-Object timestamp
  305.  
  306. try {
  307. # Export the logs, appending to the log file
  308. $Output |
  309. ConvertTo-Csv -NoTypeInformation |
  310.  
  311. # This removes the header row
  312. Select-Object -Skip 1 |
  313.  
  314. Out-File $EventsFile -Append -Encoding UTF8
  315.  
  316. Write-Debug ("Wrote " + (@($Output).Length.ToString()) + " logs to file " + $EventsFile)
  317. Write-Log -Message ("Wrote " + (@($Output).Length.ToString()) + " logs to file " + $EventsFile) -Severity Information
  318. }
  319. catch {
  320. Write-Error ("Could not write logs to the file " + $EventsFile)
  321. Write-Debug $_.Exception
  322.  
  323. Write-Log -Message ("Could not write logs to the events file: " + $EventsFile) -Severity Warning
  324. Write-Log -Message $_.Exception -Severity Error
  325. exit
  326. }
  327.  
  328. # If number of received events is greater than 0
  329. if ((@($Output).Length.ToString()) -gt 0) {
  330. try {
  331. # Get the last date entry in the response
  332. $EndTime = $Response.data.Item(0) | date
  333. }
  334. catch {
  335. Write-Error "Could not get last date entry from received events"
  336. Write-Debug $_.Exception
  337.  
  338. Write-Log -Message "Could not get last date entry from received events" -Severity Warning
  339. Write-Log -Message $_.Exception -Severity Error
  340. }
  341. try {
  342. # Add the last date entry to the StateFile
  343. $EndTime.ToString($StateFileFormat) | Out-File $StateFile
  344. }
  345. catch {
  346. Write-Error ("Could not write timestamp to state file: " + $StateFile + ". This may result in duplicate logs")
  347. Write-Debug $_.Exception
  348.  
  349. Write-Log -Message ("Could not write timestamp to state file: " + $StateFile + ". This may result in duplicate logs") -Severity Warning
  350. Write-Log -Message $_.Exception -Severity Error
  351. }
  352. }
  353. else {
  354. Write-Debug "No new events available from AMP4EP"
  355. Write-Log -Message "No new events available from AMP4EP" -Severity Information
  356. }
Add Comment
Please, Sign In to add comment