From c40a3441a5d3ccbdbec3db97e10a4173c0edd95d Mon Sep 17 00:00:00 2001 From: Mike Cohen Date: Sun, 22 Sep 2024 00:09:32 +1000 Subject: [PATCH] Inline SVG and fix minor blog post typos. (#916) --- .../2024-09-10-release-notes-0.73/_index.md | 36 ++++++------- .../importing_offline_collection.svg | 7 ++- .../kapefiles_collection.svg | 7 ++- .../blog/2024/2024-09-12-timelines/_index.md | 51 ++++++++++--------- layouts/shortcodes/figure.html | 26 ++++++++++ static/css/theme-mine.css | 47 +++++++++++++++-- 6 files changed, 127 insertions(+), 47 deletions(-) create mode 100644 layouts/shortcodes/figure.html diff --git a/content/blog/2024/2024-09-10-release-notes-0.73/_index.md b/content/blog/2024/2024-09-10-release-notes-0.73/_index.md index cb7b1e77035..e28bdc15a95 100644 --- a/content/blog/2024/2024-09-10-release-notes-0.73/_index.md +++ b/content/blog/2024/2024-09-10-release-notes-0.73/_index.md @@ -51,7 +51,7 @@ The new parser emulates the windows event log format, with common fields grouped under the `System` column and variable fields in `EventData`. -![Journald parser](journald.png) +{{< figure caption="Journald parser" src="journald.png" >}} This release also introduces a new VQL plugin `watch_journald()` which follows journald logs and forwards events to the server. @@ -67,7 +67,7 @@ the attacker on systems that ran the RDP client. This information is now easily accessible using the new `Windows.Forensics.RDPCache` artifact. -![Viewing the RDP cache tiles](rdp_cache.png) +{{< figure caption="Viewing the RDP cache tiles" src="rdp_cache.png" >}} ### Added the ability to dump clear text network traffic for debugging @@ -161,7 +161,7 @@ waiting until they complete, before sending further requests. This means if the client reboots only the currently executing queries are lost, and further queries will continue once the client reconnects. -![Collection status show finer granularity](collection_states.svg) +{{< figure caption="Collection status show finer granularity" src="collection_states.svg" >}} ### Hunts can be tagged now. @@ -172,7 +172,7 @@ Over time there can be many hunts active simultaneously, and they can be used for multiple uses. In this release, the GUI's hunt view is streamlined by enabling hunts to contains labels. -![Hunts can now have Tags](hunt_tags.svg) +{{< figure caption="Hunts can now have Tags" src="hunt_tags.svg" >}} Clicking on the hunt label in the table will automatically filter the table for that label. Hunt Labels are a way to group large numbers of @@ -184,7 +184,8 @@ The Velociraptor GUI presents most data in tabular form. It is important that tables are easy to navigate. The navigation pager is now placed at the top of the table. -![Velociraptor tables have been revamped](table_widget.svg) + +{{< figure caption="Velociraptor tables have been revamped" src="table_widget.svg" >}} If a filter term starts with ! it will now be excluded from the rows (i.e. a negative search term). @@ -202,16 +203,17 @@ As in previous versions, the user can set a download password in their preferences. However, previously the password only applied to hunt or collection exports. -![Setting password for downloads globally](setting_password.svg) +{{< figure caption="Setting password for downloads globally" src="setting_password.svg" >}} In this release, the password setting also applies to individual file downloads such as the VFS -![Downloads are password protected](encrypted_downloads.svg) + +{{< figure caption="Downloads are password protected" src="encrypted_downloads.svg" >}} Or the uploads tab in specific collections. -![Individual file downloads can be password protected](single_file_downloads.svg) +{{< figure caption="Individual file downloads can be password protected" src="single_file_downloads.svg" >}} ### Post-processing preservation artifacts @@ -242,17 +244,17 @@ Let's examine a typical workflow. I will begin by preparing an offline collector with the `Windows.KapeFiles.Targets` artifact configured to collect all event logs. -![Building an offline collector](building_offline_collector.png) +{{< figure caption="Building an offline collector" src="building_offline_collector.png" >}} Once the collection is complete I receive a ZIP file containing all the collected files. I will now import it into Velociraptor. -![Importing the offline collection](importing_offline_collection.svg) +{{< figure caption="Importing the offline collection" src="importing_offline_collection.svg" >}} Since this is an offline client and not a real client, Velociraptor will create a new client id to contain the collections. -![The imported collection looks just like any other collection](kapefiles_collection.svg) +{{< figure caption="The imported collection looks just like any other collection" src="kapefiles_collection.svg" >}} Of course we can not schedule new collections for the client because it is not a real client, but once imported, the offline collection @@ -272,21 +274,21 @@ Instead, the `Windows.KapeFiles.Targets` artifact now offers a VQL snippet as a notebook suggestion to post process the collection. I access this from the collection's notebook. -![Post processing the KapeFiles collection with a notebook suggestion](post_process_kapefiles.svg) +{{< figure caption="Post processing the KapeFiles collection with a notebook suggestion" src="post_process_kapefiles.svg" >}} The new cell contains some template VQL. I can modify it to run other artifacts. In this case I will collect the `Windows.Hayabusa.Rules` artifact with all the rules (event noisy ones) and `Windows.NTFS.MFT` artifact. -![Modifying VQL to run other artifacts](post_process_kapefiles_2.svg) +{{< figure caption="Modifying VQL to run other artifacts" src="post_process_kapefiles_2.svg" >}} The post processing steps added a new distinct collection to the offline client, as if we collected it directly from the endpoint. However, the artifacts were collected from the triage files directly imported from the offline bundle. -![A new distinct collection is added](post_process_kapefiles_3.svg) +{{< figure caption="A new distinct collection is added" src="post_process_kapefiles_3.svg" >}} Although this new workflow makes it more convenient to post process bulk file triage collections, note that this is not an ideal workflow @@ -309,7 +311,7 @@ Velociraptor]({{% ref "/blog/2024/2024-09-12-timelines/" %}}) blog post, but below is a screenshot to illustrate the final product - an annotated timeline derived from analysis of multiple artifacts. -![The complete timeline with annotations](../2024-09-12-timelines/supertimeline.svg) +{{< figure caption="The complete timeline with annotations" src="../2024-09-12-timelines/supertimeline.svg" >}} ### Added Timesketch integration artifacts @@ -319,7 +321,7 @@ source timelining tool. The details of the integration are also discussed in the blog post above, but here is a view of Timesketch with some Velociraptor timelines exported. -![Viewing timelines in Timesketch](../2024-09-12-timelines/timesketch_view.svg) +{{< figure caption="Viewing timelines in Timesketch" src="../2024-09-12-timelines/timesketch_view.svg" >}} ### Client metadata fields can now be indexed and searched. @@ -349,7 +351,7 @@ department. Indexed metadata fields exist on all clients. Additional non-indexed fields can be added by the user. -![Client metadata fields can be indexed or free form](client_metadata.svg) +{{< figure caption="Client metadata fields can be indexed or free form" src="client_metadata.svg" >}} ### Enable a server artifact to specify an impersonation user. diff --git a/content/blog/2024/2024-09-10-release-notes-0.73/importing_offline_collection.svg b/content/blog/2024/2024-09-10-release-notes-0.73/importing_offline_collection.svg index 5da03759bf7..14b1dfc352f 100644 --- a/content/blog/2024/2024-09-10-release-notes-0.73/importing_offline_collection.svg +++ b/content/blog/2024/2024-09-10-release-notes-0.73/importing_offline_collection.svg @@ -3,8 +3,11 @@ - \ No newline at end of file + Create a new client id if needed or reuse an existing onePath on the server for the collection zip to be imported \ No newline at end of file diff --git a/content/blog/2024/2024-09-10-release-notes-0.73/kapefiles_collection.svg b/content/blog/2024/2024-09-10-release-notes-0.73/kapefiles_collection.svg index 0969accc416..edf0ef0dfb0 100644 --- a/content/blog/2024/2024-09-10-release-notes-0.73/kapefiles_collection.svg +++ b/content/blog/2024/2024-09-10-release-notes-0.73/kapefiles_collection.svg @@ -3,8 +3,11 @@ - \ No newline at end of file + Collections added from ZIPClient ID created to contain client data \ No newline at end of file diff --git a/content/blog/2024/2024-09-12-timelines/_index.md b/content/blog/2024/2024-09-12-timelines/_index.md index 6adf1173953..ffdd9efceac 100644 --- a/content/blog/2024/2024-09-12-timelines/_index.md +++ b/content/blog/2024/2024-09-12-timelines/_index.md @@ -17,7 +17,7 @@ date: 2024-09-12 {{% notice note "Pre-release feature" %}} This feature will be available in the upcoming 0.73 release. You can -[try it right now](https://github.com/Velocidex/velociraptor?tab=readme-ov-file#getting-the-latest-version) and provide valuable feedback. +[try it right now](https://github.com/Velocidex/velociraptor/releases/tag/v0.73) and provide valuable feedback. {{% /notice %}} @@ -106,7 +106,7 @@ The important takeaways from this example are: ## Case study: Ransomware intrusion To illustrate how a timeline can be used in a typical DFIR -investigation, lets consider a simple (if contrived) case study: +investigation, let's consider a simple (if contrived) case study: Ransomware deployment on an endpoint. ### Step 1: Create a global notebook @@ -117,9 +117,9 @@ while cells can contain markdown text or VQL queries to evaluate. I will start off by create a global notebook to hold the timeline. -![Creating a notebook from a template](new_notebook_timeline_1.svg) +{{< figure src="new_notebook_timeline_1.svg" caption="Creating a notebook from a template" >}} -![An empty timeline notebook](new_notebook_timeline_2.svg) +{{< figure caption="An empty timeline notebook" src="new_notebook_timeline_2.svg" >}} ### Step 2: Collect some artifacts! @@ -143,8 +143,7 @@ false positives with the probability of missing a detection. However, in the triage context, I really want to see all rules - including ones that are noisy and produce a lot of false positives. - -![Configuring the Sigma artifacts](hayabusa_parameters.svg) +{{< figure caption="Configuring the Sigma artifacts" src="hayabusa_parameters.svg" >}} Therefore in this case I will choose to evaluate **All** the rules on the endpoint. The artifact will then evaluate all rules against each @@ -165,14 +164,14 @@ This type of processing is called `Stacking`. Velociraptor has an inbuilt stacking feature within the GUI - it is available on any table! -![Stacking hits by Title](hayabusa_stack_1.svg) +{{< figure caption="Stacking hits by Title" src="hayabusa_stack_1.svg" >}} First I sort by one of the table columns - This will select the column I want to stack on. In this case, I will sort by the Rule Title. Once the table is sorted, the GUI shows the stacking button. Clicking the stacking button shows the stacking overview for this table. -![Inspecting unique rules](hayabusa_stack_2.svg) +{{< figure caption="Inspecting unique rules" src="hayabusa_stack_2.svg" >}} Stacking is a common technique to view aggregation of data quickly. I allows us to see what **kind** of rules matches in this case, and how @@ -187,7 +186,7 @@ strong signal so I want to drill down on it. If I click the Link icon in the stacking table, I will be able to explore the specific times this rule matched. -![Specific instances when Defender was disabled](hayabusa_stack_defender_disabled.svg) +{{< figure caption="Specific instances when Defender was disabled" src="hayabusa_stack_defender_disabled.svg" >}} I see a match in 2023 and one in 2024. In practice a lot of false positives will occur, or even evidence of previous compromise @@ -207,7 +206,7 @@ produce too many false positives. This reduces the number of events to consider from over 18,000 to about 100 high confidence events that I can manually review. -![Reducing data](hayabusa_reduced.svg) +{{< figure caption="Reducing data" src="hayabusa_reduced.svg" >}} ### Adding to the timeline. @@ -254,7 +253,7 @@ running commentary of what happened. Let's add our Sigma analysis to the timeline. Within the Reduced Sigma table, click `Add to Timeline`. -![Adding a table to a super timeline timeline](add_timeline_1.svg) +{{< figure caption="Adding a table to a super timeline timeline" src="add_timeline_1.svg" >}} The `Add Timeline` dialog allows us to create a timeline, add it to a supertimeline and configure how events are created from the current @@ -283,7 +282,7 @@ table: After the reduced Sigma timeline is added, I can see the timeline notebook updated. -![The Supertimeline UI](timeline_sigma.svg) +{{< figure caption="The Supertimeline UI" src="timeline_sigma.svg" >}} Following is a description of the UI: @@ -321,12 +320,12 @@ When an event seems important, it can be annotated. Annotating an event will copy it into a special time series within the `Supertimeline` called `Annotation`. -![Annotating an event](timeline_annotation.svg) +{{< figure caption="Annotating an event" src="timeline_annotation.svg" >}} The annotation should contain an explanation as to why this event is relevant to the case. -![The annotated event](timeline_annotation_2.svg) +{{< figure caption="The annotated event" src="timeline_annotation_2.svg" >}} The annotated event is added to a separate timeline, which may be enabled or disabled similarly as the other time series. This allows us @@ -338,10 +337,9 @@ As I collect other artifacts, I can get more information about the case: 1. Collecting the `Windows.Sys.Users` artifact enumerates the local - users on the system, and estimates the time that the user first + users on the system, and estimates the time that the user last logged into the system by reporting the Modified time on the User's - profile registry keys and home directory modification time (This - indicates when the user last logged into the system). + profile registry keys and home directory modification time. I reduce the data to show the Home directory modification time (Last time the user logged into the account). @@ -398,7 +396,7 @@ FROM source(artifact="Windows.System.TaskScheduler/Analysis") WHERE Mtime > "2024-09-12" ``` -![The complete timeline with annotations](supertimeline.svg) +{{< figure caption="The complete timeline with annotations" src="supertimeline.svg" >}} ### Exporting the annotations @@ -407,13 +405,20 @@ table for reporting purposes. The `Timeline` notebook template provides a second cell that when recalculated exports the `Annotation` time series into a unique table. -![Exporting the annotations](annotations_export.svg) +{{< figure caption="Exporting the annotations" src="annotations_export.svg" >}} + +I now can see what the attackers did. Once they logged in as +Administrator, they Disabled Windows Defender, Added a second admin +user account. Then they logged in as that account, created a scheduled +task for persistence, disabled the Bits client logs and then +downloaded `PsExec.exe` renamed to `foo.exe`. Finally the attackers +ran `whoami` and used ping to establish network connectivity. ### The Timeline workflow To summarize, the general workflow is illustrated below -![The general timeline workflow](workflow.svg) +{{< figure caption="The general timeline workflow" src="workflow.svg" >}} As we collect artifact from a group of hosts in a hunt, or individually from specific clients, we post process the results in @@ -500,7 +505,7 @@ automatically exports them to Timesketch in the background. This means that the user does not need to think about it - all timelines created within Velociraptor will automatically be added to Timesketch. -![Configuring the Server.Monitoring.TimesketchUpload artifact](configure_timesketch_export.svg) +{{< figure caption="Configuring the Server.Monitoring.TimesketchUpload artifact" src="configure_timesketch_export.svg" >}} To install the `Server.Monitoring.TimesketchUpload` server monitoring artifact, select `Server Events` in the sidebar, then click the @@ -515,7 +520,7 @@ Finally the path on the server to the timesketch client library tool is required - this is the external binary we call to upload the actual data. -![Automating Timesketch Import](automating_timesketch_import.svg) +{{< figure caption="Automating Timesketch Import" src="automating_timesketch_import.svg" >}} Once the server monitoring artifact is configured it simply waits until a user adds a timeline to a Supertimeline in Velociraptor, as @@ -523,7 +528,7 @@ described above. When that happens the timeline is automatically added to Timesketch into a sketch named the same as the Velociraptor Supertimeline. - ![Viewing timelines in Timesketch](timesketch_view.svg) +{{< figure caption="Viewing timelines in Timesketch" src="timesketch_view.svg" >}} As can be seen in the screenshot above, the same targeted timelines are exported to Timesketch. This is most useful for existing diff --git a/layouts/shortcodes/figure.html b/layouts/shortcodes/figure.html new file mode 100644 index 00000000000..8aa9c9fced0 --- /dev/null +++ b/layouts/shortcodes/figure.html @@ -0,0 +1,26 @@ +{{ $src := .Get "src" }} +{{ $id := md5 $src }} +{{ $filename := path.Join ( path.Dir .Page.File ) $src }} +{{ $caption := .Get "caption" }} +{{ if ( hasSuffix $filename ".svg" ) }} + + {{ $data := readFile $filename }} + {{ $data = strings.ReplaceRE `(?ms)` `` $data }} + +
+
+ {{ $data | safeHTML}} +
+
{{ .Get "caption" }}
+
+ +{{ else }} + +
+
+ +
+
{{ $caption }}
+
+ +{{ end }} diff --git a/static/css/theme-mine.css b/static/css/theme-mine.css index 4fb122aa523..e4e723fc844 100644 --- a/static/css/theme-mine.css +++ b/static/css/theme-mine.css @@ -1,4 +1,18 @@ +@font-face { + font-family: Excalifont; + src: url("https://docs.velociraptor.app/fonts/playpen-sans-v13-latin-500.woff2"); +} + +@font-face { + font-family: Nunito; + src: url("/fonts/playpen-sans-v13-latin-800.woff2"); +} + +@font-face { + font-family: Comic Shanns; + src: url("/fonts/SVBasicManual.woff2"); +} html body { color: var(--MAIN-TEXT-color) !important; @@ -128,9 +142,6 @@ body.dark code.hljs { color: white; } -#body img { - max-width: 50%; -} footer.footline { border-top: 1px none; @@ -755,3 +766,33 @@ td.signature { display: flex; padding-right: 10px; } + + +.featherlight-content { + width: 90%; +} + +.featherlight-content .figure { + max-width: none; +} + +.featherlight-content svg { + max-height: 80vh; +} + +figure div.figure { + cursor: pointer; + margin: 0 auto; + max-width: 600px; +} + +figure div.figure svg, +figure div.figure img { + width: 100%; + + height: auto; +} + +.featherlight .featherlight-content img { + margin: 0 auto !important; +}