FireEye + Splunk: Intermediate Guide
Transcription
FireEye + Splunk: Intermediate Guide
FireEye + Splunk: Intermediate Guide Table of Contents Introduction. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 Current Integration Efforts. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 Creating Advanced Connectors. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 Splunk Listener . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 Splunk Role. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 Splunk User . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 FireEye Data. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 Examining a Raw Event. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 Single Line JSON. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 Multiline JSON . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 Universal Parser. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 According to Splunk: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 Parsing Other Formats. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 Experimenting with XML. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 Single Line XML. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 Multiline XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 Universal Parser. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 Summary of Differences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 Creating Apps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 Moving a Dashboard . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 Customizing an App. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 1 www.fireeye.com App Navigation Colors. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 App Icons . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 Dashboard Details . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 Sample FireEye Dashboards. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33 NX (web MPS). . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33 Alerts -> Alerts:. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33 Alerts -> Callback Activity:. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 Time Frames:. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 Panels to Enhance Visibility. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 NX (web MPS). . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 Severity Pie Chart: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 Malware Pie Chart:. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 Top 20 Most Active Target IPs: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 Top 20 Most Active Destination Ports: . . . . . . . . . . . . . . . . . . . . . . . . 37 Most Active Sensors:. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 Adding Forms (Filters) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38 Adding Tokens to Search Strings. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39 Adding User Input Forms. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40 GeoIP Maps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 iplocation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 geostats. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 Adding Drilldowns . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 2 www.fireeye.com Requirements. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 Supporting File Location: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 How to Import Support Files:. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 Drilldown by Event ID. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 Supporting files on the server:. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 inpage_drilldown_form.css. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 inpage_drilldown_form.js . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51 Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 Troubleshooting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54 Using Curl. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54 Splunk Search:. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55 Special Thanks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 About FireEye . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 Appendix A. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 3 www.fireeye.com Introduction Are you a Splunk ninja and now have a FireEye appliance? If so, our previous introductory guide (http:// www.fireeye.com/resources/pdfs/FireEye-Splunk-intro-to-integration-guide.pdf) and this intermediate guide should help you understand custom FireEye and Splunk integration options in no time. The previous introductory paper walks users through integrating the devices via syslog and some simple Splunk data carving. This paper extends that knowledge by showing users how to consume more in-depth FireEye (XML and JSON) data via HTTP POST and how to use some of Splunk’s advanced features to build a more robust dashboard. Those readers who want to quickly arrive at one possible integration solution should take note of the Current Integration Efforts section below or the Universal Parser section and then use the sample code within Appendix A. Current Integration Efforts If your organization is using the latest version of Splunk (6.x), try out our free FireEye App for Splunk Enterprise v3 (http://apps.splunk.com/app/1845/). This new app provides increased flexibility by supporting multiple FireEye appliances as well as multiple protocols and formats for sending data to Splunk. This app may not be fully backward compatible because it takes advantage of many Splunk 6.x features that were not previously available. If your organization is still using Splunk version 4.x or 5.x, you can easily download and use the free—but unsupported—Splunk for FireEye v2 app to integrate the two technologies. This Splunk app utilizes and parses FireEye’s rich extended XML output. This downloadable app is available here: https://apps.splunk.com/app/409/. The rest of this article is written for those that want to start from scratch or start from one of the above apps and learn to customize them. This article will outline various protocols and formats available from FireEye and explore the parsing options provided by Splunk. Creating Advanced Connectors In our previous introductory guide to integrating FireEye and Splunk, we covered creating connectors between the appliances using CEF or CSV format sent via syslog. When attempting to pass a more robust format such as extended XML or JSON via syslog, we discovered that the message was being prematurely truncated. To see the solution, download our new FireEye for Splunk Enterprise v3 app and check out the props.conf file. In this paper we will show how to use Splunk’s RESTful API to pass event data in XML or JSON format using an encrypted HTTPS POST. The steps below should assist in the setup. 4 www.fireeye.com Splunk Listener A default installation of Splunk 6 or later should automatically be listening via the RESTful API on port 8089. However, this can be verified by navigating to this API using a standard web browser: https://<SplunkBox>:8089 Figure 1: Splunk RESTful API is available on the default port 8089 If for whatever reason, this service is not available, verify the port number using the following steps: • Using a web browser, log in to the Splunk web interface: http://<SplunkBox>:8000 • Username: <admin account> • Password: <password> 5 www.fireeye.com Set up the Splunk listener: • Click the "Settings" hyperlink in the top right-hand corner of Splunk • Under "System", click “System settings" • Click “General settings” • Note the value in the “Management port” field Figure 2 : The port that Splunk uses for its RESTful API Splunk Role We now want to create a user in Splunk that will be used for passing the RESTful API data. However, there is currently no predefined Splunk role that can perform the job while adhering to the principle of least privilege. We could just assign our new user the “admin” role, but this would create a more severe situation should this account ever become compromised. The following instructions will create a Splunk role that has only the ability to accept data via the RESTful API: • Log into the Splunk web UI with an admin account • Click “Settings -> Users and authentication -> Access controls” • Click “Roles” -> Click the "New" button • Role Name: RESTfulAPI • Capabilities: edit_tcp 6 www.fireeye.com Splunk User Now that we have created a secure role, we need to create an account that will be used for authentication to post our event data. Note: Make sure the account name is alphanumeric only (no whitespaces) Example username: fireeye • Again, log into the Splunk web UI with an admin account • Click “Settings -> Users and authentication -> Access controls” • Click “Users” -> Click the "New" button • Fill in the required data • Privilege Note: Remember to use our newly created “restfulapi” role • Click the "Save" button Figure 3: Creating the Splunk admin account that will accept our HTTP POST messages. 7 www.fireeye.com FireEye Data Now that Splunk is listening and ready for data, we have to configure FireEye to send HTTP POST data to the connector. As mentioned in our introductory paper, the FireEye appliances are very flexible regarding notification output and support the following formats using HTTP POST: Text – Normal JSON – Normal XML – Normal Text – Concise JSON – Concise XML – Concise Text – Extended JSON – Extended XML – Extended In contrast, when sending data using syslog, all of the above formats are supported with the addition of CEF, LEEF, and CSV. Don’t worry though, these three additional formats should not be needed because other formats provide more robust data. For our first example, we will use Extended JSON—but this does not necessarily mean that it is the best format. It is just one possible option (see the “Parsing Other Formats” section for more details as to why we are selecting JSON over XML). Complete the following steps to send data to Splunk using extended JSON via HTTP POST: • Log into the FireEye appliance with an administrator account • Click “Settings” • Click “Notifications” • Click the “http” hyperlink • Make sure the "Event type" check box is selected • If the Global HTTP Settings are already set—leave them Next to the "Add HTTP Server" button, type "SplunkHTTP". Then click the "Add HTTP Server" button. In the newly created “SplunkHTTP” entry, ensure that the following check boxes are selected: • Enabled • Auth • SSL Enable 8 www.fireeye.com Enter the following per instance settings (which will override the global setting above): Server URL: https://<SplunkAD.DR.ESS>:<PORT>/services/receivers/simple? host=<FireEyeAddress>&source=wmps&sourcetype=fe_json • Username: fireeye (or username created in Splunk) • Password: <password created above in Splunk> Note: The default port used above is 8089—unless it has been changed. Remember to click the “Update” button when finished. Figure 4: Steps to configure the FireEye appliance to send data to Splunk 9 www.fireeye.com Now test the sending and receiving of notifications on the same FireEye Notifications page by clicking the "Test-Fire" button at the bottom. Flip back over to the Splunk interface and check out the raw event data. FireEye events will show up under “Search -> Data Summary” button or by typing sourcetype=fe_json in the Search box. Figure 5: The Splunk dashboard now shows events If raw data is not present, skip down to the “Troubleshooting” section at the bottom of this guide. 10 www.fireeye.com Examining a Raw Event Now that the connectors are working, we can view the raw data. Pro-tip: FireEye JSON and XML notifications changed in version 7.1 of the appliance from single line to multiline events. This affects Splunk’s native ability to parse the events; thus, we will need to create a custom sourcetype for Splunk to handle the change. Single Line JSON If using a FireEye appliance prior to software version 7.1 (which uses single line JSON as shown below), notice that Splunk will natively know when to split the packets. After clicking on the Data Summary button or searching for “FireEye”, the raw JSON alert notification should be present. The events will look similar to the following: {"msg": "extended", "product": "Web MPS", "version": "7.0.0.138133","appliance": "WebMPS.localdomain", "alert": {"src": {"mac":"XX:XX:XX:XX:XX:XX", "ip": "169.250.0.1", "host": "NA-testing.fe-notify-examples.com", "vlan": "0", "port": "10"}, "severity": "majr", "alert- url": "https:// WebMPS.localdomain/event_stream/events_for_bot?inc_id=1", "explanation": {"target-os": "WindowsXYZ", "protocol": "tcp", "service": "FireEye-TestEvent EA Service", "analysis": "replay", "cnc-services": {"cnc- service": [{"protocol": "tcp", "port": "200", "channel": "FireEye-TestEvent Channel 1", "address": "FireEye-TestEvent.example.com"}, {"protocol": "tcp", "port": "201", "channel": "cncs 2 channel fields", "address": "127.0.0.100"}]}, "target-application": "IEx123", "urls": "2", "malware- detected": {"malware": [{"content": "lms-0/contents", "url": "compl_0_1- someurl. x1y2z3.com", "type": "link", "name": "Suspicious.URL"}, {"content": "lms-0/contents", "url": "os-change-anomaly_0_1someurl.x1y2z3.com", "type":"link", "name": "Suspicious.URL"}, {"objurl": "compl_0_1-someurl.x1y2z3.com", "name": "FireEyeTestEvent-SIG"}]}}, "occurred": "2014-04-13T21:02:48Z","id": "1", "action": "notified", "dst": {"ip": "127.0.0.20", "mac":"XX:XX:XX:XX:XX:XX", "port": "20"}, "name": "webinfection"}} 11 www.fireeye.com At first, this data looks a bit confusing. Fortunately, the Splunk dashboard highlights and separates the data to make it a little easier to view and understand. By clicking the dropdown arrow, we see how Splunk natively parses JSON into fields that we can use to build our dashboard. Figure 6: Search term highlighting and Splunk parsed fields 12 www.fireeye.com Multiline JSON With the release of FireEye OS version 7.1, JSON and XML notifications are now multiline (aka pretty print)—meaning each line ends in a hard return and follow-on lines are indented as shown in the example below: { "msg": "extended", "product": "Web MPS", "version": "7.1.0.180577", "appliance": "WebMPS.localdomain", "alert": { "src": { "mac": "00:11:33:55:77:99", "ip": "169.250.0.1", "host": "DM-testing.fe-notify-examples.com", "vlan": "0", "port": "10" }, --SNIP--occurred When comparing this with the JSON from the single line section above, it is evident that this enhances the human readability. Unfortunately, it causes a problem with the native parser in Splunk. The hard returns cause Splunk to split the packet at the occurred field shown in the screenshot below. Figure 7: Multiline JSON is prematurely split in Splunk This will surely break our dashboards if we don’t account for the change in format. 13 www.fireeye.com Universal Parser To solve this, we can define our own sourcetype and specify where Splunk will break on events. But before we do this, let’s make sure we understand how line breaking works so we can optimize the parsing in Splunk: According to Splunk: “Splunk Enterprise determines event boundaries in two steps: 1. Line breaking, which uses the LINE_BREAKER attribute's regular expression value to split the incoming stream of bytes into separate lines. By default, the LINE_BREAKER is any sequence of newlines and carriage returns (that is, ([\r\n]+)). 2. Line merging, which only occurs when the SHOULD_LINEMERGE attribute is set to "true" (the default). This step uses all the other line merging settings (for example, BREAK_ONLY_ BEFORE, BREAK_ONLY_ BEFORE_DATE, MUST_BREAK_AFTER, etc.) to merge the previously-separated lines into events. If the second step does not run (because you set the SHOULD_LINEMERGE attribute to "false"), then the events are simply the individual lines determined by LINE_BREAKER. The first step is relatively efficient, while the second is relatively slow. If you are clever with the LINE_BREAKER regex, you can often make Splunk get the desired result by using only the first step, and skipping the second step. This is particularly valuable if a significant amount of your data consists of multi-line events.” Source: http://docs.splunk.com/Documentation/Splunk/6.0.3/Data/Indexmulti-lineevents Bottom line: In order to be fast and efficient, we want to be clever with our LINE_BREAKER regex so we can avoid relying on “SHOULD_LINEMERGE” capabilities. 14 www.fireeye.com Fortunately, we have created a regular expression that will act as a universal FireEye JSON parser. Perform the following steps to apply our universal parser: Step 1) Create the following file if it does not exist: $SPLUNK_HOME/etc/system/local/props.conf Step 2) Add the following contents: # Universal Handler for FireEye JSON notifications (pre and post FireEye OS 7.1) [fe_json] SHOULD_LINEMERGE = false LINE_BREAKER = ([\r\n]+)(^\{.*\}$) The regex above states that one or more carriage returns and line feeds can exist followed by an event that starts with ‘{‘ and ends with ‘}’ with anything in between. Step 3) Restart splunkd: $SPLUNK_HOME/bin/splunk restart splunkd After splunkd is restarted, all FireEye events sent to Splunk with a sourcetype of fe_json will be properly parsed as shown below: Figure 8: After applying a custom sourcetype, both the pre and post 7.1 FireEye JSON notifications parse correctly 15 www.fireeye.com Now that we have whole events, regardless of the FireEye OS version, let’s look at carving the data. In order to replicate the FireEye dashboard using JSON, we need certain fields to map properly. The JSON fields map as follows: FireEye Field Type ID File Type Malware Severity Time (UTC) Source IP Target IP MD5 URL (malware callback, domain match, malware object) URL (web infection) Location Splunk Field alert.name alert.id alert.explanation.malware-detected.malware.type alert.explanation.malware-detected.malware.name alert.severity alert.occurred alert.src.ip alert.dst.ip alert.explanation.malware-detected.malware.md5sum alert.explanation.cnc-services.cnc-service{}.address alert.explanation.cnc-services.cnc-service.address Not Passed The fields above will provide what is necessary to replicate the FireEye dashboard. However, in our introductory article we extended our FireEye dashboard to include some other useful fields. The other useful JSON fields map as follows: FireEye Field Action taken Protocol Source port Destination port FireEye alert URL 16 www.fireeye.com Splunk Field alert.action (may indicate blocked) alert.explanation.protocol alert.src.port alert.dst.port alert.alert-url (useful for linking to FE event) Now that we know all of these fields and what they map to in Splunk, we can once again replicate the FireEye dashboards using JSON (via HTTP POST) instead of using syslog as we did in our introductory guide. The final dashboard using JSON will be provided at the end of the article in the Appendix section. For a quick Splunk tutorial on carving incoming data, see our introductory FireEye/Splunk paper for the following topics which will not be repeated in this guide: • How to Replicate a FireEye Dashboard -- Simple Searches -- Piping Search Results -- Using Regular Expressions -- Using Conditionals • If Statement • Case Statement -- Sorting Searches -- Renaming the Columns -- Save As Dashboard Panel • Time Frames 17 www.fireeye.com Parsing Other Formats We mentioned earlier that FireEye is flexible in its notification output formats because it supports sending the following formats via HTTP POST: Text – Normal JSON – Normal XML – Normal Text – Concise JSON – Concise XML – Concise Text – Extended JSON – Extended XML – Extended After experimenting with the formats, it appears that extended XML may also be a robust alternative format to send to Splunk (via HTTP POST) due to its verbosity and structure. We will briefly explore this option in this paper, but we recommend sticking with the extended JSON solution we have outlined. As we will learn further down, there are still some challenges to overcome with XML. These points will not be covered in this paper; however, one possible solution is present in the latest FireEye App for Splunk Enterprise. Experimenting with XML If you too want to experiment with XML, we have to first change the FireEye notification format to XML. This is a pretty easy change in the FireEye device. This is done by going to “Settings”, “Notifications”, and then clicking “HTTP”. FireEye provides the ability to change the default format for all of the HTTP servers or the default can be overridden with a per server entry. Here, we will configure a per server entry that will apply for this Splunk server only. We also recommend changing the sourcetype to read fe_xml instead fe_json New server URL: https://<SplunkAD.DR.ESS>:<PORT>/services/receivers/ simple?host=<FireEyeAddress>&s ource=wmps&sourcetype=fe_xml 18 www.fireeye.com Remember to click the “Update” button when finished. Finally, fire off a test event so there is XML data to look at in Splunk. Figure 9: Changing the FireEye appliance to use XML for Splunk event notification We can inspect an XML field with the following Splunk search: “sourcetype=fe_xml” XML has the same issue that JSON experienced. FireEye OS 7.1 and later uses “pretty print” to display the event notification over multiple lines. Compare the difference in the examples below. 19 www.fireeye.com Single Line XML A typical single line XML (pre FE OS 7.1) event appears similar to the following: <?xml version="1.0" encoding="utf-8"?><alerts appliance="fireeye- wmps.local" msg="extended" product="Web MPS" version="7.0.2.156588" xmlns="http://www.fireeye.com/alert/2011/ AlertSchema" xmlns:xsi="http:// www.w3.org/2001/ XMLSchema-instance" xsi:schemaLocation="http://www. fireeye. com/alert/2011/AlertSchema FireEyeAlert.xsd"><alert id="691256" name="malware-object" severity="majr"><explanation analysis="binary" protocol="tcp"><malware-detected><malware name="FireEye-TestEvent- SIG"><downloaded-at>2014-04-01T11:50:59Z</ downloaded-at><md5sum>d41d8cd9 8f00b204e9800998ecf8427e</ md5sum><profile>winxp-sp2-rp</profile><executed- at>2014-0401T11:50:59Z</executed-at><application>explorer</ application></ malware></malware-detected><cnc-services><cnc-service port="200" protocol="tcp"><address>FireEye-TestEvent.example. com</ address><channel>FireEye-TestEvent Channel 1</channel></cncservice><cnc-service port="201" protocol="tcp"><address>127.0.0.100</ address><channel>cncs 2 channel fields</ channel></cnc-service></cnc- services><service>FireEye-TestEvent EA Service</service></explanation><src vlan="0"><ip>169.250.0.1</ ip><host>NA-testing.fe-notify-examples.com</ host><port>10</port><mac>XX:XX:XX:XX:XX:XX</mac></ src><dst><ip>127.0.0.20</ ip><mac>XX:XX:XX:XX:XX:XX</mac><port>20</ port></dst><occurred>2014-04- 01T11:50:57Z</occurred><alerturl>https://fireeye-wmps.local/event_stream/ events_for_bot?ma_ id=691256</alert-url><action>notified</action></alert></ alerts> 20 www.fireeye.com Multiline XML A typical multiline XML (FE OS 7.1 and later) event looks like the following: <?xml version="1.0" encoding="utf-8"?> <alerts appliance="WebMPS.localdomain" msg="extended" product="Web MPS" version="7.1.0.180577" xmlns="http://www.fireeye.com/alert/2013/ AlertSchema" xmlns:xsi="http://www. w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.fireeye.com/ alert/2013/AlertSchema FireEyeAlert.xsd"> <alert id="26" name="infection-match" severity="minr"> <explanation analysis="content" protocol="tcp"> <malware-detected> <malware name="FireEye-TestEvent-SIG-IM" sid="30" stype="bot-command"/> </malware-detected> </explanation> <src vlan="0"> <ip>169.250.0.1</ip> <host>IM-testing.fe-notify-examples.com</host> <port>10</port> --SNIP-- 21 www.fireeye.com Universal Parser To remedy this issue, we have once again created a regular expression that will act as a universal FireEye parser—but this time for XML events. Perform the following steps: Step 1) Create the following file if it does not exist: $SPLUNK_HOME/etc/system/local/props.conf Step 2) Add the following contents (below the fe_json if desired): # Universal Handler for FireEye JSON FireEye OS 7.1) notifications (pre and post [fe_json] SHOULD_LINEMERGE = false LINE_BREAKER = ([\r\n]+)(^\{.*\}$) # Universal Handler for FireEye XML notifications (pre and post FireEye OS 7.1) [fe_xml] SHOULD_LINEMERGE = false LINE_BREAKER = ([\r\n]+)(^\<\?xml.*\<\/alerts\>$) Step 3) Restart splunkd: $SPLUNK_HOME/bin/splunk restart splunkd Send another test event and observe that we have whole events—regardless of the FireEye OS version. After clicking on the arrow to expand the event, notice that Splunk attempts to extract data into fields, but is not able to extract all of the fields. There are a couple of options at this point, but in this paper we will try to pipe our search through the xmlkv command. 22 www.fireeye.com According to Splunk, the xmlkv command “extracts xml key-value pairs”. The description is as follows: “Finds key value pairs of the form <foo>bar</foo> where foo is the key and bar is the value from the _raw key.” Using the included xmlkv command, let’s see what fields Splunk is able to parse: The XML fields map as follows: FireEye Field Type ID File Type Malware Severity Time (UTC) Source IP Target IP MD5 URL (malware callback, domain match, malware object) URL (web infection) Location Splunk Field name id type Not parsed with xmlkv (need regex) severity occurred Not parsed with xmlkv (need regex) ip md5sum address Not parsed with xmlkv (need regex) Not passed The other useful XML fields map as follows: FireEye Field Action taken Protocol Source port Destination port FireEye alert URL 23 www.fireeye.com Splunk Field action (may indicate blocked) Not parsed with xmlkv (need regex) Not parsed with xmlkv (need regex) port alert-url (useful for linking to FE event) Why are some of these fields not parsed via xmlkv when they were parsed in JSON? The data is obviously present in the raw packet. We identified the issue below: --SNIP-<src vlan="0"> <ip>169.250.0.1</ip> <host>NA-testing.fe-notify-examples.com</host> <port>10</port> <mac>XX:XX:XX:XX:XX:XX</mac> </src> <dst> <ip>127.0.0.20</ip> <mac>XX:XX:XX:XX:XX:XX</mac> <port>20</port> </dst> --SNIP— Notice that in both sections, the IP is identified by the <ip> tag. The xmlkv command will only recognize the last instance because it appears to overwrite all prior tags with the same name. The same issue occurs with the <mac> and <port> tags. The reason for this is due to a limitation in the xmlkv parser found here: $SPLUNK_HOME/etc/apps/search/bin/xmlkv.py The code snippet below overwrites previous keys with the latest value: for kvpair in XML_KV_RE.findall(rawOut): r[kvpair[0]] = kvpair[1] Summary of Differences It appears that FireEye sends comparable data with either format (JSON or XML). However, the current add-on xml parser in Splunk does not handle repeated tags. FireEye’s XML requires some custom parsing which will be covered in a later paper, but is currently used in the most recent FireApp for Splunk Enterprise App. Bottom line: Pick the format that makes the most sense for your organization. 24 www.fireeye.com Creating Apps Now that you have the data to start creating your dashboard, you may want to first separate it into its own Splunk App. This can be achieved manually or by using the Splunk App Builder. The easiest way to create an app is to follow the steps below: Log into Splunk Web as an admin and navigate to Apps > Manage Apps. 1. Click Create app. 2. Fill in the following data: -- Name: MyFireEyeApp -- Folder Name: myfireeyeapp -- Version: 1 -- Visible: Yes -- Author: <Your name> -- Template: barebones By default, none of the supporting directories are created without first creating a dashboard in the app. If you don’t already have a dashboard in mind that you will move to this app, you will need to create a quick dummy dashboard so you can practice customizing your app. To create a dummy (empty) dashboard, use the following steps: • Click “Apps” -> Select our newly-created FireEye app • Click the “Dashboards” link • Click the “Create New” button • Fill in the data • Click the “Create Dashboard” button 25 www.fireeye.com Moving a Dashboard If you have already completed a dashboard (maybe using our prior guide), you can move it to the app we just created. It is as easy as copy and paste. 1. Go to your current dashboard 2. Click “Edit” -> “Edit Source” 3. Highlight and copy all of the code in the text box 4. Go to your new FireEye App -> Dashboard 5. Create Dashboard 6. Fill in the data and click the “Create Dashboard” button 7. Enter the new dashboard 8. Click “Edit” -> “Edit Source” 9. Click in the code box and right click -> paste 10.Save the new dashboard Customizing an App Now that we have an app and a dashboard, it is time to customize. We will demonstrate this by changing the colors of the navigation bars and icons of the app. This next part requires a little under-the-hood work, but we will walk you through it. We need access to the Splunk server’s underlying OS and directories. If you are not the administrator of the server, you may need their assistance in creating or copying the required files. App Navigation Colors Notice that the colors of the FireEye app are still “Splunk green”, but this too is editable. For example, look at the before and after screenshots below: Before: Figure 10: App color is Splunk green 26 www.fireeye.com Figure 11: App navigation is Splunk green After: Figure 12: Custom FireEye appliance dark blue Figure 13: Custom FireEye appliance blue This customization is possible by editing the following file: $SPLUNK_HOME/etc/apps/fireeye/local/data/ui/nav/default.xml Default contents: <nav search_view="search" color="#65A637"> <view name="search" default='true' /> <view name="data_models" /> <view name="reports" /> <view name="alerts" /> <view name="dashboards" /> </nav> This file is currently controlling two aspects of the dashboard: 1. The default navigation links (Search, Pivot, Reports, Alerts, Dashboards) 2. The color of the navigation bars - Splunk green color is indicated above by: #65A637 We will change the color to match the dark blue in the FireEye 7.1 appliance. Using the following hex code, we can get a close color match: #21232E After color change: <nav search_view="search" color="#21232E"> <view name="search" default='true' /> <view name="data_models" /> <view name="reports" /> <view name="alerts" /> <view name="dashboards" /> </nav> Remember to restart splunkd when finished making changes: $SPLUNK_HOME/bin/splunk restart splunkd 27 www.fireeye.com App Icons It is subtle at first, but some may notice that the Apps dropdown and Apps Launcher are missing icons. Since we just created the app, Splunk has no default icons present. For example, look at the before and after screenshots below: Before: Figure 14: Our newly created app is missing icons Figure 15: App logo is just text After: Figure 16: Custom FireEye Icons 28 www.fireeye.com Figure 17: Custom FireEye Log For us to add app icons, they first need to be created, appropriately named, and added to a specific directory for Splunk to properly populate the dashboard. The directory and filenames are listed below: Splunk 6.0 Directory and files: Larger main app icon: $SPLUNK_HOME/etc/apps/<app_name>/static/appIcon.png $SPLUNK_HOME/etc/apps/<app_name>/ static/appIcon_2x.png Smaller icon in the Apps dropdown: $SPLUNK_HOME/etc/apps/<app_name>/static/appIconAlt.png $SPLUNK_HOME/etc/apps/<app_name>/static/appIconAlt_2x.png Application banner logo (right hand side of app): $SPLUNK_HOME/etc/apps/<app_name>/static/appLogo.png $SPLUNK_HOME/etc/apps/<app_name>/static/appLogo_2x.png Splunk 5.0 Directory and files (useful for backward compatibility): Larger main app icon: $SPLUNK_HOME/etc/apps/<app_name>/appserver/static/appIcon.png $SPLUNK_HOME/etc/apps/<app_name>/appserver/static/appIcon_2x.png Smaller icon in the Apps dropdown: $SPLUNK_HOME/etc/apps/<app_name>/appserver/static/appIconAlt.png $SPLUNK_HOME/etc/apps/<app_name>/appserver/static/appIconAlt_2x.png Application banner logo (right hand side of app): $SPLUNK_HOME/etc/apps/<app_name>/appserver/static/appLogo.png $SPLUNK_HOME/etc/apps/<app_name>/appserver/static/appLogo_2x.png Pro-tips: • Images are at least 165 pixels to provide a crisp icon, but resized by Splunk based on the name • All images should be transparent to account for mouseover color changes • Hard refresh the screen after populating the directory with the icons. Most browsers support a hard refresh by using Ctrl + F5 29 www.fireeye.com Dashboard Details Now that we have navigation colors and application icons, let’s put some finishing touches on the appearance of the dashboards. We can customize just about any portion of the dashboard using cascading style sheets (CSS)—even minor details such as the font size, 3D effect, and parts of the dashboard we could not modify using other configuration files. For example, look at the before and after screenshots below: Before: Figure 18: The standard dashboard colors After: Figure 19: Our customized dashboard 30 www.fireeye.com This detailed customization can be done in three easy steps. First, create a custom cascading style sheet (CSS). Then we will reference that from the simple XML in our dashboard. Finally, we will restart the splunkweb service. Follow the steps below to complete this activity: 1) Create a new CSS file called custom.css with the content below in the following location: $SPLUNK_HOME/etc/apps/<app name>/appserver/static/ If our app name from the above example was used then the path will be: $SPLUNK_HOME/etc/apps/myfireeyeapp/appserver/static/ custom.css: /* Set the background color of all of the nav bars to match the FireEye dashboard background color */ .footer, .header, .app-bar, .nav, .nav-pills, .navbar-inner, a.dropdown toggle{ background: #21232E !important; } /* Set the color of the hyperlink text in our dashboard to white for readability. Add 3-D effect with shadows */ .app-bar .nav-pills > li > a, .nav-footer > li > a { #color:#D12131 !important; color:white !important; text-shadow: -1px 0px black, 0px 1px black, 1px 0px black, 0px -1px black; font-size:14px !important; } /* If the FireEye logo (appLogo.png or appLogoWhite.png) does not exist the text will be the correct size and color */ div.app-name { color:#D12131 !important; text-shadow: -1px 0px black, 0px 1px black, 1px 0px black, 0px -1px black; font-size:26px !important; } 31 www.fireeye.com 2) Edit the dummy or copied dashboard source (Edit -> Edit source) and change: <form> to: <form stylesheet="custom.css"> - or <dashboard> to: <dashboard stylesheet="custom.css"> 3) From the command line of the Splunk server restart the splunkweb service: $SPLUNK_HOME/bin/splunk restart splunkweb 32 www.fireeye.com Sample FireEye Dashboards Now that we have walked through the process of sending data to Splunk, creating an app, and customizing the appearance, we will provide some dashboards that we have put together. Note: All of these queries use sourcetype=fe_json; if the sourcetype name was modified, please change the queries below as well. To add these dashboard panels to the blank FireEye dashboard, perform the following actions: • Copy and paste the search string into the Splunk search box • Click the “Save As” button and select “Dashboard Panel” • Select “Existing” Dashboard • Select our FireEye dashboard and give the panel a title (ex: Alerts, Callback Activity, etc. ) • Click “Save” NX (web MPS) The most useful chart in the FireEye dashboard is used to look at the raw events. This dashboard is replicated below. Alerts -> Alerts: Note: In the eval statement, all JSON fields must be referred to using single quotes (‘). This is most likely needed because the period character "." is normally used for string appends. sourcetype=fe_json | eval UrlHash=case ('alert.name'=="malwareobject",'alert.explanation.malware-detected.malware.md5sum', 'alert. name'=="web-infection", 'alert.explanation.malware-detected.malware{}. objurl', 'alert.name'=="malware-callback" OR 'alert.name'=="domainmatch",'alert.explanation.cnc-services.cnc-service.address')| sort -occurred | table alert.name, alert.id, alert.explanation.malwaredetected. malware.name, alert.severity, alert.occurred, alert. explanation.protocol, alert.src.ip, alert.src.port, alert.dst.ip, alert.dst.port, UrlHash | rename alert.name AS Type, alert.id AS ID, alert.explanation.malware-detected.malware.name AS Malware, alert. severity AS Severity, alert. occurred AS Occurred, alert.explanation. protocol AS Protocol, alert.src. ip AS "Source IP", alert.src.port AS "Source Port", alert.dst.ip AS "Target IP", alert.dst.port AS "Target Port", UrlHash AS "URL/Md5sum" 33 www.fireeye.com Notice that the Malware name for a web-infection event is missing: This is because the correct value was stored in an array: The fix for this issue requires parsing via custom regex and will be covered in a more advanced paper. Alerts -> Callback Activity: sourcetype=fe_json "alert.name"="malware-callback" | stats count(alert. explanation.cnc-services.cnc-service.address) as "Events", distinct_ count(alert.src.ip) as "Hosts", max(alert. occurred) as "Last Seen" by alert.explanation.cnc-services.cnc-service.address | table alert. explanation.cnc-services.cnc-service.address, locations, Events, Hosts, "Last Seen" | rename alert.explanation.cnc-services.cncservice.address as "C&C Server", locations as "Locations" | sort –"Last Seen" Time Frames: Our first guide illustrated how to add a time range picker—this is worth mentioning here again. Click the “Edit” drop down. Click “Edit Panels”. Click “Add Time Range Picker”. Select Last 24 Hours. Click the “Done” button. Figure 21: Adding a time range picker to our dashboard 34 www.fireeye.com Pro-tip: If for some reason, your time frame button is not working as expected (ours did not by default), you have overridden the time picker in your search. Here is how to fix it: Go to your dashboard. Click the “Edit” drop down. Click “Edit Panels”. Click the magnifying glass drop down, and select “Edit Search String”. In the “Time Range Scope” section, select the “Dashboard” button and click save. Now the “Time Range Picker” button will function as expected. Figure 22: Setting the Time Range Scope to use the dashboard instead of the search string time frame 35 www.fireeye.com Panels to Enhance Visibility Now that you have a Splunk dashboard that replicates the FireEye Dashboard, let’s go further by adding more panels that will enhance the network defender’s visibility into attacks. Splunk has many visualization features that allow users to build charts and graphs for trending and analytics. NX (web MPS) We can take some of the fields that we exposed in the FireEye dashboard above and create pie charts to summarize key data points. This can help gauge if an organization is experiencing an increase or lull in attacks, as well as identify trends in malware and Command and Control (C2) ports. Each chart below is optional and may depend on the organization or security team’s preferences. Severity Pie Chart: sourcetype=fe_json | chart count by alert.severity Select pie chart After typing in the search above, select the visualization tab, then pie chart. Click the “Save As” button, select “Dashboard Panel”, click the “Existing” Button. Select the FireEye Dashboard and provide a title of “Severity”. Select “View in Dashboard” to look at your new dashboard. Now, let’s move the graph to the top by clicking “Edit” -> “Edit Panels”. Drag the pie chart to the top of the screen. Click “Done” when finished. We will follow this same procedure to add the rest of the charts. Figure 23: Current dashboard after adding severity pie chart. 36 www.fireeye.com Malware Pie Chart: sourcetype=fe_json | chart count by alert.explanation.malwaredetected. malware.name Select pie chart Top 20 Most Active Source IPs: sourcetype=fe_json | top limit=20 alert.src.ip Select pie chart Top 20 Most Active Target IPs: sourcetype=fe_json | top limit=20 alert.dst.ip Select pie chart Top 20 Most Active Destination Ports: sourcetype=fe_json | top limit=20 alert.dst.port Select pie chart Most Active Sensors: sourcetype=fe_json | chart count by appliance Select pie chart After arranging all of the charts, the dashboard should look similar to the following: Figure 24: Current dashboard after adding all of the charts 37 www.fireeye.com Adding Forms (Filters) A Splunk form allows users to supply search terms within the dashboard to assist in carving data. This user interaction can take place via text boxes, dropdown menus, radio buttons, or search terms. We will illustrate how to add a wild card to one search below as an example, but we will also provide a Simple XML Dashboard in the appendix that will apply a wildcard search to the entire dashboard. Continue on to see how this works. Adding forms can be broken down into two steps: 1. Add tokens to search strings 2. Add user input forms 38 www.fireeye.com Adding Tokens to Search Strings Tokens are defined by using dollar signs ‘$’ around variable names. Let’s use our Alerts dashboard search as an example. Note the change in bold red font to compare the before and after. Before: sourcetype=fe_json | eval UrlHash=case ('alert. name'=="malware-object",'alert.explanation.malware-detected.malware. md5sum', 'alert.name'=="web-infection", 'alert.explanation.malwaredetected.malware{}.objurl', 'alert.name'=="malware-callback" OR 'alert.name'=="domain-match",'alert.explanation.cnc-services.cncservice.address')| sort-occurred | table alert.name, alert.id, alert. explanation.malware-detected. malware.name, alert.severity, alert.occurred, alert.explanation. protocol, alert.src.ip, alert.src.port, alert.dst.ip, alert.dst. port, UrlHash | rename alert.name AS Type, alert.id AS ID, alert. explanation.malware-detected.malware.name AS Malware, alert.severity AS Severity, alert.occurred AS Occurred, alert.explanation.protocol AS Protocol, alert.src.ip AS "Source IP", alert.src.port AS "Source Port", alert.dst.ip AS "Target IP", alert.dst.port AS "Target Port", UrlHash AS "URL/Md5sum After: sourcetype=fe_json $wild$ | eval UrlHash=case ('alert. name'=="malware- object",'alert.explanation.malware-detected.malware. md5sum', 'alert.name'=="web-infection", 'alert.explanation.malwaredetected.malware{}.objurl', 'alert.name'=="malware-callback" OR 'alert.name'=="domain- match",'alert.explanation.cnc-services.cncservice.address')| sort-occurred | table alert.name, alert.id, alert. explanation.malware-detected. malware.name, alert.severity, alert. occurred, alert.explanation.protocol, alert.src.ip, alert.src.port, alert.dst.ip, alert.dst.port, UrlHash | rename alert.name AS Type, alert.id AS ID, alert.explanation.malware-detected.malware.name AS Malware, alert.severity AS Severity, alert.occurred AS Occurred, alert.explanation.protocol AS Protocol, alert.src. ip AS "Source IP", alert.src.port AS "Source Port", alert.dst.ip AS "Target IP", alert.dst.port AS "Target Port", UrlHash AS "URL/Md5sum 39 www.fireeye.com Adding User Input Forms If you had a time range picker on your previous dashboard, you should remove it now. We will add it back in manually which will prevent some minor annoyances. We will add this wildcard search field above the very first row which will place it at the top of our dashboard. As a reminder, we can edit the XML by clicking on the “Edit” button and selecting “Edit Source”. Before: <form> <label>FireEye</label> <row> <chart> After: <form> <label>FireEye</label> <!-- Add time range picker --> <fieldset autoRun="True"> <input type="time" searchWhenChanged="true"> <default> <earliestTime>-24h@h</earliestTime> <latestTime>now</latestTime> </default> </input> <!-- Add Wildcard Search (Form) --> <input type="text" token="wild"> <label>Search</label> <default>*</default> <suffix/> </input> </fieldset> <row> 40 www.fireeye.com Figure 25: All of the combined pieces used to create the user input form Pro-tip: Be sure to add the $wild$ token to all search strings for all panels on the dashboard (charts, tables, graphs, etc). To operate the search, just change the Search field at the top of the page and search for whatever term is desired. Be sure to click the “Search” button when finished. To clear a previous search, enter an asterisk in the search field and click the “Search” button again. 41 www.fireeye.com Figure 26: Demonstrating the use of the wildcard search For more information see the following Splunk doc: http://docs.splunk.com/Documentation/Splunk/6.0.2/Viz/Buildandeditforms 42 www.fireeye.com GeoIP Maps Everyone loves a map with pretty dots on it. But how about a map with pie charts overlaid with malware distribution? This is possible using an easy two-step process outlined below: 1. Generate a search with latitude and longitude coordinates 2. Editing the simple XML, change the <chart> or <table> tag to <map> In our example below we will track where the attacks are originating, so we look at the destination IP address. However, it is possible to change the IP address to whatever suits your needs. Some may want to know which hosts are infected; thus they would map the source IP instead. Keep in mind, though, that RFC 1918 addresses do not have geoIP data associated with them. iplocation No Internet access is required to utilize Splunk’s iplocation command, which extracts location information using 3rd party geoIP databases. Syntax: <search> | iplocation <field of interest> JSON: sourcetype=fe_json | iplocation alert.dst.ip Source: http://docs.splunk.com/Documentation/Splunk/6.0.2/SearchReference/Iplocation geostats Now that we have the lat/long information from the iplocation command, we will feed that data into the geostats command, which according to Splunk: “Generate[s] statistics which are clustered into geographical bins to be rendered on a world map.” Source: http://docs.splunk.com/Documentation/Splunk/6.0.2/SearchReference/Geostats Our search string will look like the following: sourcetype=fe_json | iplocation alert.dst.ip | geostats latfield=lat, longfield=lon count by alert.explanation.malwaredetected.malware.name 43 www.fireeye.com After entering the data above in the search field, save it to the FireEye dashboard by selecting “Save As -> Dashboard Panel”. Select existing, choose the FireEye dashboard and call this GeoIP. When this new panel shows up on the dashboard, move it to the top by selecting “Edit -> Edit panels” and dragging the panel to the top. Now, edit the source by clicking “Edit Source”. Edit the simple XML and change the <chart> tag to <map>. Figure 27: Changing the table tag to map Once the tags are changed to map and the dashboard is saved, the GeoIP map will appear at the top of the dashboard. Please note that FireEye “Test-fire” events use RFC-1918 addresses and will not generate information on the map. 44 www.fireeye.com Figure 28: A GeoIP map at the top of our dashboard. If you are using CEF or CSV via syslog from our introductory paper, the CSV search string is provided below: CSV: CSV:\0:\FireEye | iplocation dst | geostats latfield=lat, longfield=lon count by sname 45 www.fireeye.com Figure 29: A GeoIP location map added to our dashboard maps the attacker IPs along with the threat statistics Pro-tip: We have experienced instances in which the time range picker has caused the geoIP to stop functioning. The best solution we found was to remove the time range picker, add the geoIP, and then add in the time range picker last. In our final Simple XML dashboard that we provide, we will have both geoIP and a functioning time range picker. 46 www.fireeye.com Adding Drilldowns Fortunately, when a user clicks any of the fields in our newly-created dashboard, by default Splunk will pivot around the query that finds the event of interest. Unfortunately, the basic default drilldown behavior is to show the raw data packet—which may not always be pretty. The upside is that this behavior can be overridden by using custom drilldowns. One option is to use <drilldown> tags. However, we will go a step beyond this by using JavaScript to control extracted fields and CSS to control visibility of a detail pane. Requirements Unless we are able to embed our JavaScript and CSS into the Splunk Simple XML page, we will need access to the Splunk server’s underlying OS. If you are not the administrator of the server, you may need the Splunk administrator’s assistance in creating or copying the files. Either way, we need to know where to put the files on the Splunk server so they can be referenced. Supporting File Location: Splunk dashboards can reference CSS and JavaScript files if they are placed in the following directory: $SPLUNK_HOME/etc/apps/<app_name>/appserver/static/ For example, our Splunk dashboard was created in the FireEye App directory, so its path will be: $SPLUNK_HOME/etc/apps/myfireeyeapp/appserver/static/ We will provide example files in the section called: “Drilldown by Event ID”, but first check out the following pro-tip. Pro-tip: After creating new files in the static directory, remember to restart splunkweb: $SPLUNK_HOME/bin/splunk restart splunkweb Simple modifications of files that already exist will not require a splunkweb restart. However, they will require a browser hard refresh to make sure a locally cached version of the JavaScript or CSS file is not used. Most browsers support a hard refresh by using Ctrl + F5. 47 www.fireeye.com How to Import Support Files: According to Splunk: “Use the script and stylesheet attributes to <dashboard> or <form> tags to import a JavaScript or CSS file from the default location for an app. You can also reference script and CSS files from other apps.” For example: Import files from the same app <dashboard script="myScript.js" stylesheet="myStyles.css"> . . . </dashboard> Source: http://docs.splunk.com/Documentation/Splunk/6.0.2/Viz/OverviewofSimplifiedXML Drilldown by Event ID To demonstrate how this works, we will use a small demo page showing our FireEye alerts. This will require some Simple XML modification and two supporting files on the server. Simple XML: <form script="inpage_drilldown_form.js" stylesheet="custom.css"> <label>Drilldown demo</label> <fieldset autoRun="True" submitButton="false"> <!-- Add Time range picker --> <input type="time" searchWhenChanged="true"> <default> <earliestTime>-24h@h</earliestTime> <latestTime>now</latestTime> </default> </input> <!-- Add Wildcard Search (Form) --> <input type="text" token="wild"> <label>Search</label> <default>*</default> <suffix/> </input> <!-- Input to store the drilldown value. Hidden using javascript when the dashboard is loaded. --> <input type="text" token="ID" searchWhenChanged="true"/> </fieldset> <row> 48 www.fireeye.com <table id="master"> <title>Alerts</title> <searchString>sourcetype=fe_json $wild$ | eval UrlHash=case ('alert. name'=="malware-object",'alert. explanation.malware-detected.malware. md5sum', 'alert. name'=="web-infection", 'alert.explanation.malware- detected. malware{}.objurl', 'alert.name'=="malware-callback" OR 'alert. name'=="domain-match",'alert.explanation.cncservices.cnc-service. address')| sort -occurred | table alert.name, alert.id, alert.explanation. malware-detected. malware.name, alert.severity, alert.occurred, alert. explanation.protocol, alert.src.ip, alert.src.port, alert. dst.ip, alert. dst.port, UrlHash | rename alert.name AS Type, alert.id AS ID, alert. explanation.malware-detected.malware. name AS Malware, alert.severity AS Severity, alert.occurred AS Occurred, alert.explanation. protocol AS Protocol, alert.src.ip AS "Source IP", alert.src.port AS "Source Port", alert.dst.ip AS "Target IP", alert.dst.port AS "Target Port", UrlHash AS "URL/Md5sum"</searchString> <earliestTime>-24h</earliestTime> <latestTime>now</latestTime> </table> </row> <row> <table id="detail"> <title>Alert Detail: $ID$</title> <searchTemplate>sourcetype=fe_json alert.id=$ID$ $wild$ | table _raw, alert.alert-url</searchTemplate> <earliestTime>-24h</earliestTime> <latestTime>now</latestTime> </table> </row> </form> 49 www.fireeye.com Supporting files on the server: inpage_drilldown_form.css #field3 { /* Hide all form fields */ display: none; } Since this is minor, we can add it to our previous custom.css: /* Set the background color of all of the nav bars to match the FireEye dashboard background color */ .footer, .header, .app-bar, .nav, .nav-pills, .navbar-inner, a.dropdown- toggle { background: #21232E !important; } /* Set the color of the hyperlink text in our dashboard to white for readability. Add 3-D effect with shadows */ .app-bar .nav-pills > li > a, .nav-footer > li > a { #color:#D12131 !important; color:white !important; text-shadow: -1px 0px black, 0px 1px black, 1px 0px black, 0px -1px black; font-size:14px !important; } /* If the FireEye logo (appLogo.png or appLogoWhite.png) does not exist the text will be the correct size and color */ div.app-name { color:#D12131 !important; text-shadow: -1px 0px black, 0px 1px black, 1px 0px black, 0px -1px black; font-size:26px !important; } /* Hide the drilldown "Details" box when it is unpopulated */ #field3 { /* Hide all form fields */ display: none; } 50 www.fireeye.com inpage_drilldown_form.js require(['jquery','underscore','splunkjs/mvc','util/ console','splunkjs/mvc/ simplexml/ready!'], function($, _, mvc, console){ // Get a reference to the dashboard panels var masterView = mvc. Components.get('master'); var detailView = mvc.Components. get('detail'); var unsubmittedTokens = mvc.Components. get('default'); var submittedTokens = mvc. Components.get('submitted'); var urlTokens = mvc.Components.get('url'); if(!submittedTokens.has('ID')) { // if there's no value for the $sourcetype$ token yet, hide the dashboard panel of the detail view detailView.$el.parents('.dashboard-panel').hide(); } submittedTokens.on('change:ID', function(){ // When the token changes... if(!submittedTokens.get('ID')) { // ... hide the panel if the token is not defined detailView.$el.parents('.dashboard-panel').hide(); } else { // ... show the panel if the token has a value detailView.$el.parents('.dashboard-panel').show(); } }); masterView.on('click', function(e) { e.preventDefault(); var newValue = e.data['row.ID']; // Submit the value for the sourcetype field unsubmittedTokens. set('form.ID', newValue); submittedTokens.set(unsubmittedTokens. toJSON()); urlTokens.saveOnlyWithPrefix('form\\.', unsubmittedTokens.toJSON(), { replaceState: false }); }); }); 51 www.fireeye.com The behavior when first visiting the page shows no detail pane: Figure 30: No events clicked yet, thus the detail pane is hidden from view After the event is clicked, a detail pane can be seen below: Figure 31: Detailed pane drilldown shown above This event will be displayed until another event is clicked. The details pane can be hidden by refreshing the page. 52 www.fireeye.com Conclusion Using a FireEye device, a free demo of Splunk, and Google, we were able to investigate the different HTTP POST formats for replicating FireEye Dashboards in Splunk. In writing this guide, we have discovered that there are many ways to tackle integrating these two devices because FireEye provides robust event notification and Splunk is flexible when ingesting and presenting these events. We are sharing this information in the hope that you will be inspired by seeing even just a fraction of what is possible. Who knows, it may save you a little time as well. We would love to hear your feedback, including sample FireEye dashboards and any pro-tips you have for consuming and displaying data in Splunk. 53 www.fireeye.com Troubleshooting There are many methods that can be used to troubleshoot connection issues. Below is just one example: Using Curl Using any Linux host, or Cygwin on Windows perform the following: Step 1) echo test > test.xml Step 2) curl -k -g --user <username>:<password> --data-binary @ test.xml "https://<splunkServer>:<port>/services/receivers/ simple?host=<SendingIP>&source= fe_test&sourcetype=fe_xml" Ex: curl -k -g --user fireeye:password --data-binary @test.xml "https://192.168.33.152:8089/services/receivers/simple?host=192.168.33 .152&source= fe_test&sourcetype=fe_xml" Result: You should see something similar to the following response from Splunk after issuing the command above: <?xml version="1.0" encoding="UTF-8"?> <response> <results> <result> <field k="_index"> <value> <text>default</text> </value> </field> <field k="bytes"> <value> <text>4</text> </value> </field> <field k="host"> <value> 54 www.fireeye.com <text>Source IP Address here</text> </value> </field> <field k="source"> <value> <text>fe_alert</text> </value> </field> <field k="sourcetype"> <value> <text>fe_xml</text> </value> </field> </result> </results> </response> Splunk Search: After the data is successfully sent to Splunk, you should be able to search for it using the following search term: source=fe_test You should see “test” as the message body because it was in the body of test.xml 55 www.fireeye.com About the Author Tony Lee has more than ten years of professional experience pursuing his passion in all areas of information security. He is currently a Technical Director at Mandiant, a FireEye Company, advancing many of the network penetration testing service lines. His interests of late are kiosk hacking, post exploitation tactics, and malware research. As an avid educator, Tony has instructed thousands of students at many venues worldwide, including government, universities, corporations, and conferences such as Black Hat. He takes every opportunity to share knowledge as a contributing author to Hacking Exposed 7, frequent blogger, and a lead instructor for a series of classes. He holds a Bachelor of Science degree in computer engineering from Virginia Polytechnic Institute and State University and a Master of Science degree in security informatics from The Johns Hopkins University. Email: Tony.Lee -at- FireEye.com Linked-in: http://www.linkedin.com/in/tonyleevt Special Thanks Dennis Hanzlik Dan Dumond Ian Ahl Dave Pany Karen Kukoda Leianne Lamb Brian Stoner Gunpreet Singh Kate Scott About FireEye FireEye has invented a purpose-built, virtual machine-based security platform that provides realtime threat protection to enterprises and governments worldwide against the next generation of cyber attacks. These highly sophisticated cyber attacks easily circumvent traditional signature-based defenses, such as next-generation firewalls, IPS, anti-virus, and gateways. The FireEye Threat Prevention Platform provides real-time, dynamic threat protection without the use of signatures to protect an organization across the primary threat vectors and across the different stages of an attack life cycle. The core of the FireEye platform is a virtual execution engine, complemented by dynamic threat intelligence, to identify and block cyber attacks in real time. FireEye has over 2,500 customers across 65 countries, including over 150 of the Fortune 500. FireEye, Inc. | 1440 McCarthy Blvd. Milpitas, CA 95035 | 408.321.6300 | 877.FIREEYE (347.3393) | [email protected] | www.fireeye.com © 2014 FireEye, Inc. All rights reserved. FireEye is a registered trademark of FireEye, Inc. All other brands, products, or service names are or may be trademarks or service marks of their respective owners. SPT.CSS.EN-US.102014 Appendix A Sample code to build a robust dashboard of maps, charts, forms, and detailed drilldown panels. custom.css /* Set the background color of all of the nav bars to match the FireEye dashboard background color */ .footer, .header, .app-bar, .nav, .nav-pills, .navbar-inner, a.dropdown- toggle { background: #21232E !important; } /* Set the color of the hyperlink text in our dashboard to white for readability. Add 3-D effect with shadows */ .app-bar .nav-pills > li > a, .nav-footer > li > a { #color:#D12131 !important; color:white !important; text-shadow: -1px 0px black, 0px 1px black, 1px 0px black, 0px -1px black; } font-size:14px !important; /* If the FireEye logo (appLogo.png or appLogoWhite.png) does not exist the text will be the correct size and color */ div.app-name { color:#D12131 !important; text-shadow: -1px 0px black, 0px 1px black, 1px 0px black, 0px -1px black; } font-size:26px !important; 57 www.fireeye.com /* Hide the drilldown "Details" box when it is unpopulated */ #field3 { /* Hide all form fields */ display: none; } Simple XML: <form script="inpage_drilldown_form.js" stylesheet="custom.css"> <label>FireEye JSON - With Drilldown and Filter</label> <fieldset autoRun="True"> <input type="time" searchWhenChanged="true"> <default> <earliestTime>-24h@h</earliestTime> <latestTime>now</latestTime> </default> </input> <!-- Add Wildcard Filter --> <input type="text" token="wild"> <label>Search</label> <default>*</default> <suffix/> </input> <!-- Used for dropdown - Input field hidden using javascript. <div id = #field3 --> <input type="text" token="ID" searchWhenChanged="true"/><!-Add time range picker --> </fieldset> <row> <map> <title>GeoIP Dest</title> <searchString>sourcetype=fe_json $wild$ | iplocation alert.dst.ip | geostats latfield=lat, longfield=lon count by alert.explanation. malware- detected.malware.name</searchString> <earliestTime>$earliest$</earliestTime> <latestTime>$latest$</latestTime> </map> </row> <row> <chart> <title>Severity</title> 58 www.fireeye.com <searchString>sourcetype=fe_json $wild$ | chart count by alert. severity</searchString> <earliestTime>$earliest$</earliestTime> <latestTime>$latest$</latestTime> <option name="charting.axisTitleX.visibility">visible</option> <option name="charting.axisTitleY.visibility">visible</option> <option name="charting.axisX.scale">linear</option> <option name="charting.axisY.scale">linear</option> <option name="charting.chart">pie</option> <option name="charting.chart.nullValueMode">gaps</option> <option name="charting.chart.sliceCollapsingThreshold">0.01</option> <option name="charting.chart.stackMode">default</option> <option name="charting.chart.style">shiny</option> <option name="charting.drilldown">all</option> <option name="charting.layout.splitSeries">0</option> <option name="charting.legend. labelStyle. overflowMode">ellipsisMiddle</ option> <option name="charting.legend.placement">right</option> </chart> <chart> <title>Malware</title> <searchString>sourcetype=fe_json $wild$ | chart count by alert. explanation.malware-detected.malware.name</searchString> <earliestTime>$earliest$</earliestTime> <latestTime>$latest$</latestTime> <option name="charting.axisTitleX.visibility">visible</option> <option name="charting.axisTitleY.visibility">visible</option> <option name="charting.axisX.scale">linear</option> <option name="charting.axisY.scale">linear</option> <option name="charting.chart">pie</option> <option name="charting.chart.nullValueMode">gaps</option> <option name="charting.chart.sliceCollapsingThreshold">0.01</option> <option name="charting.chart.stackMode">default</option> <option name="charting.chart.style">shiny</option> <option name="charting.drilldown">all</option> <option name="charting.layout.splitSeries">0</option> <option name="charting.legend.labelStyle. overflowMode">ellipsisMiddle</option> <option name="charting.legend.placement">right</option> </chart> <chart> <title>Top 20 Source</title> 59 www.fireeye.com <searchString>sourcetype=fe_json $wild$ | top limit=20 alert. src.ip</ searchString> <earliestTime>$earliest$</earliestTime> <latestTime>$latest$</latestTime> <option name="charting.axisTitleX.visibility">visible</option> <option name="charting.axisTitleY.visibility">visible</option> <option name="charting.axisX.scale">linear</option> <option name="charting.axisY.scale">linear</option> <option name="charting.chart">pie</option> <option name="charting.chart.nullValueMode">gaps</option> <option name="charting.chart.sliceCollapsingThreshold">0.01</option> <option name="charting.chart.stackMode">default</option> <option name="charting.chart.style">shiny</option> <option name="charting.drilldown">all</option> <option name="charting.layout.splitSeries">0</option> <option name="charting.legend.labelStyle. overflowMode">ellipsisMiddle</option> <option name="charting.legend.placement">right</option> </chart> <chart> <title>Top 20 Target</title> <searchString>sourcetype=fe_json $wild$ | top limit=20 alert. dst.ip</ searchString> <earliestTime>$earliest$</earliestTime> <latestTime>$latest$</latestTime> <option name="charting.axisTitleX.visibility">visible</option> <option name="charting.axisTitleY.visibility">visible</option> <option name="charting.axisX.scale">linear</option> <option name="charting.axisY.scale">linear</option> <option name="charting.chart">pie</option> <option name="charting.chart.nullValueMode">gaps</option> <option name="charting.chart.sliceCollapsingThreshold">0.01</option> <option name="charting.chart.stackMode">default</option> <option name="charting.chart.style">shiny</option> <option name="charting.drilldown">all</option> <option name="charting.layout.splitSeries">0</option> <option name="charting.legend.labelStyle. overflowMode">ellipsisMiddle</option> <option name="charting.legend.placement">right</option> </chart> <chart> <title>Top 20 Dest Ports</title> <searchString>sourcetype=fe_json $wild$ | top limit=20 alert.dst. 60 www.fireeye.com port</searchString> <earliestTime>$earliest$</earliestTime> <latestTime>$latest$</latestTime> <option name="charting.axisTitleX.visibility">visible</option> <option name="charting.axisTitleY.visibility">visible</option> <option name="charting.axisX.scale">linear</option> <option name="charting.axisY.scale">linear</option> <option name="charting.chart">pie</option> <option name="charting.chart.nullValueMode">gaps</option> <option name="charting.chart.sliceCollapsingThreshold">0.01</option> <option name="charting.chart.stackMode">default</option> <option name="charting.chart.style">shiny</option> <option name="charting.drilldown">all</option> <option name="charting.layout.splitSeries">0</option> <option name="charting.legend.labelStyle. overflowMode">ellipsisMiddle</option> <option name="charting.legend.placement">right</option> </chart> <chart> <title>Sensor</title> <searchString>sourcetype=fe_json $wild$ | chart count by appliance</ searchString> <earliestTime>$earliest$</earliestTime> <latestTime>$latest$</latestTime> <option name="charting.axisTitleX.visibility">visible</option> <option name="charting.axisTitleY.visibility">visible</option> <option name="charting.axisX.scale">linear</option> <option name="charting.axisY.scale">linear</option> <option name="charting.chart">pie</option> <option name="charting.chart.nullValueMode">gaps</option> <option name="charting.chart.sliceCollapsingThreshold">0.01</option> <option name="charting.chart.stackMode">default</option> <option name="charting.chart.style">shiny</option> <option name="charting.drilldown">all</option> <option name="charting.layout.splitSeries">0</option> <option name="charting.legend.labelStyle. overflowMode">ellipsisMiddle</option> <option name="charting.legend.placement">right</option> </chart> </row> <row> <table id="master"> <title>Alerts</title> 61 www.fireeye.com <searchString>sourcetype=fe_json $wild$ | eval UrlHash=case ('alert. name'=="malware-object",'alert. explanation.malware-detected.malware. md5sum', 'alert.name'=="webinfection", 'alert.explanation.malware- detected.malware{}. objurl', 'alert.name'=="malware-callback" OR 'alert. name'=="domainmatch",'alert.explanation.cnc-services.cnc-service. address')| sort -occurred | table alert.name, alert.id, alert.explanation. malwaredetected.malware.name, alert.severity, alert.occurred, alert.src. ip, alert.src.port, alert.dst.ip, alert.dst.port, UrlHash | rename alert. name AS Type, alert.id AS ID, alert.explanation.malwaredetected.malware. name AS Malware, alert.severity AS Severity, alert.occurred AS Occurred, alert.src.ip AS "Source IP", alert.src. port AS "Source Port", alert.dst.ip AS "Target IP", alert.dst.port AS "Target Port", UrlHash AS "URL/ Md5sum"</ searchString> <earliestTime>$earliest$</earliestTime> <latestTime>$latest$</latestTime> <option name="wrap">true</option> <option name="rowNumbers">false</option> <option name="dataOverlayMode">none</option> <option name="drilldown">row</option> <option name="count">10</option> </table> </row> <row> <table id="detail"> <title>Alert Detail: $ID$</title> <searchString>sourcetype=fe_json alert.id=$ID$ $wild$ | table _raw, alert.alert-url</searchString> <earliestTime>$earliest$</earliestTime> <latestTime>$latest$</latestTime> <option name="wrap">true</option> <option name="rowNumbers">false</option> <option name="dataOverlayMode">none</option> <option name="drilldown">row</option> <option name="count">10</option> </table> </row> <row> <table> <title>Callbacks</title> <searchString>sourcetype=fe_json "alert.name"="domain-match" $wild$ | stats count(alert.explanation.cnc-services.cnc-service.address) 62 www.fireeye.com as "Events", distinct_count(alert.src.ip) as "Hosts", max(alert. occurred) as "Last Seen" by alert.explanation.cnc-services.cncservice.address | table alert.explanation.cnc-services.cnc-service. address, alert.explanation.cnc- services.cnc-service.location, Events, Hosts, "Last Seen" | rename alert. explanation.cnc-services. cnc-service.address as "C&C Server", alert. explanation.cncservices.cnc-service.location as "Locations" | sort –"Last Seen"</ searchString> <earliestTime>$earliest$</earliestTime> <latestTime>$latest$</latestTime> <option name="wrap">true</option> <option name="rowNumbers">false</option> <option name="dataOverlayMode">none</option> <option name="drilldown">row</option> <option name="count">10</option> </table> </row> </form> 63 www.fireeye.com
Similar documents
Splunk Tutorial
Splunk's ability to quickly analyze massive amounts of data enables you to summarize any set of search results in the form of interactive charts, graphs, and tables. Generate reports on-the-fly tha...
More information