<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.8.6">Jekyll</generator><link href="https://blog.dane.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://blog.dane.io/" rel="alternate" type="text/html" /><updated>2019-12-30T07:23:14+00:00</updated><id>https://blog.dane.io/feed.xml</id><title type="html">blog.dane.io</title><subtitle>Personal blog for Dane Stuckey (cryps1s)</subtitle><author><name>cryps1s</name></author><entry><title type="html">Unlimited, Unthrottled, and Anonymous LTE Access</title><link href="https://blog.dane.io/2019/12/30/unlimited-unthrottled-anonymous-lte-access.html" rel="alternate" type="text/html" title="Unlimited, Unthrottled, and Anonymous LTE Access" /><published>2019-12-30T06:35:00+00:00</published><updated>2019-12-30T06:35:00+00:00</updated><id>https://blog.dane.io/2019/12/30/unlimited-unthrottled-anonymous-lte-access</id><content type="html" xml:base="https://blog.dane.io/2019/12/30/unlimited-unthrottled-anonymous-lte-access.html">&lt;p&gt;Protecting privacy and enabling free speech on the Internet is germane to a healthy society and functioning democracy. Unfortunately, we too frequently find ourselves victims of an escalating war against privacy. Whether you’re worried about your &lt;a href=&quot;https://www.eff.org/deeplinks/2019/12/fancy-new-terms-same-old-backdoors-encryption-debate-2019&quot;&gt;Government using their powers to snoop in your personal life&lt;/a&gt; or are simply tired of the &lt;a href=&quot;https://www.wired.com/story/google-tracks-you-privacy/&quot;&gt;ever-present panopticon tracking every fucking thing you do&lt;/a&gt;, you have options to fight back.&lt;/p&gt;

&lt;p&gt;This post will walk you through improving your personal privacy by acquiring and using an unlimited, unthrottled, and anonymous* LTE hotspot offered through &lt;a href=&quot;https://www.calyxinstitute.org&quot;&gt;The Calyx Institute&lt;/a&gt;, all for about &lt;strong&gt;$40 a month&lt;/strong&gt;. When The Calyx Institute states their LTE service is unlimited and unthrottled, they absolutely mean it – I’ve yet to experience slowdowns after using a metric shit-ton of data.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/posts/lte-access-01.png&quot; alt=&quot;alt text&quot; height=&quot;250px&quot; class=&quot;center-image&quot; /&gt;&lt;br /&gt;
&lt;span class=&quot;caption text-muted&quot;&gt;A 100GB/month plan from Verizon goes for about $700 a month.&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; this is &lt;a href=&quot;https://nymag.com/intelligencer/2016/09/unlimited-data-hotspot-on-sprint-lte-from-calyx-institute.html&quot;&gt;not the first article&lt;/a&gt; which describes this invaluable service. However, most of these articles are focusing on saving money through usage of this service as a primary ISP. This is not my intent. Rather, this post will focus the history behind this LTE offering, the very real and ongoing fight to keep this service operational, and some basic OPSEC to keep in mind.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;*For some definition of anonymous.&lt;/em&gt;&lt;/p&gt;

&lt;h2 id=&quot;the-history-behind-unthrottled-lte&quot;&gt;The History Behind Unthrottled LTE&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;If you’re impatient and just want to get a hotspot, skip this next section.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I am personally shocked that unlimited, unthrottled LTE is accessible in the United States in late 2019, especially at the reasonable price of $40 a month.&lt;/p&gt;

&lt;p&gt;Given mobile carrier plans are in a race to the bottom with &lt;a href=&quot;https://www.vice.com/en_us/article/j5zpw7/us-wireless-data-prices-are-among-the-most-expensive-on-earth&quot;&gt;expensive data&lt;/a&gt;, surplus charges, and &lt;a href=&quot;https://www.cnet.com/news/verizons-throttling-of-firefighter-data-during-california-fire-raises-net-neutrality-concerns/&quot;&gt;aggressive throttling&lt;/a&gt;, this service should not logically exist. Yet it does. I’m going to quickly walk through the history behind this LTE service and how it could quickly disappear given the &lt;a href=&quot;https://www.fcc.gov/document/fcc-transforms-25-ghz-band-5g-services-0&quot;&gt;FCC is hell-bent on commercializing the wireless spectrum&lt;/a&gt; and we are seeing &lt;a href=&quot;https://www.washingtonpost.com/news/the-switch/wp/2018/04/29/t-mobile-and-sprint-announce-plans-to-merge/&quot;&gt;massive consolidation of wireless service providers&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/posts/lte-access-02.jpg&quot; alt=&quot;alt text&quot; height=&quot;300px&quot; class=&quot;center-image&quot; /&gt;&lt;br /&gt;
&lt;span class=&quot;caption text-muted&quot;&gt;Obligatory note: Ajit Pai (FCC Chairman) is an absolute clown.&lt;/span&gt;&lt;/p&gt;

&lt;h3 id=&quot;the-educational-broadband-service&quot;&gt;The Educational Broadband Service&lt;/h3&gt;

&lt;p&gt;Our story starts back in the 1960s when the U.S. Government created a reservation for 114 MHz of the 2.5GHz wireless band. Known as the &lt;a href=&quot;https://www.fcc.gov/wireless/bureau-divisions/broadband-division/broadband-radio-service-education-broadband-service&quot;&gt;&lt;strong&gt;Educational Broadband Service&lt;/strong&gt; (EBS)&lt;/a&gt;, this band was only accessible to licensed academic and educational institutions. This ultimately reserved a massive chunk of high-speed, high-capacity spectrum that was inaccessible to the commercial industry.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://nebsa.org/index.cfm/regulatory/ebs-leasing/&quot;&gt;In 1983, in an effort to encourage further adoption of the spectrum, the FCC allowed for &lt;strong&gt;excess capacity&lt;/strong&gt; sales of the spectrum to commercial entities.&lt;/a&gt; As long the EBS licensee maintained good standing and complied with FCC regulations, they could sell most of their unused spectrum capacity to commercial entities. The best part? They could sign an agreement as long as 30 years. This is important as we will see shortly.&lt;/p&gt;

&lt;h3 id=&quot;game-of-thrones-mobile-carrier-edition&quot;&gt;Game of Thrones: Mobile Carrier Edition&lt;/h3&gt;

&lt;p&gt;Fast-forward to 2006 and we find demand for wireless spectrum for high-speed cellular communications is exploding. With protected access to the EBS spectrum, nonprofit, academic, and educational institutions face massive demand from commercial wireless carriers. Using the excess capacity clause ruled by the FCC back in 1983, EBS licensees began collaborating, sharing, and selling portions of their spectrum allocation.&lt;/p&gt;

&lt;p&gt;Relevant to our story are 5 EBS licensees, operating under the trade name &lt;a href=&quot;https://voqal.org/&quot;&gt;&lt;strong&gt;Voqal&lt;/strong&gt;&lt;/a&gt;, who formed such an agreement with the wireless internet service provider &lt;a href=&quot;https://en.wikipedia.org/wiki/Clearwire&quot;&gt;&lt;strong&gt;Clearwire Corporation&lt;/strong&gt;&lt;/a&gt;. As &lt;a href=&quot;https://www.sec.gov/Archives/edgar/data/1285551/000089102007000003/v25599a1exv10w59.txt&quot;&gt;part of the 30-year agreement&lt;/a&gt;, Voqal would lease a large portion of their EBS spectrum directly to Clearwire in exchange for unlimited, high-speed broadband access for schools, libraries, educational institutions, and nonprofit organizations. This access would be granted in terms of cost-free education accounts (CFEAs) which could be given away or resold at very favorable rates to qualifying educational institutions and nonprofit organizations.&lt;/p&gt;

&lt;p&gt;To help qualified organizations gain access to these CFEAs provided under the Clearwire contract, Voqal founded the &lt;strong&gt;Mobile Citizen&lt;/strong&gt; project. Mobile Citizen would act as the CFEA intermediary and broker cost-effective and high-speed Internet access to educational and academic institutions. Partnering with other projects, these CFEA agreements enabled low-income persons, nonprofits, and academic organizations to get unlimited access to the Internet at incredibly reasonable rates. All was well in the world, right?&lt;/p&gt;

&lt;p&gt;Well no, all good things come to an end and in 2012, &lt;a href=&quot;https://newsroom.sprint.com/sprint-completes-acquisition-of-clearwire.htm&quot;&gt;Sprint decided to buy Clearwire&lt;/a&gt;. In typical corporate fashion, &lt;a href=&quot;https://www.kansascity.com/news/business/article39219684.html&quot;&gt;Sprint tried to immediately shut down the Clearwire WiMAX service, throttle the unlimited data access, and not honor the previous agreement between Mobile Citizen and Clearwire established back in 2006.&lt;/a&gt; This led to a variety of lawsuits, court injunctions, bad press, and as far as I know, this lawsuit has still yet to be resolved. At some point, Sprint capitulated and decided to honor the agreement.&lt;/p&gt;

&lt;p&gt;Yet the acquisitions weren’t done yet. In mid-2018, &lt;a href=&quot;https://www.washingtonpost.com/news/the-switch/wp/2018/04/29/t-mobile-and-sprint-announce-plans-to-merge/&quot;&gt;T-Mobile and Sprint announced a plan to merge&lt;/a&gt; with an estimated completion date of 2020. If that weren’t enough, the &lt;a href=&quot;https://www.fcc.gov/document/fcc-transforms-25-ghz-band-5g-services-0&quot;&gt;FCC voted 3-2 to auction off the EBS-protected spectrum to commercial entities sometime in 2020.&lt;/a&gt; (Editor’s note: Ajit Pai is a clown.)&lt;/p&gt;

&lt;p&gt;With massive profit margins on per-gigabyte data transfer plans and the death of net neutrality, telecommunication carriers have little incentive to honor previous agreements or advocate for inexpensive, high-data plans. The future of Mobile Citizen services, and EBS operators more broadly, is uncertain.&lt;/p&gt;

&lt;h2 id=&quot;the-calyx-institute-and-unlimited-lte-access&quot;&gt;The Calyx Institute and Unlimited LTE Access&lt;/h2&gt;

&lt;p&gt;Now that we’ve walked through the convoluted history of agreements, purchases, acquisitions, and lawsuits, where does the Calyx Institute come into play?&lt;/p&gt;

&lt;p&gt;Founded in 2010, &lt;a href=&quot;https://www.calyxinstitute.org&quot;&gt;The Calyx Institute&lt;/a&gt; is a 501(c)(3) nonprofit organization dedicated to raising awareness about surveillance and privacy issues. Most notably, the Founder of The Calyx Institute, &lt;a href=&quot;https://en.wikipedia.org/wiki/Nicholas_Merrill#Challenging_the_National_Security_Letter:_Doe_v._Ashcroft&quot;&gt;Nick Merrill&lt;/a&gt;, was hit with a National Security Letter under the USA PATRIOT Act, and successfully fought it in court. &lt;a href=&quot;https://www.youtube.com/watch?v=C25EkdWLU1k&quot;&gt;There’s a good 27c3 talk about his journey through the court system as part of this fight.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As a nonprofit organization, The Calyx Institute operates a variety of awesome services to help keep the Internet private. These services include a free and end-to-end encrypted jabber (chat) server, Tor exit nodes, and Mobile Citizen LTE access. That’s right. As they are a nonprofit organization, they can take advantage of that CFEA agreement between Mobile Citizen and Clearwire/Sprint back in 2006. The best part is: if you choose to join The Calyx Institute as a member, you are eligible for access to this LTE service. Neat, huh?&lt;/p&gt;

&lt;h3 id=&quot;joining-the-calyx-institute&quot;&gt;Joining the Calyx Institute&lt;/h3&gt;

&lt;p&gt;In order to be eligible for the LTE hotspot, you need to be a contributing member of The Calyx Institute. Dues start at $500 a year for the Contributor level, or $600 a year for the Contributor Plus level. After the first year, the dues drop $100 since you already have hotspot hardware.&lt;/p&gt;

&lt;p&gt;If you spring for the &lt;strong&gt;Contributor level ($500/year)&lt;/strong&gt;, you’ll be given a Coolpad Surf hotspot with 12 months of unlimited LTE access via Sprint. This comes out to about $42 a month for unlimited LTE access.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/posts/lte-access-03.jpg&quot; alt=&quot;alt text&quot; height=&quot;300px&quot; class=&quot;center-image&quot; /&gt;&lt;br /&gt;
&lt;span class=&quot;caption text-muted&quot;&gt;Coolpad Surf Hotspot.&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;If you spring for the &lt;strong&gt;Contributor Plus level ($600/year)&lt;/strong&gt;, you’ll be given an Inseego MiFi 8000 hotspot with 12 months of unlimited LTE access via Sprint. This comes out to about $50 a month for unlimited LTE access.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/posts/lte-access-04.png&quot; alt=&quot;alt text&quot; height=&quot;300px&quot; class=&quot;center-image&quot; /&gt;
&lt;span class=&quot;caption text-muted&quot;&gt;Inseego Mifi 8000 Hotspot.&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;Between the two, the Inseego MiFi 8000 is the superior choice. With two TS9 ports for external antennas, a substantially larger battery, and USB-C charging, it’s one of the best 4G LTE hotspots you can get today.&lt;/p&gt;

&lt;p&gt;Considering most hotspot deals are NOT unlimited, aggressively throttle, and are expensive, this deal is a no-brainer. Additionally, you can sign up for this service without &lt;strong&gt;giving any identifying information to the ISP.&lt;/strong&gt;&lt;/p&gt;

&lt;h3 id=&quot;getting-a-privacy-friendly-hotspot&quot;&gt;Getting a Privacy-Friendly Hotspot&lt;/h3&gt;

&lt;p&gt;As stated at the beginning of this post, Mobile Citizen LTE access can be a very privacy-friendly option. While you can sign up with a credit card via their website (note: since they’re a nonprofit, this is tax deductible), there are other options available.&lt;/p&gt;

&lt;p&gt;As noted on The Calyx Institute website, they will provide the following information to their mobile operator when a new user registers for service:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Name&lt;/li&gt;
  &lt;li&gt;Addresss&lt;/li&gt;
  &lt;li&gt;Hardware information (e.g. SIM card, device ID, etc.)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The important part here is that, at no point whatsoever, does it require your name or address need to be yours - or valid at all. As such, you have two primary ways of getting an LTE hotspot without attributing it directly to yourself:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Option 1: Pay in person with cash.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Did you know that The Calyx Institute shows up to DEF CON in person? Yup, they sure do. If you go to everyone’s favorite hacker summer camp, you’re in luck.&lt;/p&gt;

&lt;p&gt;Simply show up to their vendor booth, give them a name (may I recommend Ajit Pai?), hand them a wad of cash, and walk away with your new hotspot.&lt;/p&gt;

&lt;p&gt;Need to renew your membership? Simply show up with more cash next year and get a new SIM card.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Option 2: Pay with Bitcoin.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The Calyx Institute accepts payment via Bitcoin on their website. Simply give a name, give an address, and pay with Bitcoin.&lt;/p&gt;

&lt;p&gt;Don’t want to use your real name? Put whatever you want on the package and have it delivered to your house.&lt;/p&gt;

&lt;p&gt;Don’t want it delivered to your house? Use a remailer, a friend, or another service for receiving the package.&lt;/p&gt;

&lt;p&gt;Either way, your hotspot will arrive activated and present with 12 months of unlimited, unthrottled Internet service.&lt;/p&gt;

&lt;h3 id=&quot;hotspot-opsec&quot;&gt;Hotspot OPSEC&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Important note: no matter how you get your hotspot, &lt;a href=&quot;https://www.calyxinstitute.org/legal/terms-of-service&quot;&gt;you’re agreeing to abide by the terms of service for LTE access.&lt;/a&gt;. Don’t be a jerk and use this for illegal, immoral, or unethical purposes.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Having a hotspot unassociated with your real name can be a major boon to privacy and enable freedom of speech. That said, there are some operational security (OPSEC) considerations you need to be mindful of:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Your hotspot is tied to your physical location.&lt;/strong&gt; As an active LTE client with a static mobile device identifier, your location and usage of the hotspot can and will be tracked. The primary benefit of this service is that your mobile carrier (e.g. Sprint) simply &lt;em&gt;does not know who you are&lt;/em&gt; but will only know &lt;em&gt;where you are&lt;/em&gt;. For the maximally paranoid, you may consider using a mobile carrier other than Sprint, which will ensure your devices aren’t all beaconing to the same towers as the same time.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Your ISP can still see everything you do.&lt;/strong&gt; All this hotspot provides is Internet access, not guarantees of privacy or confidentiality. You should assume that all your traffic will be inspected, dissected, logged, and recorded in perpetuity. As such, you will need to employ VPNs, encrypt DNS traffic, use TLS, and control metadata leakage yourself.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;This hotspot still provides advantages over Wi-Fi access points.&lt;/strong&gt; While not private, the hotspot has clear advantages over traditional public access points. Public Wi-Fi access points may be metered, unencrypted, require registration (e.g. an e-mail address, name, room number, device MAC address), or use privacy-hostile services (e.g. Google Wi-Fi).&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Never forget that OPSEC is a mindset and a process, not a silver bullet.&lt;/strong&gt; When this access is used intelligently, you can bolster your privacy. When used poorly, it may erode it. Be vigilant, be paranoid, and fight for your right to privacy (and party).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Paired well with a travel router, your Mobile Citizen LTE hotspot will grant you enjoyable and fully unlimited, unshaped Internet access, no matter where you go. *&lt;/p&gt;

&lt;p&gt;(*As long as it’s within the United States and has Sprint service.)&lt;/p&gt;

&lt;h2 id=&quot;further-reading-and-acknowledgements&quot;&gt;Further Reading and Acknowledgements&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Thanks for The Calyx Foundation and Mobile Citizen for enabling affordable access to the Internet, facilitating freedom of speech, and fighting for our privacy rights.&lt;/li&gt;
&lt;/ul&gt;</content><author><name>cryps1s</name></author><summary type="html">Protecting privacy and enabling free speech on the Internet is germane to a healthy society and functioning democracy. Unfortunately, we too frequently find ourselves victims of an escalating war against privacy. Whether you’re worried about your Government using their powers to snoop in your personal life or are simply tired of the ever-present panopticon tracking every fucking thing you do, you have options to fight back.</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blog.dane.io/assets/img/posts/lte-access-00.jpg" /><media:content medium="image" url="https://blog.dane.io/assets/img/posts/lte-access-00.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Deploying a Static Website via Azure</title><link href="https://blog.dane.io/2019/12/28/deploying-a-static-website-via-azure.html" rel="alternate" type="text/html" title="Deploying a Static Website via Azure" /><published>2019-12-28T02:49:22+00:00</published><updated>2019-12-28T02:49:22+00:00</updated><id>https://blog.dane.io/2019/12/28/deploying-a-static-website-via-azure</id><content type="html" xml:base="https://blog.dane.io/2019/12/28/deploying-a-static-website-via-azure.html">&lt;p&gt;While AWS remains the market leader for public cloud providers, I have personally found Azure to be significantly more security-conscious and pleasurable to work with. As part of the learning process, I’ve slowly been migrating and deploying services onto Azure – including this blog.&lt;/p&gt;

&lt;p&gt;This post is going to focus on deploying a simple, static website onto an Azure storage account (AWS S3 equivalent). As part of this deployment, I will front the storage account with a content delivery network (CDN), enable a valid HTTPS certificate, configure reasonable caching defaults, and set up continuous integration for deployment via CircleCI. The goal of this project is to have a remarkably secure website with minimal time, energy, and resources committed to maintaining it.&lt;/p&gt;

&lt;p&gt;I will caveat this post by stating that I am definitively not a web developer, and most of these web technologies are outside my proficiency.&lt;/p&gt;

&lt;h2 id=&quot;the-case-for-a-static-web-page&quot;&gt;The Case for a Static Web Page&lt;/h2&gt;

&lt;p&gt;So the first question we should answer is: &lt;em&gt;why do we want a static web page&lt;/em&gt;? There are a few compelling reasons why static web pages are so attractive:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Static web pages can be incredibly secure.&lt;/strong&gt; A static web page has no moving parts, plugins, servers, or dynamic content that present attack surface. While this blog has absolutely nothing of significance or value if hacked, a static deployment means one less thing to worry about.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Static web pages don’t need a traditional hosting provider.&lt;/strong&gt; You don’t need to shell out large amounts of cash for a wordpress or other hosting provider. You can simply throw your static web page in a cheap bucket and call it a day.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Static web pages are dead simple.&lt;/strong&gt; There are no dynamically generated components to maintain which means every viewer receives the same viewing experience. Static web pages are typically also small and incredibly fast to load.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Static web pages are compatible with git and CI/CD.&lt;/strong&gt; You can edit your web pages in markdown, manage versions through git, and auto-deploy with CI/CD. It’s a pretty magical process.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The static web page zeitgeist likely originated with the creation of &lt;a href=&quot;https://jekyllrb.com/&quot;&gt;Jekyll&lt;/a&gt;, a static site generator (SSG) which powers GitHub Pages functionality. Since Jekyll, SSGs have exploded in popularity and created a rich ecosystem of frameworks. While you can craft an artisanal static website by hand, these frameworks make it trivial to get started and deploy a new project.&lt;/p&gt;

&lt;p&gt;There are a variety of SSG frameworks available, but &lt;a href=&quot;https://gohugo.io/&quot;&gt;Hugo&lt;/a&gt;, &lt;a href=&quot;https://jekyllrb.com/&quot;&gt;Jekyll&lt;/a&gt;, and &lt;a href=&quot;https://www.gatsbyjs.org/&quot;&gt;Gatsby.js&lt;/a&gt; are perhaps the most well-known and popular. Each of these have their own language preferences, features, and benefits, but all serve the same purpose. A cross-comparison of these frameworks is outside the scope of this post (and outside of my depth of my knowledge), but I ultimately selected &lt;strong&gt;Jekyll&lt;/strong&gt; for my personal blog.&lt;/p&gt;

&lt;p&gt;Once you’ve selected a framework and found a &lt;a href=&quot;http://jekyllthemes.org/&quot;&gt;free theme&lt;/a&gt; that appeals to you, you’ll need to get a local development environment ready.&lt;/p&gt;

&lt;h2 id=&quot;windows-development-environment&quot;&gt;Windows Development Environment&lt;/h2&gt;

&lt;p&gt;As most of my devices run with application whitelisting enabled, I needed to spin up a local development environment. If you’re not foolish enough to use application whitelisting, run another operating system (e.g. MacOS), or already have a local developer environment, this section may not be useful for you. Feel free to skip it.&lt;/p&gt;

&lt;p&gt;For Jekyll, we’ll need a few components installed:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Windows Subsystem for Linux (WSL)&lt;/li&gt;
  &lt;li&gt;Git&lt;/li&gt;
  &lt;li&gt;Ruby&lt;/li&gt;
  &lt;li&gt;Jekyll (Ruby Gem)&lt;/li&gt;
  &lt;li&gt;HTML-Proofer (Ruby Gem)&lt;/li&gt;
  &lt;li&gt;Other ruby gems for your site (e.g. “jekyll-sitemap”, “jekyll-seo-tag”, etc.)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In my instance, I spun up a new Windows 10 developer environment in Hyper-V, but you could just as easily do this on your host.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Install WSL using PowerShell.&lt;/p&gt;

    &lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Enable-WindowsOptionalFeature&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Online&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-FeatureName&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Microsoft-Windows-Subsystem-Linux&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Install Ubuntu 16.04 LTS via PowerShell and Reboot.&lt;/p&gt;

    &lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Invoke-WebRequest&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Uri&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;https://aka.ms/wsl-ubuntu-1604&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-OutFile&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Ubuntu.appx&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-UseBasicParsing&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
 &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Add-AppxPackage&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;\app-name-as-per-above.appx&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Update WSL.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; &lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt-get update &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt-get upgrade &lt;span class=&quot;nt&quot;&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Install Basic Tools.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; &lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt-get &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;gnupg2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://jekyllrb.com/docs/installation/windows/&quot;&gt;Install Jekyll&lt;/a&gt;.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; &lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt-add-repository ppa:brightbox/ruby-ng
 &lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt-get update
 &lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt-get &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;ruby2.5 ruby2.5-dev build-essential dh-autoreconf
 gem update
 gem &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;jekyll bundler html-proofer
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://jekyllrb.com/docs/&quot;&gt;Create a New Site&lt;/a&gt; OR &lt;a href=&quot;https://jekyllrb.com/docs/themes/&quot;&gt;Install a Theme&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;At the end of this process, you should have a Jekyll-compatible environment ready and either a new site, or a templated site, ready for configuration. This is the part where you actually make your blog, configure your template, and add content.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Protip:&lt;/strong&gt; To test your local changes, you can use the &lt;code class=&quot;highlighter-rouge&quot;&gt;jekyll serve&lt;/code&gt; command. This will open up a listener on &lt;a href=&quot;http://127.0.0.1:4000&quot;&gt;http://127.0.0.1:4000&lt;/a&gt; where you can preview your changes.&lt;/p&gt;

&lt;h2 id=&quot;configuring-your-repository&quot;&gt;Configuring Your Repository&lt;/h2&gt;

&lt;p&gt;Now that we’ve got a rough skeleton for our blog, we’ll throw it in a GitHub.com repository.&lt;/p&gt;

&lt;h3 id=&quot;create-a-gitignore-file&quot;&gt;Create a .gitignore file&lt;/h3&gt;

&lt;p&gt;First, we’ll create a local .gitignore file for your repository and add the following contents:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;_site
.sass-cache
node_modules
.jekyll-cache/
.jekyll-metadata
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This will allow us to version control the web site content without uploading the actual HTML pages. We’ll generate these from the source files as part of our CI/CD pipeline.&lt;/p&gt;

&lt;h3 id=&quot;upload-web-site-files&quot;&gt;Upload Web Site Files&lt;/h3&gt;

&lt;p&gt;Next, we’ll commit everything and upload it to our repository. We can now version control all changes to our web site using our GitHub repository. An example of what this looks like is below.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/posts/static-website-01.png&quot; alt=&quot;alt text&quot; height=&quot;650px&quot; class=&quot;center-image&quot; /&gt;&lt;br /&gt;
&lt;span class=&quot;caption text-muted&quot;&gt;Private GitHub repo for blog.dane.io.&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;We’ll come back and make some additional changes to our repository later but, for now, we’re going to move over to our Azure account and get that configured.&lt;/p&gt;

&lt;h2 id=&quot;configuring-azure&quot;&gt;Configuring Azure&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Protip:&lt;/strong&gt; If you’re new to Azure, you can &lt;a href=&quot;https://azure.microsoft.com/en-us/free/&quot;&gt;register for a free account&lt;/a&gt; and get $200 worth of credit and 12 months of some free services.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Double Protip:&lt;/strong&gt; If you’re a &lt;a href=&quot;https://visualstudio.microsoft.com/vs/pricing/&quot;&gt;Visual Studio subscriber&lt;/a&gt;, you get $50 a month in Azure credits in addition to software access (e.g. Windows 10, Server 2019) and other benefits. You might consider purchasing a subscription, or convincing your workplace to sponsor it, if you intend to play with Azure and the Windows platform long-term.&lt;/p&gt;

&lt;p&gt;We’ll need an Azure account for hosting our web site. If you use Office365, you already have an Azure account. If not, you’ll need to get one. Go ahead and login or create your Azure account now.&lt;/p&gt;

&lt;h3 id=&quot;create-the-storage-account&quot;&gt;Create the Storage Account&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; By default, all storage accounts in Azure are encrypted using server side encryption (SSE) by Microsoft. We don’t need to do anything special for encryption at rest.&lt;/p&gt;

&lt;p&gt;Next, we’ll create our storage account for hosting our static website. As our website content is stored in a GitHub repository, we don’t need to worry about backups, redundancy, or other availability or integrity protection mechanisms at the storage account level.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Navigate to Storage Accounts within the Azure Portal.&lt;/li&gt;
  &lt;li&gt;Create a new storage account with the following specifications:
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;Resource Group&lt;/strong&gt;: New (e.g. blog_dane_io)&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Storage Account Name:&lt;/strong&gt; something representative (e.g. daneio). Note: this must be globally unique within Azure.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Location:&lt;/strong&gt; Choose your location (e.g. US-West-2)&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Performance:&lt;/strong&gt; Standard&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Account Kind:&lt;/strong&gt; Storagev2 (general purpose)&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Replication:&lt;/strong&gt; Locally-redundant storage (LRS)&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Access tier:&lt;/strong&gt; Hot (can change this later if needed)&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Connectivity method:&lt;/strong&gt; Public endpoint (all networks)&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Secure transfer required:&lt;/strong&gt; Enabled&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Navigate to the storage account you created.&lt;/li&gt;
  &lt;li&gt;Configure the following settings on the storage account:
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;Static website:&lt;/strong&gt; Enabled. (Use default index.html and 404.html paths)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/posts/static-website-02.png&quot; alt=&quot;alt text&quot; height=&quot;500px&quot; class=&quot;center-image&quot; /&gt;&lt;br /&gt;
&lt;span class=&quot;caption text-muted&quot;&gt;Storage account configuration.&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/posts/static-website-03.png&quot; alt=&quot;alt text&quot; height=&quot;300px&quot; class=&quot;center-image&quot; /&gt;&lt;br /&gt;
&lt;span class=&quot;caption text-muted&quot;&gt;Static website configuration.&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;We now have a storage account ready for hosting our static website content. If you use the Storage Explorer, you’ll notice that a default &lt;strong&gt;$web&lt;/strong&gt; container now exists and is ready to serve up our website.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/posts/static-website-04.png&quot; alt=&quot;alt text&quot; height=&quot;300px&quot; class=&quot;center-image&quot; /&gt;&lt;br /&gt;
&lt;span class=&quot;caption text-muted&quot;&gt;Static website container ($web).&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;If we only wanted to serve out of the bucket itself, we could simply configure a domain name and stop here. However, we want to do a few more things before we can call this project finished. Let’s go set up our custom domain name.&lt;/p&gt;

&lt;h3 id=&quot;configure-custom-domain-name&quot;&gt;Configure Custom Domain Name&lt;/h3&gt;

&lt;p&gt;If you’re into vanity domains (and who isn’t?), you might consider using a custom domain or subdomain for your website. As I use Azure for managing my DNS, I’ll configure it to use the &lt;code class=&quot;highlighter-rouge&quot;&gt;blog.dane.io&lt;/code&gt; subdomain.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Navigate to DNS Zones within the Azure Portal.&lt;/li&gt;
  &lt;li&gt;Create a new Resource Group and Instance (e.g. dane.io).&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Navigate to the newly created instance and grab the name server information:&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; Name server 1: ns1-06.azure-dns.com.
 Name server 2: ns2-06.azure-dns.net.
 Name server 3: ns3-06.azure-dns.org.
 Name server 4: ns4-06.azure-dns.info.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;Update your domain registrar to point at the Azure name servers.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/posts/static-website-05.png&quot; alt=&quot;alt text&quot; height=&quot;300px&quot; class=&quot;center-image&quot; /&gt;&lt;br /&gt;
&lt;span class=&quot;caption text-muted&quot;&gt;Validation of DNS changes.&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;We are now using Azure to manage our DNS. We’ll be able to create the custom records for our CDN by creating a record set within the Azure DNS console.&lt;/p&gt;

&lt;h3 id=&quot;enabling-the-azure-cdn&quot;&gt;Enabling the Azure CDN&lt;/h3&gt;

&lt;p&gt;We’re going to front our website with an Azure content delivery network (CDN) to improve speeds, reduce bandwidth usage of our bucket, and distribute our content to geographically distributed points of presence.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Navigate to your storage account you created within the Azure portal.&lt;/li&gt;
  &lt;li&gt;Under “Azure CDN”, create a new endpoint with the following specifications:
    &lt;ul&gt;
      &lt;li&gt;Create new CDN profile.&lt;/li&gt;
      &lt;li&gt;Name: Use a representative name (e.g. daneio)&lt;/li&gt;
      &lt;li&gt;Pricing: Standard Microsoft.&lt;/li&gt;
      &lt;li&gt;CDN Endpoint Name: Use a representative name (e.g. daneio.azureedge.net) Note: this must be globally unique within Azure.&lt;/li&gt;
      &lt;li&gt;Origin hostname: Grab the name from the “Primary Static Website Endpoint” under the Properties tab. (Example: &lt;a href=&quot;https://daneio.z5.web.core.windows.net)&quot;&gt;https://daneio.z5.web.core.windows.net)&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;Click create.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/posts/static-website-06.png&quot; alt=&quot;alt text&quot; height=&quot;300px&quot; class=&quot;center-image&quot; /&gt;&lt;br /&gt;
&lt;span class=&quot;caption text-muted&quot;&gt;Custom origin information.&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;Next, we’re going to configure our DNS record to point to the CDN endpoint that we specified above (e.g. &lt;a href=&quot;https://daneio.azureedge.net).&quot;&gt;https://daneio.azureedge.net).&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Navigate to the DNS Zone you created within the Azure portal.&lt;/li&gt;
  &lt;li&gt;Create a new record set with the following specifications:
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;Name:&lt;/strong&gt; blog.dane.io (or whatever your own domain is)&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Type:&lt;/strong&gt; CNAME&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;TTL:&lt;/strong&gt; 1 hour&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Alias:&lt;/strong&gt; daneio.azureedge.net.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This will redirect any requests to our subdomain (e.g. blog.dane.io) to the Azure CDN endpoint.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/posts/static-website-07.png&quot; alt=&quot;alt text&quot; height=&quot;200px&quot; class=&quot;center-image&quot; /&gt;&lt;br /&gt;
&lt;span class=&quot;caption text-muted&quot;&gt;Successfully validated DNS record.&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;Once the record has been created, we’ll need to associate the domain with our Azure CDN endpoint.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Navigate to the Azure CDN endpoint you created.&lt;/li&gt;
  &lt;li&gt;Under “Custom Domains”, add a new custom domain with the following specifications:
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;Endpoint hostname:&lt;/strong&gt; daneio.azureedge.net (or whatever your Azure CDN endpoint is)&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Custom hostname:&lt;/strong&gt; blog.dane.io (or whatever you used for the domain above)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Click add.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;enabling-tls-encryption&quot;&gt;Enabling TLS Encryption&lt;/h3&gt;

&lt;p&gt;Once we have confirmed the DNS record, we can have Azure provision and manage a digital certificate for us.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Navigate to the Azure CDN endpoint you created.&lt;/li&gt;
  &lt;li&gt;Under “Custom Domains”, select the custom domain you added.&lt;/li&gt;
  &lt;li&gt;Enable &lt;strong&gt;custom domain HTTPS&lt;/strong&gt; with a &lt;strong&gt;CDN-managed&lt;/strong&gt; certificate.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Once this has been kicked off, it may take a few hours for the TLS certificate to be provisioned.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/posts/static-website-08.png&quot; alt=&quot;alt text&quot; height=&quot;300px&quot; class=&quot;center-image&quot; /&gt;&lt;br /&gt;
&lt;span class=&quot;caption text-muted&quot;&gt;Successfully issued TLS certificate.&lt;/span&gt;&lt;/p&gt;

&lt;h3 id=&quot;configuring-cdn-compression&quot;&gt;Configuring CDN Compression&lt;/h3&gt;

&lt;p&gt;Next, we’re going to ensure that compression is enabled for content delivered via the Azure CDN. While images are likely already compressed, we can save some bandwidth and improve delivery speed by compressing other MIME formats.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Navigate to the Azure CDN endpoint you created.&lt;/li&gt;
  &lt;li&gt;Under “Compression” ensure that Compression is &lt;strong&gt;enabled&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By default, fonts, XML, plaintext, CSV, HTML, and other MIME formats will be compressed. You may add additional MIME signatures to this list to provide compression on-the-fly.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/posts/static-website-09.png&quot; alt=&quot;alt text&quot; height=&quot;600px&quot; class=&quot;center-image&quot; /&gt;&lt;br /&gt;
&lt;span class=&quot;caption text-muted&quot;&gt;MIME types compressed during CDN delivery.&lt;/span&gt;&lt;/p&gt;

&lt;h3 id=&quot;configuring-cdn-cache&quot;&gt;Configuring CDN Cache&lt;/h3&gt;

&lt;p&gt;Next, we’re going to configure our CDN cache. This is especially important as assets cached via the CDN will be retained until the time-to-live (TTL) expires. If we fail to configure reasonable caching, updates to our website will be painful.&lt;/p&gt;

&lt;p&gt;By default, Azure storage accounts set a cache on a per-object basis with a default of 7 days. While this is fine for static content (e.g. image assets, fonts), it will be a very poor experience for updates to HTML pages. While we could set the TTL for each object individually as we add it to the bucket, there is a really lazy way to solve this problem.&lt;/p&gt;

&lt;p&gt;We’ll set the general CDN caching rule for our CDN:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Navigate to the Azure CDN endpoint you created.&lt;/li&gt;
  &lt;li&gt;Under “Caching rules” ensure that the query string caching behavior is set to &lt;strong&gt;ignore query strings&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/posts/static-website-10.png&quot; alt=&quot;alt text&quot; height=&quot;150px&quot; class=&quot;center-image&quot; /&gt;&lt;br /&gt;
&lt;span class=&quot;caption text-muted&quot;&gt;Default caching behavior.&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;Next, we’ll create some custom cache rules using the &lt;strong&gt;rules engine&lt;/strong&gt;. Our goal will be as follows:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Set the default TTL to a short-lived value (e.g. 5 minutes) for all assets. This will allow for quick updates when critical files (e.g. HTML) are changed.&lt;/li&gt;
  &lt;li&gt;Explicitly set the TTL to a long-lived value (e.g. 7 days) for all other static assets loaded (e.g. images, fonts, CSS).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Managing the cache in this way ensures that we can centrally adjust values instead of setting them on a per-object basis in the storage account.&lt;/p&gt;

&lt;p&gt;To do so, perform the following:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Navigate to the Azure CDN endpoint you created.&lt;/li&gt;
  &lt;li&gt;Navigate to “Rules Engine”.&lt;/li&gt;
  &lt;li&gt;Under the &lt;strong&gt;global rule&lt;/strong&gt; click &lt;strong&gt;add action&lt;/strong&gt; and add the following:
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;Always cache expiration:&lt;/strong&gt; Override with 5 minute TTL.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Click &lt;strong&gt;add rule&lt;/strong&gt; and add the following:
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;Name&lt;/strong&gt;: CacheControl&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Logic:&lt;/strong&gt; If URL file contains ‘/assets/’ (to lowercase), then set cache expiration override to 7 days.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In this instance, I have configured 2 specific rules:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Rule 1 (Global):&lt;/strong&gt; Default assets get a 5 minute TTL.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Rule 2 (CacheControl):&lt;/strong&gt; Any file delivered out of the &lt;code class=&quot;highlighter-rouge&quot;&gt;/assets/&lt;/code&gt; folder is given a 7 day TTL. We’ll use this folder for images, javascript, CSS, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This combination of short and long TTLs ensures that our CDN is only delivering compressed text (e.g. HTML, CSS) on a frequent basis, but all large and static assets (e.g. images, gifs, fonts) are cached. When we make production changes to our website, it takes around 5 minutes for the HTML CDN cache to expire and be refreshed, making it a seamless user browsing experience.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/posts/static-website-11.png&quot; alt=&quot;alt text&quot; height=&quot;300px&quot; class=&quot;center-image&quot; /&gt;&lt;br /&gt;
&lt;span class=&quot;caption text-muted&quot;&gt;Custom caching behavior rules.&lt;/span&gt;&lt;/p&gt;

&lt;h3 id=&quot;adding-basic-security-features&quot;&gt;Adding Basic Security Features&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Note: Due to issues with the Microsoft CDN and Twitter card support, I switched over to Standard Akamai. Unfortunately, the Akamai CDN does not allow custom header manipulation. As such, I’m leaving this documentation for those who might still need to use the Microsoft CDN.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Next, we’ll want to configure a few basic security features:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Redirect HTTP to HTTPS.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://scotthelme.co.uk/hsts-the-missing-link-in-tls/&quot;&gt;Enable HTTP Strict Transport Security (HSTS) for the website.&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://scotthelme.co.uk/hardening-your-http-response-headers/#x-frame-options&quot;&gt;Prevent framing our website from other sites (X-Frame-Options).&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://scotthelme.co.uk/content-security-policy-an-introduction/&quot;&gt;Set a content-security-policy (CSP) for what may be loaded.&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://scotthelme.co.uk/hardening-your-http-response-headers/#x-content-type-options&quot;&gt;Prevent MIME sniffing (X-Content-Type-Options).&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://scotthelme.co.uk/a-new-security-header-referrer-policy/&quot;&gt;Configure a referrer policy.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While many of these are not strictly necessary given the static nature of the website, it’s fairly trivial to add and deploy. We’ll do it for completion’s sake.&lt;/p&gt;

&lt;p&gt;We’ll start with HTTPS redirection. This is important as the CDN will not serve content over HTTP.&lt;/p&gt;

&lt;p&gt;To do so, perform the following:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Navigate to the Azure CDN endpoint you created.&lt;/li&gt;
  &lt;li&gt;Navigate to “Rules Engine”.&lt;/li&gt;
  &lt;li&gt;Click &lt;strong&gt;add rule&lt;/strong&gt; and add the following:
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;Name&lt;/strong&gt;: EnforceHTTPS&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Logic:&lt;/strong&gt; If &lt;code class=&quot;highlighter-rouge&quot;&gt;request protocol equals HTTP&lt;/code&gt;, then &lt;code class=&quot;highlighter-rouge&quot;&gt;URL redirect found (302)&lt;/code&gt; to protocol &lt;code class=&quot;highlighter-rouge&quot;&gt;HTTPS&lt;/code&gt;.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/posts/static-website-12.png&quot; alt=&quot;alt text&quot; height=&quot;200px&quot; class=&quot;center-image&quot; /&gt;&lt;br /&gt;
&lt;span class=&quot;caption text-muted&quot;&gt;Custom EnforceHTTPS rule.&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;Next, we’ll configure HSTS and a Content Security Policy for the website. HSTS ensures that browsers will only connect to the website over HTTPS, and the CSP will help prevent cross site scripting (XSS), as much of a rarity as that might be.&lt;/p&gt;

&lt;p&gt;To do so, perform the following:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Navigate to the Azure CDN endpoint you created.&lt;/li&gt;
  &lt;li&gt;Navigate to “Rules Engine”.&lt;/li&gt;
  &lt;li&gt;Under the &lt;strong&gt;global rule&lt;/strong&gt; click &lt;strong&gt;add action&lt;/strong&gt; and add the following:
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;And modify response header:&lt;/strong&gt; Append &lt;code class=&quot;highlighter-rouge&quot;&gt;Strict-Transport-Security&lt;/code&gt; with value &lt;code class=&quot;highlighter-rouge&quot;&gt;max-age=315360000; preload&lt;/code&gt;.&lt;/li&gt;
      &lt;li&gt;Click &lt;strong&gt;add action&lt;/strong&gt; again.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;And modify responder header:&lt;/strong&gt; Append &lt;code class=&quot;highlighter-rouge&quot;&gt;Content-Security-Policy&lt;/code&gt; with the value &lt;code class=&quot;highlighter-rouge&quot;&gt;default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'&lt;/code&gt;.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/posts/static-website-13.png&quot; alt=&quot;alt text&quot; height=&quot;200px&quot; class=&quot;center-image&quot; /&gt;&lt;br /&gt;
&lt;span class=&quot;caption text-muted&quot;&gt;HSTS and CSP configured.&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;Next, we’ll prevent our site from being embedded on other websites (e.g. X-Frame-Options), prevent MIME sniffing (X-Content-Type-Options), and configure a referrer policy.&lt;/p&gt;

&lt;p&gt;To do so, perform the following:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Navigate to the Azure CDN endpoint you created.&lt;/li&gt;
  &lt;li&gt;Navigate to “Rules Engine”.&lt;/li&gt;
  &lt;li&gt;Click &lt;strong&gt;add rule&lt;/strong&gt; and add the following:
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;Name:&lt;/strong&gt; SecurityHeaders&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Logic:&lt;/strong&gt; If &lt;code class=&quot;highlighter-rouge&quot;&gt;request method equals GET&lt;/code&gt;, then &lt;code class=&quot;highlighter-rouge&quot;&gt;modify response header&lt;/code&gt; to append &lt;code class=&quot;highlighter-rouge&quot;&gt;X-Content-Type-Options&lt;/code&gt; with value &lt;code class=&quot;highlighter-rouge&quot;&gt;nosniff&lt;/code&gt;.&lt;/li&gt;
      &lt;li&gt;Click &lt;strong&gt;add action&lt;/strong&gt; again.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Logic:&lt;/strong&gt; Then &lt;code class=&quot;highlighter-rouge&quot;&gt;modify response header&lt;/code&gt; to append &lt;code class=&quot;highlighter-rouge&quot;&gt;Referrer-Policy&lt;/code&gt; with value &lt;code class=&quot;highlighter-rouge&quot;&gt;strict-origin-when-cross-origin&lt;/code&gt;.&lt;/li&gt;
      &lt;li&gt;Click &lt;strong&gt;add action&lt;/strong&gt; again.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Logic:&lt;/strong&gt; Then &lt;code class=&quot;highlighter-rouge&quot;&gt;modify response header&lt;/code&gt; to append &lt;code class=&quot;highlighter-rouge&quot;&gt;X-Frame-Options&lt;/code&gt; with value &lt;code class=&quot;highlighter-rouge&quot;&gt;DENY&lt;/code&gt;.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/posts/static-website-14.png&quot; alt=&quot;alt text&quot; height=&quot;300px&quot; class=&quot;center-image&quot; /&gt;&lt;br /&gt;
&lt;span class=&quot;caption text-muted&quot;&gt;X-Frame-Options and HSTS.&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;We’ll go ahead and do a quick scan via &lt;a href=&quot;https://securityheaders.com&quot;&gt;Security Headers&lt;/a&gt; and validate things look good:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/posts/static-website-15.png&quot; alt=&quot;alt text&quot; height=&quot;400px&quot; class=&quot;center-image&quot; /&gt;&lt;br /&gt;
&lt;span class=&quot;caption text-muted&quot;&gt;While not an A+, it’s good enough for Government work.&lt;/span&gt;&lt;/p&gt;

&lt;h2 id=&quot;configuring-circleci&quot;&gt;Configuring CircleCI&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; It’s really easy to spill secrets via CircleCI and GitHub. I highly recommend you keep your repository private to reduce the likelihood of accidental misconfiguration.&lt;/p&gt;

&lt;h3 id=&quot;hooking-circleci-to-github&quot;&gt;Hooking CircleCI to GitHub&lt;/h3&gt;

&lt;p&gt;Once we have built our website, configured the storage account, configured the Azure CDN, and have a valid TLS certificate, we’re ready to hook everything together. We’ll first configure a CircleCI project for our GitHub repository:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Authenticate to CircleCI using your GitHub account.&lt;/li&gt;
  &lt;li&gt;Click &lt;strong&gt;Set Up Project&lt;/strong&gt; for your website repository. Ignore the CircleCI yaml file right now.&lt;/li&gt;
  &lt;li&gt;Under your new project in CircleCI, navigate to Advanced Settings. Change the following:
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;Build Forked Pull Requests:&lt;/strong&gt; Disable this.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Pass Secrets to Builds From Forked Pull Requests:&lt;/strong&gt; Disable this.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;CircleCI now has a deploy key from the GitHub repository, and we’ve disabled building of forked pull requests. This is especially important if your repository is public, as adversaries can potentially steal secrets from environmental variables in your CircleCI node if these settings are enabled.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/posts/static-website-16.png&quot; alt=&quot;alt text&quot; height=&quot;250px&quot; class=&quot;center-image&quot; /&gt;&lt;br /&gt;
&lt;span class=&quot;caption text-muted&quot;&gt;Also known as the “wreck my world” buttons.&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;Next, we’re going to go grab some credentials for our storage account in Azure:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Navigate to the Azure storage account you created.&lt;/li&gt;
  &lt;li&gt;Navigate to “Access Keys”.&lt;/li&gt;
  &lt;li&gt;Copy the key specified under key1.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is your access key. Keep it safe; anyone with access to this key will be able to do whatever they’d like to your storage account. We’re going to go ahead and give it to CircleCI so it’ll be able to modify the bucket (and pray CircleCI never has a breach).&lt;/p&gt;

&lt;p&gt;To do so, perform the following:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Navigate to the settings for your project in CircleCI.&lt;/li&gt;
  &lt;li&gt;Under Build Settings, navigate to &lt;strong&gt;Environment Variables&lt;/strong&gt;.&lt;/li&gt;
  &lt;li&gt;Add the following two environmental variables:
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;Name:&lt;/strong&gt; &lt;code class=&quot;highlighter-rouge&quot;&gt;AZURE_STORAGE_ACCOUNT&lt;/code&gt; with value &lt;code class=&quot;highlighter-rouge&quot;&gt;daneio&lt;/code&gt; (or whatever your bucket name is.)&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Name:&lt;/strong&gt; &lt;code class=&quot;highlighter-rouge&quot;&gt;AZURE_STORAGE_KEY&lt;/code&gt; with value &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;paste your key here&amp;gt;&lt;/code&gt;.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/posts/static-website-17.png&quot; alt=&quot;alt text&quot; height=&quot;250px&quot; class=&quot;center-image&quot; /&gt;&lt;br /&gt;
&lt;span class=&quot;caption text-muted&quot;&gt;Using environmental variables keeps credentials out of files in your repository.&lt;/span&gt;&lt;/p&gt;

&lt;h3 id=&quot;generating-a-circleci-yaml-file&quot;&gt;Generating a CircleCI YAML File&lt;/h3&gt;

&lt;p&gt;Now we have CircleCI configured and ready to rock. The last step here will be generating a CircleCI YAML file for controlling when to build containers with our code. This is part art-form, part science, and may take a few (dozen) tries to get it right. I’ve included a copy of my current config.yml file below, which I’ll explain in further detail. Whether you use mine, grab a premade one, or make your own, you’ll need to throw it in your GitHub repository as &lt;code class=&quot;highlighter-rouge&quot;&gt;.circleci/config.yml&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;version: 2
&lt;span class=&quot;nb&quot;&gt;jobs&lt;/span&gt;:
  build:
    docker:
      - image: circleci/ruby:latest
    working_directory: ~/repo
    steps:
      - checkout
      - restore_cache:
          keys:
            - rubygems-v2-&lt;span class=&quot;se&quot;&gt;\{\{&lt;/span&gt; checksum &lt;span class=&quot;s2&quot;&gt;&quot;Gemfile.lock&quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\}\}&lt;/span&gt;
            - rubygems-v2-fallback
      - run:
          name: Install Dependencies
          &lt;span class=&quot;nb&quot;&gt;command&lt;/span&gt;: |
            bundle &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--jobs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;4 &lt;span class=&quot;nt&quot;&gt;--retry&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;3 &lt;span class=&quot;nt&quot;&gt;--path&lt;/span&gt; vendor/bundle &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; bundle clean
      - save_cache:
          key: rubygems-v2-&lt;span class=&quot;se&quot;&gt;\{\{&lt;/span&gt; checksum &lt;span class=&quot;s2&quot;&gt;&quot;Gemfile.lock&quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\}\}&lt;/span&gt;
          paths:
            - vendor/bundle
      - run:
          name: Jekyll build
          &lt;span class=&quot;nb&quot;&gt;command&lt;/span&gt;: bundle &lt;span class=&quot;nb&quot;&gt;exec &lt;/span&gt;jekyll build
      - run:
          name: HTMLProofer tests
          &lt;span class=&quot;nb&quot;&gt;command&lt;/span&gt;: |
            bundle &lt;span class=&quot;nb&quot;&gt;exec &lt;/span&gt;htmlproofer ./_site &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;--allow-missing-href&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;--allow-hash-href&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;--check-favicon&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;--check-html&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;--disable-external&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;--only-4xx&lt;/span&gt;
      - run:
          name: Cleanup filters
          &lt;span class=&quot;nb&quot;&gt;command&lt;/span&gt;: |
            &lt;span class=&quot;nb&quot;&gt;rm&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; gulpfile.js jekyll-theme-clean-blog.gemspec LICENSE README.md package-lock.json package.json
      - persist_to_workspace:
          root: ./
          paths:
            - _site
  deploy:
    docker:
      - image: circleci/python:latest
    working_directory: ~/repo
    steps:
      - attach_workspace:
          at: ./
      - run:
          name: Install Azure CLI
          &lt;span class=&quot;nb&quot;&gt;command&lt;/span&gt;: curl &lt;span class=&quot;nt&quot;&gt;-sL&lt;/span&gt; https://aka.ms/InstallAzureCLIDeb | &lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;bash
      - run:
          name: Upload to Azure bucket
          &lt;span class=&quot;nb&quot;&gt;command&lt;/span&gt;: az storage blob &lt;span class=&quot;nb&quot;&gt;sync&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--source&lt;/span&gt; ./_site &lt;span class=&quot;nt&quot;&gt;--container&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'$web'&lt;/span&gt;
workflows:
  version: 2
  Production Deployment:
    &lt;span class=&quot;nb&quot;&gt;jobs&lt;/span&gt;:
      - build
      - deploy
      - deploy:
          requires:
            - build
          filters:
            branches:
              only: master
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This YAML file is configured with two specific jobs: &lt;strong&gt;build&lt;/strong&gt; and &lt;strong&gt;deploy&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;build&lt;/strong&gt; job runs against &lt;em&gt;every commit&lt;/em&gt; to the repository and performs the following:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;A new linux container is spun up using one of Circle’s ruby images.&lt;/li&gt;
  &lt;li&gt;(Optional) Some caching shenanigans are used to speed up deploys.&lt;/li&gt;
  &lt;li&gt;The GitHub repository is checked out using the SSH deploy key.&lt;/li&gt;
  &lt;li&gt;(Optional) The ruby bundle for my theme is installed and cleaned.&lt;/li&gt;
  &lt;li&gt;Jekyll runs and builds the website. The output is saved to the &lt;code class=&quot;highlighter-rouge&quot;&gt;_site&lt;/code&gt; folder locally within the CircleCI container.&lt;/li&gt;
  &lt;li&gt;HTMLProofer runs against the output website and looks for broken links, errors, etc.&lt;/li&gt;
  &lt;li&gt;Some junk files are deleted since I don’t want them hanging out in my webroot.&lt;/li&gt;
  &lt;li&gt;The output of the &lt;code class=&quot;highlighter-rouge&quot;&gt;_site&lt;/code&gt; folder is saved for later use by the &lt;strong&gt;deploy&lt;/strong&gt; job.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;strong&gt;deploy&lt;/strong&gt; job only runs against &lt;em&gt;changes to the master branch&lt;/em&gt; and performs the following:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;A new linux container is spun up using one of Circle’s python images.&lt;/li&gt;
  &lt;li&gt;We re-attach the &lt;strong&gt;build&lt;/strong&gt; workspace containing the contents of the &lt;code class=&quot;highlighter-rouge&quot;&gt;_site&lt;/code&gt; folder.&lt;/li&gt;
  &lt;li&gt;We install the &lt;code class=&quot;highlighter-rouge&quot;&gt;AzureCLI&lt;/code&gt; tool.&lt;/li&gt;
  &lt;li&gt;We use the &lt;code class=&quot;highlighter-rouge&quot;&gt;AzureCLI&lt;/code&gt; tool to synchronize the storage account with the files we have locally.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;configuring-github-checks&quot;&gt;Configuring GitHub Checks&lt;/h3&gt;

&lt;p&gt;The final step of this project is configuring &lt;strong&gt;branch protection&lt;/strong&gt; and &lt;strong&gt;status checks&lt;/strong&gt; for our GitHub repository. This will force us to use pull requests for merging to master, and force successful CircleCI builds as part of that pull request. This will hopefully prevent us from pushing something broken into production by relying on our CircleCI build jobs as a gate.&lt;/p&gt;

&lt;p&gt;To do so, perform the following:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Navigate to your GitHub repository and go to &lt;strong&gt;Settings -&amp;gt; Branches.&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;Enforce &lt;strong&gt;branch protection&lt;/strong&gt; for &lt;strong&gt;master&lt;/strong&gt;.&lt;/li&gt;
      &lt;li&gt;Enable &lt;strong&gt;Require status checks to pass before merging.&lt;/strong&gt;&lt;/li&gt;
      &lt;li&gt;Enable &lt;strong&gt;Require branches to be up to date before merging&lt;/strong&gt;&lt;/li&gt;
      &lt;li&gt;Select the status check for &lt;strong&gt;ci/circleci: build&lt;/strong&gt; as required.&lt;/li&gt;
      &lt;li&gt;Select &lt;strong&gt;include administrators&lt;/strong&gt; to force compliance for yourself.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/posts/static-website-18.png&quot; alt=&quot;alt text&quot; height=&quot;650px&quot; class=&quot;center-image&quot; /&gt;&lt;br /&gt;
&lt;span class=&quot;caption text-muted&quot;&gt;Branch protections requiring a build CI Job to pass.&lt;/span&gt;&lt;/p&gt;

&lt;h3 id=&quot;example-circleci-workflow&quot;&gt;Example CircleCI Workflow&lt;/h3&gt;

&lt;p&gt;When properly configured, every commit to our website will automatically perform the build and identify any jekyll or HTML issues. When we feel comfortable with the final results and merge to the master branch, the deploy job will execute, updating our website on production. The synchronize command will manage all of our file uploads and deletes, making this CI job rather trivial to maintain.&lt;/p&gt;

&lt;p&gt;To perform an update to the website, simply:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Commit all changes to a new branch.&lt;/li&gt;
  &lt;li&gt;Perform a pull-request to master from your branch. Pass the CircleCI build job.&lt;/li&gt;
  &lt;li&gt;Merge to master and the &lt;code class=&quot;highlighter-rouge&quot;&gt;deploy&lt;/code&gt; CircleCI job will run. You’re done.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/posts/static-website-19.png&quot; alt=&quot;alt text&quot; height=&quot;500px&quot; class=&quot;center-image&quot; /&gt;&lt;br /&gt;
&lt;span class=&quot;caption text-muted&quot;&gt;Pull requests need to pass a CI job to deploy.&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/posts/static-website-20.png&quot; alt=&quot;alt text&quot; height=&quot;150px&quot; class=&quot;center-image&quot; /&gt;&lt;br /&gt;
&lt;span class=&quot;caption text-muted&quot;&gt;Successful build and deploy.&lt;/span&gt;&lt;/p&gt;

&lt;h2 id=&quot;pricing&quot;&gt;Pricing&lt;/h2&gt;

&lt;p&gt;Lastly, how much does all of this cost? Well, so far, it’s cost about $0.25 for a handful of days. Most of the costs incurred have been from figuring out the services and experimenting with CircleCI jobs (e.g. syncing lots of files to storage.)&lt;/p&gt;

&lt;p&gt;I anticipate that (a) it will typically cost between $10 and $15 per month, and (b) some clown will likely decide to try and drive up the costs substantially through malicious abuse.&lt;/p&gt;

&lt;p&gt;Luckily, you can set a set a spending limit on Azure subscriptions to prevent costs from going through the roof. We’ll see how this shakes out after a month or two of operation.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/posts/static-website-21.png&quot; alt=&quot;alt text&quot; height=&quot;450px&quot; class=&quot;center-image&quot; /&gt;&lt;br /&gt;
&lt;span class=&quot;caption text-muted&quot;&gt;Temporary pricing chart.&lt;/span&gt;&lt;/p&gt;

&lt;h2 id=&quot;further-reading-and-acknowledgements&quot;&gt;Further Reading and Acknowledgements&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://blackrockdigital.io/&quot;&gt;BlackRock Digital&lt;/a&gt; for my Jekyll theme.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://scotthelme.co.uk/&quot;&gt;Scott Helme&lt;/a&gt; has a great website that discusses HTTP security headers.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://jessicadeen.com/how-to-setup-azure-cdn-with-azure-storage-and-allow-twitter-cards/&quot;&gt;Jessica Deen&lt;/a&gt; for helping solve some CDN/Twitter shenanigans.&lt;/li&gt;
  &lt;li&gt;CircleCI, Jekyll, and Azure documentation were stellar and assisted quite a bit on this project.&lt;/li&gt;
  &lt;li&gt;I cobbled my CircleCI yaml file together from quite a few sources which I neglected to document. Thanks to whoever you were.&lt;/li&gt;
&lt;/ul&gt;</content><author><name>cryps1s</name></author><summary type="html">While AWS remains the market leader for public cloud providers, I have personally found Azure to be significantly more security-conscious and pleasurable to work with. As part of the learning process, I’ve slowly been migrating and deploying services onto Azure – including this blog.</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blog.dane.io/assets/img/posts/static-website-00.jpg" /><media:content medium="image" url="https://blog.dane.io/assets/img/posts/static-website-00.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Detecting Windows Endpoint Compromise with SACLs</title><link href="https://blog.dane.io/2018/07/16/detecting-windows-endpoint-compromise-with-sacls.html" rel="alternate" type="text/html" title="Detecting Windows Endpoint Compromise with SACLs" /><published>2018-07-16T08:00:00+00:00</published><updated>2018-07-16T08:00:00+00:00</updated><id>https://blog.dane.io/2018/07/16/detecting-windows-endpoint-compromise-with-sacls</id><content type="html" xml:base="https://blog.dane.io/2018/07/16/detecting-windows-endpoint-compromise-with-sacls.html">&lt;p&gt;This post is going to focus on using the &lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/secauthz/access-control-lists&quot;&gt;system access control list (SACL)&lt;/a&gt; functionality to detect endpoint compromise on Windows hosts. The goal is to quickly, cheaply, and effectively detect anomalous activity on an endpoint without focusing purely on anomalous process and thread execution.&lt;/p&gt;

&lt;p&gt;If you’re unfamiliar with SACLs, the concept is quite simple: &lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/secauthz/access-control-entries&quot;&gt;Apply an audit access control entry (ACE)&lt;/a&gt; to an object (e.g. a file, registry key) which logs when that object is successfully or unsuccessfully (or both) accessed or modified by one or more principles. These events will, with appropriate configuration, generate event log entries that may be analyzed to identify post-exploitation activity.&lt;/p&gt;

&lt;p&gt;Note: This particular blog post will only cover object access and manipulation SACL entries. There are many other uses for SACLs which I may explore in future posts.&lt;/p&gt;

&lt;h2 id=&quot;ace-and-acl-basics&quot;&gt;ACE and ACL Basics&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Note: This is a very basic primer of ACEs, ACLs, and Security Descriptors. It is highly recommended you perform deeper research on these technologies to understand their nuance and internals.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Before we dig into deploying SACLs, we’ll cover a very basic and quick primer on access control lists (ACLs) and access control entries (ACE).&lt;/p&gt;

&lt;p&gt;In the Windows world, an ACL is a list structure that can contain zero, one, or multiple ACE. Each ACE in an ACL describes a security identifier (SID) and specific access (or deny) rights allowed for that SID against a given object. For instance, an ACE can allow specific users to read/write/modify an object, while another ACE can deny access to the object altogether for other users.&lt;/p&gt;

&lt;p&gt;ACLs are applied against securable objects, such as files, folders, registry keys, and kernel objects. While there are many documented securable objects, &lt;a href=&quot;https://www.slideshare.net/harmj0y/an-ace-in-the-hole-stealthy-host-persistence-via-security-descriptors&quot;&gt;research has identified there are still many dozens of objects that remain undocumented.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;An ACL can be one of two specific varieties: a &lt;strong&gt;discretionary access control list (DACL)&lt;/strong&gt; or a &lt;strong&gt;system access control list (SACL)&lt;/strong&gt;. The DACL is primarily used for &lt;em&gt;controlling access&lt;/em&gt; to an object, whereas a SACL is primarily used for &lt;em&gt;logging access attempts&lt;/em&gt; to an object.&lt;/p&gt;

&lt;p&gt;There’s a lot going on here, so we’ll look at a quick visual:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/posts/sacl-01.png&quot; alt=&quot;alt text&quot; height=&quot;650px&quot; class=&quot;center-image&quot; /&gt;&lt;br /&gt;
&lt;span class=&quot;caption text-muted&quot;&gt;&lt;a href=&quot;https://eneter.blogspot.com/2013/08/windows-security-wiki.html&quot;&gt;https://eneter.blogspot.com/2013/08/windows-security-wiki.html&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;We’ll first walk through the DACL. As noted in the above image, the DACL has both &lt;strong&gt;Access Denied&lt;/strong&gt; and &lt;strong&gt;Access Allowed&lt;/strong&gt; ACEs. When an attempt is made to access a securable objects, the system will check the ACEs specified in the object’s DACL and make a determination on whether access should be allowed or not.&lt;/p&gt;

&lt;p&gt;This is referenced in the following diagram:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/posts/sacl-02.gif&quot; alt=&quot;alt text&quot; height=&quot;180px&quot; class=&quot;center-image&quot; /&gt;&lt;br /&gt;
&lt;span class=&quot;caption text-muted&quot;&gt;&lt;a href=&quot;https://msdn.microsoft.com/en-us/library/cc246052.aspx&quot;&gt;https://msdn.microsoft.com/en-us/library/cc246052.aspx&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;In this example, a process is attempting to access a securable object and the token is inspected and compared against ACE entries on the object’s DACL. As the SIDs specified in the access token match those specified in the ACE, access is granted.&lt;/p&gt;

&lt;p&gt;This diagram also outlines the order of ACE evaluation when attempting to access an object:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Explicit Deny ACEs&lt;/li&gt;
  &lt;li&gt;Explicit Allow ACEs&lt;/li&gt;
  &lt;li&gt;Inherited Deny ACEs&lt;/li&gt;
  &lt;li&gt;Inherited Allow ACEs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We’ll next walk through the SACL, the often-ignored and underutilized friend of the DACL. Unlike the DACL, the SACL provides access to the Audit ACE. The audit ACE simply describes whether or not access to an object was allowed, denied, or both, and with what access was granted.&lt;/p&gt;

&lt;p&gt;This will prove to be incredibly valuable for a few key reasons:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;DACLs generally won’t stop post-exploitation activity for a given user. Compromise of a user’s process will allow the adversary to access the user’s files and folders with impunity.&lt;/li&gt;
  &lt;li&gt;Endpoint detection and response tooling has major blind spots. Some tooling may straight up ignore file reads while others may only report changes to objects, but not specify what changed.&lt;/li&gt;
  &lt;li&gt;We can quickly apply audit ACEs to objects and record access (successful or not) for specific actions (e.g. read, write, delete, permission changes, etc.) without requiring additional tooling or telemetry sources.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In summary: &lt;em&gt;DACLs control what SIDs can access what objects&lt;/em&gt;, while SACLs &lt;em&gt;tell you whether or not they were successful in their attempt to perform a given set of actions&lt;/em&gt; against that object.&lt;/p&gt;

&lt;h2 id=&quot;defensive-sacl-primitives&quot;&gt;Defensive SACL Primitives&lt;/h2&gt;

&lt;p&gt;There two defensive SACL primitives that we will use in this post:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Object Read SACLs&lt;/strong&gt;. These are SACLs designed to detect unusual post-exploitation activity focused on credential theft, privilege escalation, file pilfering, etc. The premise is simple: Log when someone accesses this object.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Object Write SACLs&lt;/strong&gt;. These are SACLs designed to detect writes, modifications, permission changes, or other activity used for persistence, anti-forensics, or system tampering. The premise is simple: Log when someone writes to/modifies this object.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These two object primitives can be easily applied to both file system and registry objects. These primitives are defined in powershell as follows:&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# SACL Primitive for File Reads / Directory Traversals / Ownership Changes&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$AuditUser&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Everyone&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$AuditRules&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;ReadData, TakeOwnership&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$InheritType&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;None&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$PropagationFlags&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;None&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$AuditType&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Success&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$FileReadSuccessAudit&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;New-Object&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;System.Security.AccessControl.FileSystemAuditRule&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$AuditUser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$AuditRules&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$InheritType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$PropagationFlags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$AuditType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# SACL Primitive for File Writes / Appends / Deletes / Ownership Changes&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$AuditUser&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Everyone&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$AuditRules&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;CreateFiles, AppendData, DeleteSubdirectoriesAndFiles, Delete, TakeOwnership&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$InheritType&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;None&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$PropagationFlags&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;None&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$AuditType&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Success&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$FileWriteSuccessAudit&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;New-Object&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;System.Security.AccessControl.FileSystemAuditRule&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$AuditUser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$AuditRules&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$InheritType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$PropagationFlags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$AuditType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# SACL Primitive for Registry Key Value Sets / Key Creation / Key Writes / Ownership Changes&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$AuditUser&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Everyone&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$AuditRules&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;SetValue, CreateSubkey, WriteKey, TakeOwnership&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$InheritType&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;None&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$PropagationFlags&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;None&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$AuditType&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Success&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$RegistryWriteSuccessAudit&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;New-Object&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;System.Security.AccessControl.RegistryAuditRule&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$AuditUser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$AuditRules&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$InheritType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$PropagationFlags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$AuditType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# SACL Primitive for Registry Key Value Sets / Key Creation / Key Writes / Ownership Changes&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$AuditUser&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Everyone&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$AuditRules&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;SetValue, CreateSubkey, WriteKey, TakeOwnership&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$InheritType&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;ContainerInherit, ObjectInherit&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$PropagationFlags&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;None&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$AuditType&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Success&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$RegistryRecursiveWriteSuccessAudit&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;New-Object&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;System.Security.AccessControl.RegistryAuditRule&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$AuditUser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$AuditRules&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$InheritType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$PropagationFlags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$AuditType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;adding-a-sacl&quot;&gt;Adding a SACL&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Note: You will need appropriate Windows event logging enabled for object manipulation event IDs to log. &lt;a href=&quot;https://github.com/palantir/windows-event-forwarding&quot;&gt;I recommend the audit settings specified here.&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now, we’ll walk through how to configure a SACL manually. This is ill-advised for any production deployment, but it’s important to know how to investigate and modify these by hand.&lt;/p&gt;

&lt;p&gt;For this example, we’ll configure a SACL on a super secret filed called &lt;strong&gt;KFC_Recipe.docx&lt;/strong&gt; with the &lt;strong&gt;object read&lt;/strong&gt; primitive we described above. The goal will be to log any access to this file and then identify unusual access by investigating the events.&lt;/p&gt;

&lt;h3 id=&quot;using-the-security-gui&quot;&gt;Using the Security GUI&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Navigate to the KFC_Recipe.docx file and Right-click &amp;gt; Properties.&lt;/li&gt;
  &lt;li&gt;Click on the Security tab.&lt;/li&gt;
  &lt;li&gt;Click Advanced.&lt;/li&gt;
  &lt;li&gt;Click on the Auditing tab.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/posts/sacl-03.png&quot; alt=&quot;alt text&quot; height=&quot;450px&quot; class=&quot;center-image&quot; /&gt;&lt;br /&gt;
&lt;span class=&quot;caption text-muted&quot;&gt;Our unprotected KFC Recipe. Shame.&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;This panel will detail any configured audit ACEs configured on the object. As we haven’t added an ACE, it will be empty. Let’s fix that.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Click Add.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/posts/sacl-04.png&quot; alt=&quot;alt text&quot; height=&quot;440px&quot; class=&quot;center-image&quot; /&gt;&lt;br /&gt;
&lt;span class=&quot;caption text-muted&quot;&gt;We first need to specify a principal (SID) to audit.&lt;/span&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Click on “Select a Principal”.&lt;/li&gt;
  &lt;li&gt;Type “Everyone” and Check Names. Hit OK.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/posts/sacl-05.png&quot; alt=&quot;alt text&quot; height=&quot;250px&quot; class=&quot;center-image&quot; /&gt;&lt;br /&gt;
&lt;span class=&quot;caption text-muted&quot;&gt;This will audit all principals that access this object.&lt;/span&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Click the Advanced button and uncheck all boxes except List Folder / Read Data. Set the Type to All.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/posts/sacl-06.png&quot; alt=&quot;alt text&quot; height=&quot;440px&quot; class=&quot;center-image&quot; /&gt;&lt;br /&gt;
&lt;span class=&quot;caption text-muted&quot;&gt;This will audit all principals that successfully or unsuccessfully read the file.&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/posts/sacl-07.png&quot; alt=&quot;alt text&quot; height=&quot;440px&quot; class=&quot;center-image&quot; /&gt;&lt;br /&gt;
&lt;span class=&quot;caption text-muted&quot;&gt;The final output of the audit ACE.&lt;/span&gt;&lt;/p&gt;

&lt;h3 id=&quot;using-powershell&quot;&gt;Using Powershell&lt;/h3&gt;

&lt;p&gt;This process is substantially easier to deploy via powershell:&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# SACL Primitive for File Reads / Directory Traversals / Ownership Changes&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$AuditUser&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Everyone&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$AuditRules&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;ReadData, TakeOwnership&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$InheritType&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;None&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$PropagationFlags&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;None&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$AuditType&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Success&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$FileReadSuccessAudit&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;New-Object&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;System.Security.AccessControl.FileSystemAuditRule&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$AuditUser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$AuditRules&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$InheritType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$PropagationFlags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$AuditType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$FilePath&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;ENV&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;USERPROFILE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;\Documents\KFC_Recipe.docx&quot;&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# Get the ACL with Audit ACEs&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Acl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Get-Acl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$FilePath&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Audit&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# Set the ACE&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Acl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;SetAuditRule&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$FileReadSuccessAudit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# Apply the ACL&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Acl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Set-Acl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Out-Null&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;verify-the-ace-works&quot;&gt;Verify the ACE Works&lt;/h2&gt;

&lt;p&gt;Now we’ll perform validation on this ACE to ensure it’s logging appropriately.&lt;/p&gt;

&lt;p&gt;We’ll first test as an innocuous user by opening the document in Microsoft Word:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/posts/sacl-08.png&quot; alt=&quot;alt text&quot; height=&quot;700px&quot; class=&quot;center-image&quot; /&gt;&lt;br /&gt;
&lt;span class=&quot;caption text-muted&quot;&gt;Opening the document in Word generates a 4663 Event (File System Object Access).&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;Looking at the windows event log reveals that a &lt;strong&gt;4663 (File System Object Access)&lt;/strong&gt; event was logged. In this event, we can see the &lt;strong&gt;Object_Name&lt;/strong&gt; references the &lt;strong&gt;KFC_Recipe.docx&lt;/strong&gt; file, and the &lt;strong&gt;Process_Name&lt;/strong&gt; references &lt;strong&gt;WINWORD.exe&lt;/strong&gt; (Microsoft Word).&lt;/p&gt;

&lt;p&gt;Let’s now try to access this file via another process:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/posts/sacl-09.png&quot; alt=&quot;alt text&quot; height=&quot;850px&quot; class=&quot;center-image&quot; /&gt;&lt;br /&gt;
&lt;span class=&quot;caption text-muted&quot;&gt;Malicious file copying the KFC_Recipe.docx file.&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;In this instance, I used a malicious file (C:\Windows\Temp\runsystem32.exe) to simply copy the KFC_Recipe.docx file to C:\Windows\Temp prior to exfiltrating it.&lt;/p&gt;

&lt;p&gt;In this instance, the SACL worked and our malicious binary was logged attempting to access our sensitive document. We can now operationalize this data by looking for anomalous processes accessing this file.&lt;/p&gt;

&lt;h2 id=&quot;alerting-and-detection-strategies&quot;&gt;Alerting and Detection Strategies&lt;/h2&gt;

&lt;p&gt;Here are some examples of potential &lt;a href=&quot;https://github.com/palantir/alerting-detection-strategy-framework&quot;&gt;alerting and detection strategies&lt;/a&gt; that could be developed and exploited with appropriately configured SACLs:&lt;/p&gt;

&lt;h3 id=&quot;browser-data-harvesting&quot;&gt;Browser Data Harvesting&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Alerting and Detection Strategy:&lt;/strong&gt; Identify when a non-browser process accesses sensitive browser files, databases, and folders.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SACL Primitive:&lt;/strong&gt; Object Read&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Baseline Activity:&lt;/strong&gt; Browser processes (e.g. Chrome and Firefox) will routinely access these files.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Activity Caught:&lt;/strong&gt; Interrogation of browser history, theft of browser cookies, theft of browser login data, etc.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/posts/sacl-09.png&quot; alt=&quot;alt text&quot; height=&quot;850px&quot; class=&quot;center-image&quot; /&gt;&lt;br /&gt;
&lt;span class=&quot;caption text-muted&quot;&gt;Powershell.exe accessing Chrome History DB.&lt;/span&gt;&lt;/p&gt;

&lt;h3 id=&quot;key-and-credential-harvesting&quot;&gt;Key and Credential Harvesting&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Alerting and Detection Strategy:&lt;/strong&gt; Identify when a non-legitimate process accesses sensitive files, keys, and credential stores in a user’s home directory.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SACL Primitive:&lt;/strong&gt; Object Read&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Baseline Activity:&lt;/strong&gt; Password vaults, SSH/SSH key manager binaries, GPG binaries, administration tools.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Activity Caught:&lt;/strong&gt; Theft of SSH/GPG keys, theft of password vaults, theft of AWS/Azure credentials, etc.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/posts/sacl-10.png&quot; alt=&quot;alt text&quot; height=&quot;850px&quot; class=&quot;center-image&quot; /&gt;&lt;br /&gt;
&lt;span class=&quot;caption text-muted&quot;&gt;Unusual process reading SSH keys.&lt;/span&gt;&lt;/p&gt;

&lt;h3 id=&quot;registry-persistence&quot;&gt;Registry Persistence&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Alerting and Detection Strategy:&lt;/strong&gt; Identify malicious persistence — or malicious modification of legitimate persistence entries — in commonly-abused registry locations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SACL Primitive:&lt;/strong&gt; Object Write&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Baseline Activity:&lt;/strong&gt; Variable depending on software installation and behavior.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Activity Caught:&lt;/strong&gt; Addition of new malicious binary run key entries, hijacking of malicious persistence entries, etc.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/posts/sacl-11.png&quot; alt=&quot;alt text&quot; height=&quot;850px&quot; class=&quot;center-image&quot; /&gt;&lt;br /&gt;
&lt;span class=&quot;caption text-muted&quot;&gt;Legitimate persistence mechanism hijack by a malicious binary.&lt;/span&gt;&lt;/p&gt;

&lt;h3 id=&quot;malicious-system-tampering&quot;&gt;Malicious System Tampering&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Alerting and Detection Strategy:&lt;/strong&gt; Identify when there are malicious modifications to critical system security, logging, or protective controls.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SACL Primitive:&lt;/strong&gt; Object Write&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Baseline Activity:&lt;/strong&gt; GPO activity, normal administrative changes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Activity Caught:&lt;/strong&gt; &lt;a href=&quot;https://specterops.io/assets/resources/SpecterOps_Subverting_Trust_in_Windows.pdf&quot;&gt;Modification of trust stores [PDF]&lt;/a&gt;, modification of logging (e.g. commandline, powershell), manipulation of security tooling controls (e.g. sysmon configuration), etc.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/posts/sacl-12.png&quot; alt=&quot;alt text&quot; height=&quot;850px&quot; class=&quot;center-image&quot; /&gt;&lt;br /&gt;
&lt;span class=&quot;caption text-muted&quot;&gt;Powershell logging disabled by a malicious binary.&lt;/span&gt;&lt;/p&gt;

&lt;h2 id=&quot;protips&quot;&gt;Protips&lt;/h2&gt;

&lt;p&gt;There are a few protips that I’ve learned while deploying this across my home environment:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The objects you deploy a SACL to will determine the overall volume, but you should expect this technique to be very noisy. You likely will need to employ some tuning and whitelisting on the front-end to reduce the overall volume of indexed events.&lt;/li&gt;
  &lt;li&gt;You will need centralized log collection of Windows Event Logs to operationalize these detection strategies. You cannot rely on host-based logs stored only on the endpoint, so plan to ship off logs as quickly as possible. I recommend looking at the Windows Event Forwarding project from Palantir for a native way of collecting/managing logs for DFIR purposes.&lt;/li&gt;
  &lt;li&gt;There are tons of legitimate alerting strategies you can develop using SACLs. These are merely the tip of the iceberg, and I would encourage you to think deeply about what makes the most sense for your environment.&lt;/li&gt;
  &lt;li&gt;You can audit “Read Permissions”, “Change Permissions”, and “Take Ownership” to further monitor sensitive files. Attempts by an adversary to (a) enumerate and (b) manipulate audit ACEs applied to an object will be logged with a 4663 (filesystem) or 4657 (registry) event.&lt;/li&gt;
  &lt;li&gt;There is a nuclear auditing option called the Global Audit Policy. This can enable object-access auditing for all file-system objects, registry keys, or both. The benefit of this option is that it removes the need to manually handjam auditing ACEs onto the objects you care about. The downside is that the volume of audit events is astronomical. Global audit policy is outside the scope of this post.&lt;/li&gt;
  &lt;li&gt;Object access monitoring is one of many ways SACLs can be used. There are several other defensive primitives which are outside the scope of this post.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;further-reading-and-acknowledgements&quot;&gt;Further Reading and Acknowledgements&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;SpecterOps for their awesome work and research on ACE-based attacks and persistence.&lt;/li&gt;
  &lt;li&gt;Windows Internals Part 1 Seventh Edition&lt;/li&gt;
&lt;/ul&gt;</content><author><name>cryps1s</name></author><summary type="html">This post is going to focus on using the system access control list (SACL) functionality to detect endpoint compromise on Windows hosts. The goal is to quickly, cheaply, and effectively detect anomalous activity on an endpoint without focusing purely on anomalous process and thread execution.</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blog.dane.io/assets/img/posts/sacl-00.jpg" /><media:content medium="image" url="https://blog.dane.io/assets/img/posts/sacl-00.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">DARKSURGEON: A Windows 10 Packer Project for Defenders</title><link href="https://blog.dane.io/2018/05/14/darksurgeon-a-windows-10-packer-project-for-defenders.html" rel="alternate" type="text/html" title="DARKSURGEON: A Windows 10 Packer Project for Defenders" /><published>2018-05-14T08:00:00+00:00</published><updated>2018-05-14T08:00:00+00:00</updated><id>https://blog.dane.io/2018/05/14/darksurgeon-a-windows-10-packer-project-for-defenders</id><content type="html" xml:base="https://blog.dane.io/2018/05/14/darksurgeon-a-windows-10-packer-project-for-defenders.html">&lt;p&gt;I’m happy to announce the alpha release of &lt;a href=&quot;https://github.com/cryps1s/DARKSURGEON&quot;&gt;DARKSURGEON, a Windows 10 packer project&lt;/a&gt; to empower incident response, digital forensics, malware analysis, and network defense.&lt;/p&gt;

&lt;p&gt;DARKSURGEON is designed to perform the following:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Accelerate incident response, digital forensics, malware analysis, and network defense with a preconfigured Windows 10 environment complete with tools, scripts, and utilities.&lt;/li&gt;
  &lt;li&gt;Provide a framework for defenders to customize and deploy their own programmatically-built Windows images using Packer and Vagrant.&lt;/li&gt;
  &lt;li&gt;Reduce the amount of latent telemetry collection, minimize error reporting, and provide reasonable privacy and hardening standards for Windows 10.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you haven’t worked with packer before, this project has a simple premise:&lt;/p&gt;

&lt;p&gt;Provide all the tools you need to have a productive, secure, and private Windows virtual machine so you can spend less time tweaking your environment and more time fighting bad guys.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/posts/darksurgeon-01.png&quot; alt=&quot;alt text&quot; height=&quot;450px&quot; class=&quot;center-image&quot; /&gt;&lt;br /&gt;
&lt;span class=&quot;caption text-muted&quot;&gt;Example DARKSURGEON Applications.&lt;/span&gt;&lt;/p&gt;

&lt;h2 id=&quot;development-principles&quot;&gt;Development Principles&lt;/h2&gt;

&lt;p&gt;DARKSURGEON is based on a few key development principles:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Modularity is key.&lt;/strong&gt; Each component of the installation and configuration process should be modular. This allows for individuals to tailor their packer image in the most flexible way.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Builds must be atomic.&lt;/strong&gt; A packer build should either complete all configuration and installation tasks without errors, or it should fail. A packer image with missing tools is a failure scenario.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Hardened out of the box.&lt;/strong&gt; To the extent that it will not interfere with investigative workflows, all settings related to proactive hardening and security controls should be enabled. Further information on DARKSURGEON security can be found later in this post.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Instrumented out of the box.&lt;/strong&gt; To the extent that it will not interfere with investigative workflows, Microsoft Sysmon, Windows Event Logging, and osquery will provide detailed telemetry on host behavior without further configuration.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Private out of the box.&lt;/strong&gt; To the extent that it will not interfere with investigative workflows, all settings related to privacy, Windows telemetry, and error reporting should minimize collection.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;hardening&quot;&gt;Hardening&lt;/h3&gt;

&lt;p&gt;Hardening of the host must balance the needs of productivity with risk mitigation. DARKSURGEON pre-configured with scripts to enable either a High or Low Security mode, each tailored towards different workflows. Currently, only the low security mode is available for testing.&lt;/p&gt;

&lt;p&gt;The default selection, Low Security, caters primarily to ephemeral use virtual machines (e.g. incident response or malware analysis, etc.)&lt;/p&gt;

&lt;p&gt;Regardless of your selection, all default installations of DARKSURGEON have the following security features:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Windows OS security guidelines are implemented.&lt;/li&gt;
  &lt;li&gt;The latest Windows security patches are applied.&lt;/li&gt;
  &lt;li&gt;Windows Secure Boot is Enabled.&lt;/li&gt;
  &lt;li&gt;LLMNR is Disabled.&lt;/li&gt;
  &lt;li&gt;NBT/NBT-NS is Disabled.&lt;/li&gt;
  &lt;li&gt;WPAD is Disabled.&lt;/li&gt;
  &lt;li&gt;Powershell v2 is Removed.&lt;/li&gt;
  &lt;li&gt;SMB v1 is Disabled.&lt;/li&gt;
  &lt;li&gt;Application handlers for commonly-abused file extensions are defanged (opened in notepad).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In &lt;strong&gt;Low Security&lt;/strong&gt; mode, the following hardening features are present:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Windows Defender Anti-Virus (WDAV) is enabled with hourly auto-updates.&lt;/li&gt;
  &lt;li&gt;Windows Defender Anti-Virus Real-Time Scanning is Disabled.&lt;/li&gt;
  &lt;li&gt;Windows Defender Anti-Virus Cloud Checks are Disabled.&lt;/li&gt;
  &lt;li&gt;Windows Defender SmartScreen is Disabled.&lt;/li&gt;
  &lt;li&gt;Windows Defender Credential Guard is Disabled.&lt;/li&gt;
  &lt;li&gt;Windows Defender Exploit Guard is Disabled.&lt;/li&gt;
  &lt;li&gt;Windows Defender Exploit Guard Attack Surface Reduction (ASR) is Disabled.&lt;/li&gt;
  &lt;li&gt;Windows Defender Application Guard is Disabled.&lt;/li&gt;
  &lt;li&gt;Windows Defender Firewall is Enabled with default rules.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;telemetry&quot;&gt;Telemetry&lt;/h3&gt;

&lt;p&gt;Whether analyzing unknown binaries or working on sensitive projects, endpoint telemetry powers detection and response operations. DARKSURGEON comes pre-configured with the following telemetry sources available for analysis:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Windows Event Log Auditing is enabled. (&lt;a href=&quot;https://github.com/palantir/windows-event-forwarding&quot;&gt;Palantir Windows Event Forwarding Guidance&lt;/a&gt;).&lt;/li&gt;
  &lt;li&gt;Windows Powershell Auditing is enabled. (&lt;a href=&quot;https://github.com/palantir/windows-event-forwarding&quot;&gt;Palantir Windows Event Forwarding Guidance&lt;/a&gt;).&lt;/li&gt;
  &lt;li&gt;Sysinternals Sysmon is installed and configured. (&lt;a href=&quot;https://github.com/SwiftOnSecurity/sysmon-config&quot;&gt;SwiftonSecurity Ruleset&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;privacy&quot;&gt;Privacy&lt;/h3&gt;

&lt;p&gt;Your operational environment contains some of the most sensitive data from your network, and it’s important to safeguard that from prying eyes. DARKSURGEON implements the following strategies to maximize privacy without hindering workflows:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Windows 10 telemetry settings are configured to minimize collection.&lt;/li&gt;
  &lt;li&gt;Cortana, diagnostics, tracking, and other services are disabled.&lt;/li&gt;
  &lt;li&gt;Windows Error Reporting (WER) is disabled.&lt;/li&gt;
  &lt;li&gt;Windows Timeline, shared clipboard, device hand-off, and other synchronize-by-default applications are disabled or neutered.&lt;/li&gt;
  &lt;li&gt;Microsoft Guidance for reducing telemetry and data collection has been implemented.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;base-tooling&quot;&gt;Base Tooling&lt;/h3&gt;

&lt;p&gt;Out of the box, DARKSURGEON comes equipped with tools, scripts, and binaries to make your life as a defender easier. The following are a non-exhaustive listing of the various categories and tools present in the project:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Android Analysis:&lt;/strong&gt; Tools, scripts, and binaries focused on android analysis and reverse engineering. Examples include:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;APKTool&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Blue Team:&lt;/strong&gt; Tools, scripts, and binaries focused on blue team, network defense, and alerting/detection development. Examples include:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Atomic Red Teaming (Red Canary)&lt;/li&gt;
  &lt;li&gt;Bloodhound / Sharphound&lt;/li&gt;
  &lt;li&gt;CimSweep&lt;/li&gt;
  &lt;li&gt;Dumpsterfire&lt;/li&gt;
  &lt;li&gt;EndGame Red Team Automation (RTA)&lt;/li&gt;
  &lt;li&gt;Kansa&lt;/li&gt;
  &lt;li&gt;Invoke-ATTACKAPI&lt;/li&gt;
  &lt;li&gt;Posh-Sysmon&lt;/li&gt;
  &lt;li&gt;PowerForensics&lt;/li&gt;
  &lt;li&gt;Yara&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Debuggers:&lt;/strong&gt; Tools, scripts, and binaries for debugging binary artifacts. Examples include:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Ollydbg&lt;/li&gt;
  &lt;li&gt;x64dbg&lt;/li&gt;
  &lt;li&gt;Windbg&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Disassemblers:&lt;/strong&gt; Tools, scripts, and binaries for disassembling binary artifacts. Examples include:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;IDA 7 (Demo)&lt;/li&gt;
  &lt;li&gt;Binary Ninja (Demo)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;DotNet Analysis:&lt;/strong&gt; Tools, scripts, and binaries for performing analysis of DotNet artifacts. Examples include:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;DNSpy&lt;/li&gt;
  &lt;li&gt;DotPeek&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Flash Analysis:&lt;/strong&gt; Tools, scripts, and binaries for performing analysis of flash artifacts. Examples include:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;FFDec&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Forensic Analysis:&lt;/strong&gt; Tools, scripts, and binaries for performing forensic analysis on application and operating system artifacts. Examples include:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Amcache Parser&lt;/li&gt;
  &lt;li&gt;AppCompatCache Parser&lt;/li&gt;
  &lt;li&gt;Shellbags Explorer&lt;/li&gt;
  &lt;li&gt;TSK (The Sleuthkit)&lt;/li&gt;
  &lt;li&gt;Volatility&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Hex Editors:&lt;/strong&gt; Hex editing software. Examples include:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;HxD&lt;/li&gt;
  &lt;li&gt;010 Editor&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Java Analysis:&lt;/strong&gt; Tools, scripts, and binaries for performing analysis of Java artifacts. Examples include:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;JD-GUI&lt;/li&gt;
  &lt;li&gt;Dex2JAR&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Network Analysis:&lt;/strong&gt; Tools, scripts, and binaries for performing analysis of network traffic and protocols. Examples include:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Burp Free&lt;/li&gt;
  &lt;li&gt;FakeNet-NG&lt;/li&gt;
  &lt;li&gt;Wireshark&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;PE Analysis:&lt;/strong&gt; Tools, scripts, and binaries for performing analysis of PE artifacts. Examples include:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;ExplorerSuite (CFF Explorer)&lt;/li&gt;
  &lt;li&gt;PEStudio&lt;/li&gt;
  &lt;li&gt;PEview&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Powershell Modules:&lt;/strong&gt; Administration, productivity, and support modules for Powershell. Examples include:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Active Directory (RSAT)&lt;/li&gt;
  &lt;li&gt;Azure Management&lt;/li&gt;
  &lt;li&gt;Pester&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Python Libraries:&lt;/strong&gt; Administration, productivity, and support libraries for Python. Examples include:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;OLETools&lt;/li&gt;
  &lt;li&gt;Passivetotal&lt;/li&gt;
  &lt;li&gt;PEFile&lt;/li&gt;
  &lt;li&gt;PyCryptodome&lt;/li&gt;
  &lt;li&gt;Scapy&lt;/li&gt;
  &lt;li&gt;Shodan&lt;/li&gt;
  &lt;li&gt;Vivisect&lt;/li&gt;
  &lt;li&gt;Yara-Python&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Red Team:&lt;/strong&gt; Tools, scripts, and binaries focused on red team, network exploitation, and alerting/detection development. Examples include:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Grouper&lt;/li&gt;
  &lt;li&gt;Inveigh&lt;/li&gt;
  &lt;li&gt;PowerupSQL&lt;/li&gt;
  &lt;li&gt;PSAttack&lt;/li&gt;
  &lt;li&gt;Responder&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Remote Management:&lt;/strong&gt; Administration, productivity, and support modules for remote management of systems and applications. Examples include:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;AWS Command Line (AWSCLI)&lt;/li&gt;
  &lt;li&gt;Remote Server Administration Tools (RSAT)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Utilities:&lt;/strong&gt; Administration, productivity, and support utilities. Examples include:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;API Monitor&lt;/li&gt;
  &lt;li&gt;Chocolatey&lt;/li&gt;
  &lt;li&gt;Cyber Chef&lt;/li&gt;
  &lt;li&gt;Windows Subsystem for Linux (WSL)&lt;/li&gt;
  &lt;li&gt;Winlogbeat&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Visual Basic Analysis:&lt;/strong&gt; Tools, scripts, and binaries for performing analysis of Visual Basic artifacts. Examples include:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;VBDecompiler&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;building-darksurgeon&quot;&gt;Building DARKSURGEON&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/posts/darksurgeon-02.png&quot; alt=&quot;alt text&quot; height=&quot;350px&quot; class=&quot;center-image&quot; /&gt;&lt;br /&gt;
&lt;span class=&quot;caption text-muted&quot;&gt;The Mark of a Successful Build.&lt;/span&gt;&lt;/p&gt;

&lt;h4 id=&quot;build-process&quot;&gt;Build Process&lt;/h4&gt;

&lt;p&gt;DARKSURGEON is built using the &lt;a href=&quot;https://www.packer.io/&quot;&gt;HashiCorp application packer&lt;/a&gt;. The total build time for a new instance of DARKSURGEON is around 2–3 hours.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Packer creates a new virtual machine using the DARKSURGEON JSON file and your hypervisor of choice (e.g. Hyper-V, Virtualbox, VMWare).&lt;/li&gt;
  &lt;li&gt;The answers.iso file is mounted inside the DARKSURGEON VM along with the Windows ISO. The answers.iso file contains the unattend.xml needed for a touchless installation of windows, as well as a powershell script to configure Windows Remote Management (winrm).&lt;/li&gt;
  &lt;li&gt;Packer connects to the DARKSURGEON VM using WinRM and copies over all files in the helper-scripts and configuration-files directory to the host.&lt;/li&gt;
  &lt;li&gt;Packer performs serial installations of each of the configured powershell scripts, performing occasional reboots as needed.&lt;/li&gt;
  &lt;li&gt;When complete, packer performs a sysprep, shuts down the virtual machine, and creates a vagrant box file. Additional outputs may be specified in the post-processors section of the JSON file.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4 id=&quot;setup&quot;&gt;Setup&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Note: Hyper-V is currently the only supported hypervisor in this alpha release. VirtualBox and VMWare support are forthcoming.&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Install packer, vagrant, and your preferred hypervisor on your host.&lt;/li&gt;
  &lt;li&gt;Download the repository contents to your host.&lt;/li&gt;
  &lt;li&gt;Download a Windows 10 Enterprise Evaluation ISO (1803).&lt;/li&gt;
  &lt;li&gt;Move the ISO file to your local DAKRSURGEON repository.&lt;/li&gt;
  &lt;li&gt;Update the DARKSURGEON.json file with the Windows ISO SHA1 hash and file name.&lt;/li&gt;
  &lt;li&gt;(Optional) Execute the powershell script New-DARKSURGEONISO.ps1 to generate a new answers.iso file. There is an answers ISO file included in the repository but you may re-build this if you don’t trust it, or you would like to modify the unattend files:&lt;br /&gt;
&lt;code class=&quot;highlighter-rouge&quot;&gt;powershell.exe New-DARKSURGEONISO.ps1&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Build the recipe using packer:&lt;br /&gt;
&lt;code class=&quot;highlighter-rouge&quot;&gt;packer build -only=[hyperv-iso|vmware|virtualbox] .\DARKSURGEON.json&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;configuring-darksurgeon&quot;&gt;Configuring DARKSURGEON&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/posts/darksurgeon-03.png&quot; alt=&quot;alt text&quot; height=&quot;650px&quot; class=&quot;center-image&quot; /&gt;&lt;br /&gt;
&lt;span class=&quot;caption text-muted&quot;&gt;Need new capabilities? Add them to DARKSURGEON.json.&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;DARKSURGEON is designed to be modular and easy to configure. An example configuration is provided in the DARKSURGEON.json file, but you may add, remove, or tweak any of the underlying scripts.&lt;/p&gt;

&lt;p&gt;Have a custom CA you need to add? Need to add a license file for IDA? No problem. You can throw any files you need in the configuration-files directory and they’ll be copied over to the host for you.&lt;/p&gt;

&lt;p&gt;Want to install a custom package, or need some specific OS tweaks? No worries. Simply make a new powershell script (or modify an existing one) in the configuration-scripts directory and add it as a build step in the packer JSON file.&lt;/p&gt;

&lt;h3 id=&quot;using-darksurgeon&quot;&gt;Using DARKSURGEON&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Note: Hyper-V is currently the only supported hypervisor in this alpha release. VirtualBox and VMWare support are forthcoming.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/posts/darksurgeon-04.png&quot; alt=&quot;alt text&quot; height=&quot;300px&quot; class=&quot;center-image&quot; /&gt;&lt;br /&gt;
&lt;span class=&quot;caption text-muted&quot;&gt;Vagrant up to fight bad guys.&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;Once DARKSURGEON has successfully built, you’ll receive an output vagrant box file. The box file contains the virtual machine image and vagrant metadata, allowing you to quickly spin up a virtual machine as needed.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Install vagrant and your preferred hypervisor on your host.&lt;/li&gt;
  &lt;li&gt;Navigate to the DARKSURGEON repository (or the location where you’ve saved the DARKSURGEON box file).&lt;/li&gt;
  &lt;li&gt;Perform a vagrant up:
&lt;code class=&quot;highlighter-rouge&quot;&gt;vagrant up&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Vagrant will now extract the virtual machine image from the box file, read the metadata, and create a new VM for you.&lt;/p&gt;

&lt;p&gt;Want to kill this VM and get a new one? Easy, just perform the following:
&lt;code class=&quot;highlighter-rouge&quot;&gt;vagrant destroy &amp;amp;&amp;amp; vagrant up&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Once the DARKSURGEON virtual machine is running, you can login using one of the two local accounts:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note: These are default accounts with default credentials. You may want to consider changing the credentials in your packer build.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Administrator Account:&lt;/strong&gt;&lt;br /&gt;
Username: darksurgeon&lt;br /&gt;
Password: darksurgeon&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Local User Account:&lt;/strong&gt;&lt;br /&gt;
Username: unprivileged&lt;br /&gt;
Password: unprivileged&lt;/p&gt;

&lt;p&gt;If you’d rather not use vagrant, you can either import the VM image manually, or look at one of the many other &lt;a href=&quot;https://www.packer.io/docs/post-processors/index.html&quot;&gt;post-processor options provided by packer.&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;next-steps&quot;&gt;Next Steps&lt;/h3&gt;

&lt;p&gt;Ready to get started? Just head over to the &lt;a href=&quot;https://github.com/cryps1s/DARKSURGEON&quot;&gt;GitHub Repository and download the project.&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;contributing&quot;&gt;Contributing&lt;/h3&gt;

&lt;p&gt;Contributions, fixes, and improvements can be submitted directly against this project as a &lt;a href=&quot;https://github.com/cryps1s/DARKSURGEON/issues&quot;&gt;GitHub issue or pull request.&lt;/a&gt; Tools will be reviewed and added on a case-by-case basis.&lt;/p&gt;

&lt;h3 id=&quot;further-reading-and-acknowledgements&quot;&gt;Further Reading and Acknowledgements&lt;/h3&gt;

&lt;p&gt;This project stands on the shoulders of giants, and I cannot properly thank all of the original authors for their work, contributions, and inspiration.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/joefitzgerald&quot;&gt;Joe Fitzgerald&lt;/a&gt; for pioneering Windows packer projects.&lt;/li&gt;
  &lt;li&gt;The FLARE team at FireEye for their awesome work on the chocolatey packages and repository for the &lt;a href=&quot;https://github.com/fireeye/flare-vm&quot;&gt;FLAREVM project.&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://twitter.com/Centurion&quot;&gt;Chris Long&lt;/a&gt; for his awesome work on &lt;a href=&quot;https://github.com/clong/DetectionLab&quot;&gt;DetectionLab&lt;/a&gt; and the packer CI pipeline.&lt;/li&gt;
  &lt;li&gt;All of the authors, chocolatey package maintainers, and tool writers that made this possible.&lt;/li&gt;
  &lt;li&gt;Friends and colleagues for challenging me to finally open source this project.&lt;/li&gt;
&lt;/ul&gt;</content><author><name>cryps1s</name></author><summary type="html">I’m happy to announce the alpha release of DARKSURGEON, a Windows 10 packer project to empower incident response, digital forensics, malware analysis, and network defense.</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blog.dane.io/assets/img/posts/darksurgeon-00.jpg" /><media:content medium="image" url="https://blog.dane.io/assets/img/posts/darksurgeon-00.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Endpoint Isolation with the Windows Firewall</title><link href="https://blog.dane.io/2018/04/22/endpoint-isolation-with-the-windows-firewall.html" rel="alternate" type="text/html" title="Endpoint Isolation with the Windows Firewall" /><published>2018-04-22T08:00:00+00:00</published><updated>2018-04-22T08:00:00+00:00</updated><id>https://blog.dane.io/2018/04/22/endpoint-isolation-with-the-windows-firewall</id><content type="html" xml:base="https://blog.dane.io/2018/04/22/endpoint-isolation-with-the-windows-firewall.html">&lt;p&gt;Over the last few weeks, I’ve had conversations with several individuals around mitigating lateral movement in a Windows environment. In all of these cases, I was surprised to learn that these defenders were not using the native Windows Firewall as one of their defense-in-depth layers. This was curious to me as the firewall is both present by default and is one of the easiest ways to limit remote access to many commonly-abused services.&lt;/p&gt;

&lt;p&gt;This post is going to focus on using the Windows Firewall for isolating and securing endpoints in an Active Directory environment. The goal is to limit the potential attack surface of endpoints by limiting access to potentially exploitable services, require IPSEC authentication to management services, and provide additional encryption to services which rely on plaintext or weak ciphers. The configurations listed in this post should be immediately deployable in a production environment and ultimate make our adversary’s lateral movement attempts that much more frustrating.&lt;/p&gt;

&lt;p&gt;An important note: you should go watch &lt;a href=&quot;https://twitter.com/jepayneMSFT&quot;&gt;Jessica Payne’s&lt;/a&gt; &lt;a href=&quot;https://channel9.msdn.com/Events/Ignite/New-Zealand-2016/M377&quot;&gt;Demystifying the Windows Firewall&lt;/a&gt; talk from Ignite 2016. Most of the content in this post is simply a re-hash of the best practices and strategies that she has outlined in her presentation. Her talk is the reference for the Windows Firewall.
Seriously, go watch it right now.&lt;/p&gt;

&lt;h2 id=&quot;firewall-principles&quot;&gt;Firewall Principles&lt;/h2&gt;

&lt;p&gt;There are some basic principles to adhere to when developing a comprehensive firewall policy:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Manage centrally&lt;/strong&gt;. We’re going to rely on using Group Policy Objects (GPO) for managing our firewall rules. This has the benefit of native integration within Active Directory and, if using Advanced Group Policy Management (AGPM), change control, rollback, and auditing features.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Block by default&lt;/strong&gt;. We’re going to block services by default. We will whitelist critical services we need with appropriate scope. Everything else can get tossed to the void.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Require authentication&lt;/strong&gt;. We’re going to challenge remote devices and users to authenticate before they can communicate to our critical services. If they fail authentication, they get tossed to the void.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Encrypt plaintext protocols&lt;/strong&gt;. We’re going to apply encryption and integrity protections on plaintext protocols.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Use strong cryptographic settings&lt;/strong&gt;. We’re going to use strong ciphers, key sizes, and protocols when establishing IPSec tunnels.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Ignore local policies&lt;/strong&gt;. By default, any user or application can create local firewall rules. To ensure our ruleset isn’t accidentally or intentionally subverted, we’re going to deny local rules from applying in the firewall.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;firewall-base-settings-endpoints&quot;&gt;Firewall Base Settings (Endpoints)&lt;/h2&gt;

&lt;p&gt;From these principles, we can now start the process of building our firewall settings. These will configure how the firewall operates, determine logging settings, and set authentication and encryption options for IPSEC.&lt;/p&gt;

&lt;p&gt;To start, we’ll open up the &lt;strong&gt;Group Policy Management&lt;/strong&gt; editor (gpmc.msc) and make a new GPO called Workstation Firewall Policy.
Scope this to the OU containing your workstations of choice but &lt;strong&gt;do not apply it yet&lt;/strong&gt; (remove “Authenticated Users” from the security filter).&lt;/p&gt;

&lt;p&gt;In the GPO manager, navigate to &lt;strong&gt;Computer Configuration &amp;gt; Windows Settings &amp;gt; Security Settings &amp;gt; Windows Defender Firewall with Advanced Security&lt;/strong&gt;&lt;/p&gt;

&lt;h3 id=&quot;configuring-firewallsettings&quot;&gt;Configuring Firewall Settings&lt;/h3&gt;

&lt;p&gt;The first option we’ll set is to enforce the Firewall to be enabled on all profiles. Navigate to each of the Profile Tabs and set the following settings:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Firewall State:&lt;/strong&gt; On&lt;br /&gt;
&lt;strong&gt;Inbound Connections:&lt;/strong&gt; Block&lt;br /&gt;
&lt;strong&gt;Outbound Connections:&lt;/strong&gt; Allow&lt;/p&gt;

&lt;h4 id=&quot;settings&quot;&gt;Settings&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Display a Notification:&lt;/strong&gt; No&lt;br /&gt;
 &lt;strong&gt;Allow Unicast Response:&lt;/strong&gt; Yes&lt;br /&gt;
 &lt;strong&gt;Apply Local Firewall Rules:&lt;/strong&gt; No&lt;br /&gt;
 &lt;strong&gt;Apply Local Connection Security Rules:&lt;/strong&gt; No&lt;/p&gt;

&lt;h4 id=&quot;logging&quot;&gt;Logging&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Name:&lt;/strong&gt; Default&lt;br /&gt;
&lt;strong&gt;Size Limit:&lt;/strong&gt; 4096 (or higher - dealer’s choice)&lt;br /&gt;
&lt;strong&gt;Log Dropped Packets:&lt;/strong&gt; Yes&lt;br /&gt;
&lt;strong&gt;Log Successful Connections:&lt;/strong&gt; No&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/posts/firewall-01.png&quot; alt=&quot;alt text&quot; height=&quot;650px&quot; class=&quot;center-image&quot; /&gt;&lt;br /&gt;
&lt;span class=&quot;caption text-muted&quot;&gt;Desired firewall settings.&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/posts/firewall-02.png&quot; alt=&quot;alt text&quot; height=&quot;650px&quot; class=&quot;center-image&quot; /&gt;&lt;br /&gt;
&lt;span class=&quot;caption text-muted&quot;&gt;Desired firewall settings.&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/posts/firewall-03.png&quot; alt=&quot;alt text&quot; height=&quot;550px&quot; class=&quot;center-image&quot; /&gt;&lt;br /&gt;
&lt;span class=&quot;caption text-muted&quot;&gt;Desired firewall settings.&lt;/span&gt;&lt;/p&gt;

&lt;h3 id=&quot;configuring-ipsec-settings&quot;&gt;Configuring IPSEC Settings&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;NOTE: IPSEC ciphers, key sizes, and exchange protocols may need to be tailored to your environment and needs. These selections assume a modern fleet with strong security requirements. Avoid DES and MD5 in any configuration.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The second option we’ll set are the IPSEC settings. Navigate to the IPSEC Settings Tab and set the following settings:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Exchange Main Mode:&lt;/strong&gt; Advanced&lt;br /&gt;
&lt;strong&gt;Security Methods:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;SHA-384-AES-CBC-256-Elliptic Curve Diffie-Hellman-P-384&lt;/li&gt;
  &lt;li&gt;SHA-384-AES-CBC-192-Elliptic Curve Diffie-Hellman-P-384&lt;/li&gt;
  &lt;li&gt;SHA-384-AES-CBC-128-Elliptic Curve Diffie-Hellman-P-384&lt;/li&gt;
  &lt;li&gt;SHA-256-AES-CBC-256-Elliptic Curve Diffie-Hellman-P-256&lt;/li&gt;
  &lt;li&gt;SHA-256-AES-CBC-192-Elliptic Curve Diffie-Hellman-P-256&lt;/li&gt;
  &lt;li&gt;SHA-256-AES-CBC-128-Elliptic Curve Diffie-Hellman-P-256&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Key Lifespan:&lt;/strong&gt; 480 minutes&lt;br /&gt;
&lt;strong&gt;Use Diffie-Hellman:&lt;/strong&gt; Yes&lt;br /&gt;
&lt;strong&gt;Data Protection Quick Mode:&lt;/strong&gt; Advanced&lt;br /&gt;
&lt;strong&gt;Security Methods (Data Integrity):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;ESP-AES-GMAC-256 (60/100,000)&lt;/li&gt;
  &lt;li&gt;ESP-AES-GMAC-192 (60/100,000)&lt;/li&gt;
  &lt;li&gt;ESP-AES-GMAC-128 (60/100,000)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Security Methods (Data Integrity/Encryption):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;ESP-AES-GCM-256 (60/100,000)&lt;/li&gt;
  &lt;li&gt;ESP-AES-GCM-192 (60/100,000)&lt;/li&gt;
  &lt;li&gt;ESP-AES-GCM-128 (60/100,000)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Authentication Method:&lt;/strong&gt; Computer and Kerberos (v5)&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/posts/firewall-04.png&quot; alt=&quot;alt text&quot; height=&quot;650px&quot; class=&quot;center-image&quot; /&gt;&lt;br /&gt;
&lt;span class=&quot;caption text-muted&quot;&gt;Desired IPSec Key Exchange Settings.&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/posts/firewall-05.png&quot; alt=&quot;alt text&quot; height=&quot;550px&quot; class=&quot;center-image&quot; /&gt;&lt;br /&gt;
&lt;span class=&quot;caption text-muted&quot;&gt;Desired IPSec Quick Mode Settings.&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/posts/firewall-06.png&quot; alt=&quot;alt text&quot; height=&quot;650px&quot; class=&quot;center-image&quot; /&gt;&lt;br /&gt;
&lt;span class=&quot;caption text-muted&quot;&gt;Desired IPSec Settings.&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;At this stage, we’ve gone ahead and configured the base policies for the firewall. This has the following effects:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The firewall will be enabled on all profiles.&lt;/li&gt;
  &lt;li&gt;The firewall will ignore locally applied rules.&lt;/li&gt;
  &lt;li&gt;The firewall will log dropped packets for debugging purposes.&lt;/li&gt;
  &lt;li&gt;Local firewall rules will not be applied.&lt;/li&gt;
  &lt;li&gt;IPSec is configured to use strong ciphers, keys, and protocols.&lt;/li&gt;
  &lt;li&gt;IPSec authentication will use kerberos for user and computer accounts.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;firewall-connection-security-rules-endpoints&quot;&gt;Firewall Connection Security Rules (Endpoints)&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Note: As you develop new rules, you should deploy to a subset of systems using the security filter. Failure to adequately test firewall rules could cause a loss of availability for critical systems.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We will now start the process of implementing connection security rules for the endpoints. &lt;a href=&quot;https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2008-R2-and-2008/cc772017%28v%3dws.10%29&quot;&gt;Connection security rules&lt;/a&gt; allow for complex management of IPSEC tunnels to include authentication from users or computers prior to establishment of sessions.&lt;/p&gt;

&lt;p&gt;In essence, we will use these rules to require both computers on each end of a given session to establish an authenticated (and optionally: encrypted) session to protect critical services. These rules do not deal with directionality or access controls, so they will be used in conjunction with standard firewall rules later in this post.&lt;/p&gt;

&lt;p&gt;In the GPO editor, open up the &lt;strong&gt;Workstations Firewall Policy&lt;/strong&gt; and navigate to &lt;strong&gt;Computer Configuration &amp;gt; Windows Settings &amp;gt; Security Settings &amp;gt; Windows Defender Firewall with Advanced Security &amp;gt; Connection Security Rules&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;We’ll use a standard naming scheme for our rules to make it easier to understand and troubleshoot rule issues:&lt;br /&gt;
&lt;strong&gt;GPO-{Secure}-{Service}-Profile&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/posts/firewall-07.png&quot; alt=&quot;alt text&quot; height=&quot;60px&quot; class=&quot;center-image&quot; /&gt;&lt;br /&gt;
&lt;span class=&quot;caption text-muted&quot;&gt;Connection Security Rules.&lt;/span&gt;&lt;/p&gt;

&lt;h4 id=&quot;securing-winrm&quot;&gt;Securing WinRM&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Note: As you develop new rules, you should use the “Request Authentication for Inbound and Outbound Settings” option, as it will gracefully fall back for troubleshooting purposes. This should be changed to “Require Authentication” once it is stable.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The first rule we’ll implement will secure WinRM by requiring successful kerberos authentication from trusted computers and users. This is designed to gate access to WinRM only from trusted machines on the network, such as Windows Event Collectors, bastion hosts, and other management devices. This additionally mitigates the risk of exploits targeting WinRM and associated services.&lt;/p&gt;

&lt;p&gt;Implement this rule with the following details:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rule Type:&lt;/strong&gt; Custom&lt;br /&gt;
&lt;strong&gt;Endpoint 1:&lt;/strong&gt; Any&lt;br /&gt;
&lt;strong&gt;Endpoint 2:&lt;/strong&gt; Any&lt;br /&gt;
&lt;strong&gt;Requirements:&lt;/strong&gt; Request Authentication for Inbound and Outbound Settings&lt;br /&gt;
&lt;strong&gt;Authentication Method:&lt;/strong&gt; Default (User/Computer Kerberos v5)&lt;br /&gt;
&lt;strong&gt;Protocol Type:&lt;/strong&gt; TCP&lt;br /&gt;
&lt;strong&gt;Endpoint 1 Port:&lt;/strong&gt; 5985, 5986&lt;br /&gt;
&lt;strong&gt;Endpoint 2 Port:&lt;/strong&gt; All Ports&lt;br /&gt;
&lt;strong&gt;Scope (Local):&lt;/strong&gt; Any IP Address&lt;br /&gt;
&lt;strong&gt;Scope (Remote):&lt;/strong&gt; Any IP Address&lt;br /&gt;
&lt;strong&gt;Profile:&lt;/strong&gt; All&lt;br /&gt;
&lt;strong&gt;Name:&lt;/strong&gt; GPO-Secure-WinRM-Policy&lt;/p&gt;

&lt;h4 id=&quot;securing-rdp&quot;&gt;Securing RDP&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Note: As you develop new rules, you should use the “Request Authentication for Inbound and Outbound Settings” option, as it will gracefully fall back for troubleshooting purposes. This should be changed to “Require Authentication” once it is stable.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The next rule we’ll implement will secure RDP by requiring successful kerberos authentication from trusted computers and users. This is designed to gate access to RDP only from trusted machines on the network, such as help-desk machines, bastion hosts, and other management devices. This additionally mitigates the risk of exploits targeting RDP and associated services.&lt;/p&gt;

&lt;p&gt;Implement this rule with the following details:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rule Type:&lt;/strong&gt; Custom&lt;br /&gt;
&lt;strong&gt;Endpoint 1:&lt;/strong&gt; Any&lt;br /&gt;
&lt;strong&gt;Endpoint 2:&lt;/strong&gt; Any&lt;br /&gt;
&lt;strong&gt;Requirements:&lt;/strong&gt; Request Authentication for Inbound and Outbound Settings&lt;br /&gt;
&lt;strong&gt;Authentication Method:&lt;/strong&gt; Default (User/Computer Kerberos v5)&lt;br /&gt;
&lt;strong&gt;Protocol Type:&lt;/strong&gt; TCP&lt;br /&gt;
&lt;strong&gt;Endpoint 1 Port:&lt;/strong&gt; 3389
&lt;strong&gt;Endpoint 2 Port:&lt;/strong&gt; All Ports&lt;br /&gt;
&lt;strong&gt;Scope (Local):&lt;/strong&gt; Any IP Address&lt;br /&gt;
&lt;strong&gt;Scope (Remote):&lt;/strong&gt; Any IP Address&lt;br /&gt;
&lt;strong&gt;Profile:&lt;/strong&gt; All&lt;br /&gt;
&lt;strong&gt;Name:&lt;/strong&gt; GPO-Secure-RDP-Policy&lt;/p&gt;

&lt;h3 id=&quot;firewall-rules-endpoints&quot;&gt;Firewall Rules (Endpoints)&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Note: As you develop new rules, you should deploy to a subset of systems using the security filter. Failure to adequately test firewall rules could cause a loss of availability for critical systems.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We will now start the process of implementing firewall rules for the endpoints.&lt;/p&gt;

&lt;p&gt;In the GPO editor, open up the &lt;strong&gt;Workstations Firewall Policy&lt;/strong&gt; and navigate to &lt;strong&gt;Computer Configuration &amp;gt; Windows Settings &amp;gt; Security Settings &amp;gt; Windows Defender Firewall with Advanced Security &amp;gt; Inbound Rules&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;We’ll use a standard naming scheme for our rules to make it easier to understand and troubleshoot rule issues:&lt;/p&gt;

&lt;!-- markdownlint-disable MD036 --&gt;
&lt;p&gt;&lt;strong&gt;GPO-{Allow,Block,Secure}-{Service}-{Protocol}&lt;/strong&gt;
&lt;!-- markdownlint-enable MD036 --&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/posts/firewall-08.png&quot; alt=&quot;alt text&quot; height=&quot;170px&quot; class=&quot;center-image&quot; /&gt;&lt;br /&gt;
&lt;span class=&quot;caption text-muted&quot;&gt;Example of My Firewall Rules.&lt;/span&gt;&lt;/p&gt;

&lt;h4 id=&quot;blocking-smb--remote-named-pipes&quot;&gt;Blocking SMB / Remote Named Pipes&lt;/h4&gt;

&lt;p&gt;The first rule we’ll implement will block incoming Server Message Block (SMB) connections. This is designed to prevent remote access to file shares on the workstation, as well as mitigate the risk of exploits targeting SMB and associated services.&lt;/p&gt;

&lt;p&gt;Implement this rule with the following details:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rule&lt;/strong&gt; Type: Custom&lt;br /&gt;
&lt;strong&gt;Programs&lt;/strong&gt;: All Programs&lt;br /&gt;
&lt;strong&gt;Protocol&lt;/strong&gt; Type: TCP&lt;br /&gt;
&lt;strong&gt;Local&lt;/strong&gt; Port: 445&lt;br /&gt;
&lt;strong&gt;Remote&lt;/strong&gt; Port: All Ports&lt;br /&gt;
&lt;strong&gt;Scope&lt;/strong&gt; (Local): Any IP Address&lt;br /&gt;
&lt;strong&gt;Scope&lt;/strong&gt; (Remote): Any IP Address&lt;br /&gt;
&lt;strong&gt;Action&lt;/strong&gt;: Block the Connection&lt;br /&gt;
&lt;strong&gt;Profile&lt;/strong&gt;: All&lt;br /&gt;
&lt;strong&gt;Name&lt;/strong&gt;: GPO-Block-SMB-TCP&lt;/p&gt;

&lt;h4 id=&quot;blocking-netbios--nbt&quot;&gt;Blocking NetBIOS / NBT&lt;/h4&gt;

&lt;p&gt;The next rule we’ll implement will block incoming NetBIOS and NetBIOS over TCP (NBT) connections. As NetBIOS is not required in a modern environment, this rule will mitigate the risk of exploits targeting NetBIOS and associated services.&lt;/p&gt;

&lt;p&gt;Implement this rule with the following details:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rule Type&lt;/strong&gt;: Custom&lt;br /&gt;
&lt;strong&gt;Programs:&lt;/strong&gt; All Programs&lt;br /&gt;
&lt;strong&gt;Protocol Type&lt;/strong&gt;: TCP&lt;br /&gt;
&lt;strong&gt;Local Port&lt;/strong&gt;: 137, 138, 139&lt;br /&gt;
&lt;strong&gt;Remote Port&lt;/strong&gt;: All Ports&lt;br /&gt;
&lt;strong&gt;Scope (Local&lt;/strong&gt;): Any IP Address&lt;br /&gt;
&lt;strong&gt;Scope (Remote&lt;/strong&gt;): Any IP Address&lt;br /&gt;
&lt;strong&gt;Action:&lt;/strong&gt; Block the Connection&lt;br /&gt;
&lt;strong&gt;Profile:&lt;/strong&gt; All&lt;br /&gt;
&lt;strong&gt;Name:&lt;/strong&gt; GPO-Block-NetBIOS-TCP&lt;/p&gt;

&lt;p&gt;We’ll repeat this rule, but for UDP. Implement this rule with the following details:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rule Type&lt;/strong&gt;: Custom&lt;br /&gt;
&lt;strong&gt;Programs:&lt;/strong&gt; All Programs&lt;br /&gt;
&lt;strong&gt;Protocol Type&lt;/strong&gt;: UDP&lt;br /&gt;
&lt;strong&gt;Local Port&lt;/strong&gt;: 137, 138, 139&lt;br /&gt;
&lt;strong&gt;Remote Port&lt;/strong&gt;: All Ports&lt;br /&gt;
&lt;strong&gt;Scope (Local&lt;/strong&gt;): Any IP Address&lt;br /&gt;
&lt;strong&gt;Scope (Remote&lt;/strong&gt;): Any IP Address&lt;br /&gt;
&lt;strong&gt;Action:&lt;/strong&gt; Block the Connection&lt;br /&gt;
&lt;strong&gt;Profile:&lt;/strong&gt; All&lt;br /&gt;
&lt;strong&gt;Name:&lt;/strong&gt; GPO-Block-NetBIOS-UDP&lt;/p&gt;

&lt;h4 id=&quot;blocking-rpcdcomwmi&quot;&gt;Blocking RPC/DCOM/WMI&lt;/h4&gt;

&lt;p&gt;The next rule we’ll implement will block incoming Remote Procedure Call (RPC) connections. RPC allows access to the Distributed COM (DCOM) service, the WMI service, and many other windows services. This rule will mitigate the risk of exploits targeting RPC and associated services.
Implement this rule with the following details:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rule Type:&lt;/strong&gt; Custom&lt;br /&gt;
&lt;strong&gt;Programs:&lt;/strong&gt; All Programs&lt;br /&gt;
&lt;strong&gt;Protocol Type:&lt;/strong&gt; TCP&lt;br /&gt;
&lt;strong&gt;Local Port:&lt;/strong&gt; 135, 593&lt;br /&gt;
&lt;strong&gt;Remote Port:&lt;/strong&gt; All Ports&lt;br /&gt;
&lt;strong&gt;Scope (Local):&lt;/strong&gt; Any IP Address&lt;br /&gt;
&lt;strong&gt;Scope (Remote):&lt;/strong&gt; Any IP Address&lt;br /&gt;
&lt;strong&gt;Action: Block&lt;/strong&gt; the Connection&lt;br /&gt;
&lt;strong&gt;Profile:&lt;/strong&gt; All&lt;br /&gt;
&lt;strong&gt;Name:&lt;/strong&gt; GPO-Block-RPC-TCP&lt;/p&gt;

&lt;p&gt;We’ll repeat this rule, but for UDP. Implement this rule with the following details:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rule Type:&lt;/strong&gt; Custom&lt;br /&gt;
&lt;strong&gt;Programs:&lt;/strong&gt; All Programs&lt;br /&gt;
&lt;strong&gt;Protocol Type:&lt;/strong&gt; UDP&lt;br /&gt;
&lt;strong&gt;Local Port:&lt;/strong&gt; 135, 593&lt;br /&gt;
&lt;strong&gt;Remote Port:&lt;/strong&gt; All Ports&lt;br /&gt;
&lt;strong&gt;Scope (Local):&lt;/strong&gt; Any IP Address&lt;br /&gt;
&lt;strong&gt;Scope (Remote):&lt;/strong&gt; Any IP Address&lt;br /&gt;
&lt;strong&gt;Action:&lt;/strong&gt; Block the Connection&lt;br /&gt;
&lt;strong&gt;Profile:&lt;/strong&gt; All&lt;br /&gt;
&lt;strong&gt;Name:&lt;/strong&gt; GPO-Block-RPC-UDP&lt;/p&gt;

&lt;h4 id=&quot;securing-winrm-connections&quot;&gt;Securing WinRM Connections&lt;/h4&gt;

&lt;p&gt;The next rule we’ll implement will secure incoming WinRM connections with an authenticated IPSEC tunnel using the security connection rule we previously built.&lt;/p&gt;

&lt;p&gt;Implement this rule with the following details:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rule Type:&lt;/strong&gt; Custom&lt;br /&gt;
&lt;strong&gt;Programs:&lt;/strong&gt; All Programs&lt;br /&gt;
&lt;strong&gt;Protocol Type:&lt;/strong&gt; TCP&lt;br /&gt;
&lt;strong&gt;Local Port:&lt;/strong&gt; 5985, 5986&lt;br /&gt;
&lt;strong&gt;Remote Port:&lt;/strong&gt; All Ports&lt;br /&gt;
&lt;strong&gt;Scope (Local):&lt;/strong&gt; Any IP Address&lt;br /&gt;
&lt;strong&gt;Scope (Remote):&lt;/strong&gt; Any IP Address&lt;br /&gt;
&lt;strong&gt;Action:&lt;/strong&gt; Allow if Secure&lt;br /&gt;
&lt;strong&gt;Profile:&lt;/strong&gt; All&lt;br /&gt;
&lt;strong&gt;Name:&lt;/strong&gt; GPO-Secure-WinRM-TCP&lt;/p&gt;

&lt;p&gt;Then, right-click on the rule and navigate to properties. Select the &lt;strong&gt;Remote Computers&lt;/strong&gt; tab. This allows you to specify which computers in your Active Directory environment are allowed to connect to this machine remotely.&lt;/p&gt;

&lt;p&gt;In this example, I am going to allow my desktop monolith to connect remotely via WinRM to any device in my network via WinRM. I am also going to allow my Windows Event Collector machine WEF to connect for event forwarding purposes.&lt;/p&gt;

&lt;p&gt;You can substitute this for any privileged access workstations (PAWs), bastion hosts, Windows Event Collectors, or other management hosts in your fleet.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/posts/firewall-09.png&quot; alt=&quot;alt text&quot; height=&quot;650px&quot; class=&quot;center-image&quot; /&gt;&lt;br /&gt;
&lt;span class=&quot;caption text-muted&quot;&gt;Remote Computer Requirements.&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;Next, we’ll specify legitimate remote users. Select the Remote User tab. This allows you to specify which users in your Active Directory environment are allowed to connect to this machine remotely.&lt;/p&gt;

&lt;p&gt;In this example, I am only going to allow myself to connect remotely via WinRM.&lt;/p&gt;

&lt;p&gt;You can substitute this for any user or user group in your fleet. These could include help-desk, workstation administrators, or other user types.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/posts/firewall-10.png&quot; alt=&quot;alt text&quot; height=&quot;650px&quot; class=&quot;center-image&quot; /&gt;&lt;br /&gt;
&lt;span class=&quot;caption text-muted&quot;&gt;Remote User Requirements.&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;Lastly, I am going to specify the requirements needed to secure this connection. Select the General Tab and click Customize under the Allow Connection if it is secure option.&lt;/p&gt;

&lt;p&gt;As WinRM uses encryption natively (e.g. kerberos or HTTPS), I do not need to double-encrypt the payload with IPSEC encryption. Additionally, I feel pretty confident that the integrity of these sessions will be guaranteed by the underlying protocol. As such, I am going to select Allow the Session to Use Null Encapsulation, which will ensure we authenticate the connection, but do not apply any encryption or integrity protections.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/posts/firewall-11.png&quot; alt=&quot;alt text&quot; height=&quot;650px&quot; class=&quot;center-image&quot; /&gt;&lt;br /&gt;
&lt;span class=&quot;caption text-muted&quot;&gt;WinRM IPSEC Settings.&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;The result of this rule is that:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Only kerberos-authenticated connections originating from HOME\dane can connect to WinRM on this machine.&lt;/li&gt;
  &lt;li&gt;Only kerberos-authenticated connections originating from HOME\WEF$ and HOME\monolith$ can connect to WinRM on this machine.&lt;/li&gt;
  &lt;li&gt;When the IPSEC session is established, it will be authenticated, but no other protections will be applied.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;securing-rdp-connections&quot;&gt;Securing RDP Connections&lt;/h4&gt;

&lt;p&gt;The next rule we’ll implement will secure incoming RDP connections with an authenticated IPSEC tunnel using the security connection rule we previously built.&lt;/p&gt;

&lt;p&gt;Implement this rule with the following details:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rule Type:&lt;/strong&gt; Custom&lt;br /&gt;
&lt;strong&gt;Programs:&lt;/strong&gt; All Programs&lt;br /&gt;
&lt;strong&gt;Protocol Type:&lt;/strong&gt; TCP&lt;br /&gt;
&lt;strong&gt;Local Port:&lt;/strong&gt; 3389&lt;br /&gt;
&lt;strong&gt;Remote Port:&lt;/strong&gt; All Ports&lt;br /&gt;
&lt;strong&gt;Scope (Local):&lt;/strong&gt; Any IP Address&lt;br /&gt;
&lt;strong&gt;Scope (Remote):&lt;/strong&gt; Any IP Address&lt;br /&gt;
&lt;strong&gt;Action:&lt;/strong&gt; Allow if Secure&lt;br /&gt;
&lt;strong&gt;Profile:&lt;/strong&gt; All&lt;br /&gt;
&lt;strong&gt;Name:&lt;/strong&gt; GPO-Secure-RDP-TCP&lt;/p&gt;

&lt;p&gt;I will repeat the Remote Users and Remote Machines configuration as per the previous rule. However, since I don’t trust RDP encryption or authentication, I am going to specify additional IPSEC security requirements.&lt;/p&gt;

&lt;p&gt;Select the General Tab and click Customize under the &lt;strong&gt;Allow Connection if it is secure option&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I am going to select Require the connections to be encrypted, which will not only authenticate the session, but force integrity and encryption protections. Additionally, select &lt;strong&gt;Allow the Computers to Dynamically Negotiate Encryption.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/posts/firewall-12.png&quot; alt=&quot;alt text&quot; height=&quot;650px&quot; class=&quot;center-image&quot; /&gt;&lt;br /&gt;
&lt;span class=&quot;caption text-muted&quot;&gt;RDP Secure Settings Settings.&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;The result of this rule is that:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Only kerberos-authenticated connections originating from HOME\dane can connect to RDP on this machine.&lt;/li&gt;
  &lt;li&gt;Only kerberos-authenticated connections originating from HOME\monolith$ can connect to RDP on this machine.&lt;/li&gt;
  &lt;li&gt;When the IPSEC session is established, it will be authenticated, but also require encryption and integrity protection.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;blocking-outbound-connections-endpoints&quot;&gt;Blocking Outbound Connections (Endpoints)&lt;/h4&gt;

&lt;p&gt;Lastly, the firewall provides an excellent interface for developing rules to prevent outbound connections from binaries on endpoints. These can be used to prevent services from communicating on untrusted profiles (e.g. Public, Private networks), preventing binaries from communicating to non-private resources (e.g. Non-RFC1918 addresses), or even from communicating at all. These rules can be very useful for catching unsophisticated techniques, especially those which rely on living off the land principles.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/posts/firewall-13.png&quot; alt=&quot;alt text&quot; height=&quot;220px&quot; class=&quot;center-image&quot; /&gt;&lt;br /&gt;
&lt;span class=&quot;caption text-muted&quot;&gt;Outbound Firewall Deny Rules.&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;In the GPO editor, open up the &lt;strong&gt;Workstations Firewall Policy&lt;/strong&gt; and navigate to &lt;strong&gt;Computer Configuration &amp;gt; Windows Settings &amp;gt; Security Settings &amp;gt; Windows Defender Firewall with Advanced Security &amp;gt; Outbound Rules&lt;/strong&gt;.&lt;/p&gt;

&lt;h5 id=&quot;blocking-calcexe&quot;&gt;Blocking Calc.exe&lt;/h5&gt;

&lt;p&gt;While not the most glamorous of defensive strategies, calc.exe is commonly abused by default behaviors for process migration and injection techniques. This is an example rule which prevents calc.exe from communicating with any network resources.
Implement this rule with the following details:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rule Type:&lt;/strong&gt; Custom&lt;br /&gt;
&lt;strong&gt;Programs:&lt;/strong&gt; %SystemRoot%\System32\calc.exe&lt;br /&gt;
&lt;strong&gt;Protocol Type:&lt;/strong&gt; Any&lt;br /&gt;
&lt;strong&gt;Local Port:&lt;/strong&gt; Any&lt;br /&gt;
&lt;strong&gt;Remote Port:&lt;/strong&gt; All Ports&lt;br /&gt;
&lt;strong&gt;Scope (Local):&lt;/strong&gt; Any IP Address&lt;br /&gt;
&lt;strong&gt;Scope (Remote):&lt;/strong&gt; Any IP Address&lt;br /&gt;
&lt;strong&gt;Action:&lt;/strong&gt; Block&lt;br /&gt;
&lt;strong&gt;Profile:&lt;/strong&gt; All&lt;br /&gt;
&lt;strong&gt;Name:&lt;/strong&gt; GPO-Block-Calc-All&lt;/p&gt;

&lt;p&gt;We’ll repeat this rule, but for the syswow64 path. Implement this rule with the following details:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rule Type:&lt;/strong&gt; Custom&lt;br /&gt;
&lt;strong&gt;Programs:&lt;/strong&gt; %SystemRoot%\Syswow64\calc.exe&lt;br /&gt;
&lt;strong&gt;Protocol Type:&lt;/strong&gt; Any&lt;br /&gt;
&lt;strong&gt;Local Port:&lt;/strong&gt; Any&lt;br /&gt;
&lt;strong&gt;Remote Port:&lt;/strong&gt; All Ports&lt;br /&gt;
&lt;strong&gt;Scope (Local):&lt;/strong&gt; Any IP Address&lt;br /&gt;
&lt;strong&gt;Scope (Remote):&lt;/strong&gt; Any IP Address&lt;br /&gt;
&lt;strong&gt;Action:&lt;/strong&gt; Block&lt;br /&gt;
&lt;strong&gt;Profile:&lt;/strong&gt; All&lt;br /&gt;
&lt;strong&gt;Name:&lt;/strong&gt; GPO-Block-Calc-All&lt;/p&gt;

&lt;h5 id=&quot;blocking-notepadexe&quot;&gt;Blocking Notepad.exe&lt;/h5&gt;

&lt;p&gt;While not the most glamorous of defensive strategies, notepad.exe is commonly abused by default behaviors for process migration and injection techniques. This is an example rule which prevents notepad.exe from communicating with any network resources.&lt;/p&gt;

&lt;p&gt;Implement this rule with the following details:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rule Type:&lt;/strong&gt; Custom&lt;br /&gt;
&lt;strong&gt;Programs:&lt;/strong&gt; %SystemRoot%\System32\notepad.exe&lt;br /&gt;
&lt;strong&gt;Protocol Type:&lt;/strong&gt; Any&lt;br /&gt;
&lt;strong&gt;Local Port:&lt;/strong&gt; Any&lt;br /&gt;
&lt;strong&gt;Remote Port:&lt;/strong&gt; All Ports&lt;br /&gt;
&lt;strong&gt;Scope (Local):&lt;/strong&gt; Any IP Address&lt;br /&gt;
&lt;strong&gt;Scope (Remote):&lt;/strong&gt; Any IP Address&lt;br /&gt;
&lt;strong&gt;Action:&lt;/strong&gt; Block&lt;br /&gt;
&lt;strong&gt;Profile:&lt;/strong&gt; All&lt;br /&gt;
&lt;strong&gt;Name:&lt;/strong&gt; GPO-Block-Notepad-All&lt;/p&gt;

&lt;p&gt;We’ll repeat this rule, but for the syswow64 path. Implement this rule with the following details:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rule Type:&lt;/strong&gt; Custom&lt;br /&gt;
&lt;strong&gt;Programs:&lt;/strong&gt; %SystemRoot%\Syswow64\notepad.exe&lt;br /&gt;
&lt;strong&gt;Protocol Type:&lt;/strong&gt; Any&lt;br /&gt;
&lt;strong&gt;Local Port:&lt;/strong&gt; Any&lt;br /&gt;
&lt;strong&gt;Remote Port:&lt;/strong&gt; All Ports&lt;br /&gt;
&lt;strong&gt;Scope (Local):&lt;/strong&gt; Any IP Address&lt;br /&gt;
&lt;strong&gt;Scope (Remote):&lt;/strong&gt; Any IP Address&lt;br /&gt;
&lt;strong&gt;Action:&lt;/strong&gt; Block&lt;br /&gt;
&lt;strong&gt;Profile:&lt;/strong&gt; All&lt;br /&gt;
&lt;strong&gt;Name:&lt;/strong&gt; GPO-Block-Notepad-All&lt;/p&gt;

&lt;h5 id=&quot;blocking-conhostexe&quot;&gt;Blocking Conhost.exe&lt;/h5&gt;

&lt;p&gt;While not the most glamorous of defensive strategies, conhost.exe is commonly abused by default behaviors for process migration and injection techniques. This is an example rule which prevents conhost.exe from communicating with any network resources.&lt;/p&gt;

&lt;p&gt;Implement this rule with the following details:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rule Type:&lt;/strong&gt; Custom&lt;br /&gt;
&lt;strong&gt;Programs:&lt;/strong&gt; %SystemRoot%\System32\conhost.exe&lt;br /&gt;
&lt;strong&gt;Protocol Type:&lt;/strong&gt; Any&lt;br /&gt;
&lt;strong&gt;Local Port:&lt;/strong&gt; Any&lt;br /&gt;
&lt;strong&gt;Remote Port:&lt;/strong&gt; All Ports&lt;br /&gt;
&lt;strong&gt;Scope (Local):&lt;/strong&gt; Any IP Address&lt;br /&gt;
&lt;strong&gt;Scope (Remote):&lt;/strong&gt; Any IP Address&lt;br /&gt;
&lt;strong&gt;Action:&lt;/strong&gt; Block&lt;br /&gt;
&lt;strong&gt;Profile:&lt;/strong&gt; All&lt;br /&gt;
&lt;strong&gt;Name:&lt;/strong&gt; GPO-Block-Conhost-All&lt;/p&gt;

&lt;p&gt;We’ll repeat this rule, but for the syswow64 path. Implement this rule with the following details:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rule Type:&lt;/strong&gt; Custom&lt;br /&gt;
&lt;strong&gt;Programs:&lt;/strong&gt; %SystemRoot%\Syswow64\Conhost.exe&lt;br /&gt;
&lt;strong&gt;Protocol Type:&lt;/strong&gt; Any&lt;br /&gt;
&lt;strong&gt;Local Port:&lt;/strong&gt; Any&lt;br /&gt;
&lt;strong&gt;Remote Port:&lt;/strong&gt; All Ports&lt;br /&gt;
&lt;strong&gt;Scope (Local):&lt;/strong&gt; Any IP Address&lt;br /&gt;
&lt;strong&gt;Scope (Remote):&lt;/strong&gt; Any IP Address&lt;br /&gt;
&lt;strong&gt;Action:&lt;/strong&gt; Block&lt;br /&gt;
&lt;strong&gt;Profile:&lt;/strong&gt; All&lt;br /&gt;
&lt;strong&gt;Name:&lt;/strong&gt; GPO-Block-Conhost-All&lt;/p&gt;

&lt;h5 id=&quot;blocking-mshtaexe&quot;&gt;Blocking Mshta.exe&lt;/h5&gt;

&lt;p&gt;Mshta.exe is commonly abused by attackers to proxy execution of malicious .hta files and Javascript or VBScript. This is an example rule which prevents mshta.exe from communicating with any network resources.&lt;/p&gt;

&lt;p&gt;Implement this rule with the following details:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rule Type:&lt;/strong&gt; Custom&lt;br /&gt;
&lt;strong&gt;Programs:&lt;/strong&gt; %SystemRoot%\System32\mshta.exe&lt;br /&gt;
&lt;strong&gt;Protocol Type:&lt;/strong&gt; Any&lt;br /&gt;
&lt;strong&gt;Local Port:&lt;/strong&gt; Any&lt;br /&gt;
&lt;strong&gt;Remote Port:&lt;/strong&gt; All Ports&lt;br /&gt;
&lt;strong&gt;Scope (Local):&lt;/strong&gt; Any IP Address&lt;br /&gt;
&lt;strong&gt;Scope (Remote):&lt;/strong&gt; Any IP Address&lt;br /&gt;
&lt;strong&gt;Action:&lt;/strong&gt; Block&lt;br /&gt;
&lt;strong&gt;Profile:&lt;/strong&gt; All&lt;br /&gt;
&lt;strong&gt;Name:&lt;/strong&gt; GPO-Block-Mshta-All&lt;/p&gt;

&lt;p&gt;We’ll repeat this rule, but for the syswow64 path. Implement this rule with the following details:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rule Type:&lt;/strong&gt; Custom&lt;br /&gt;
&lt;strong&gt;Programs:&lt;/strong&gt; %SystemRoot%\Syswow64\mshta.exe&lt;br /&gt;
&lt;strong&gt;Protocol Type:&lt;/strong&gt; Any&lt;br /&gt;
&lt;strong&gt;Local Port:&lt;/strong&gt; Any&lt;br /&gt;
&lt;strong&gt;Remote Port:&lt;/strong&gt; All Ports&lt;br /&gt;
&lt;strong&gt;Scope (Local):&lt;/strong&gt; Any IP Address&lt;br /&gt;
&lt;strong&gt;Scope (Remote):&lt;/strong&gt; Any IP Address&lt;br /&gt;
&lt;strong&gt;Action:&lt;/strong&gt; Block&lt;br /&gt;
&lt;strong&gt;Profile:&lt;/strong&gt; All&lt;br /&gt;
&lt;strong&gt;Name:&lt;/strong&gt; GPO-Block-Mshta-All&lt;/p&gt;

&lt;h5 id=&quot;blocking-cscriptexe&quot;&gt;Blocking Cscript.exe&lt;/h5&gt;

&lt;p&gt;Cscript.exe is commonly abused by attackers to execute malicious scripts. This is an example rule which prevents Cscript.exe from communicating with any network resources.&lt;/p&gt;

&lt;p&gt;Implement this rule with the following details:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rule Type:&lt;/strong&gt; Custom&lt;br /&gt;
&lt;strong&gt;Programs:&lt;/strong&gt; %SystemRoot%\System32\Cscript.exe&lt;br /&gt;
&lt;strong&gt;Protocol Type:&lt;/strong&gt; Any&lt;br /&gt;
&lt;strong&gt;Local Port:&lt;/strong&gt; Any&lt;br /&gt;
&lt;strong&gt;Remote Port:&lt;/strong&gt; All Ports&lt;br /&gt;
&lt;strong&gt;Scope (Local):&lt;/strong&gt; Any IP Address&lt;br /&gt;
&lt;strong&gt;Scope (Remote):&lt;/strong&gt; Any IP Address&lt;br /&gt;
&lt;strong&gt;Action:&lt;/strong&gt; Block&lt;br /&gt;
&lt;strong&gt;Profile:&lt;/strong&gt; All&lt;br /&gt;
&lt;strong&gt;Name:&lt;/strong&gt; GPO-Block-Cscript-All&lt;/p&gt;

&lt;p&gt;We’ll repeat this rule, but for the syswow64 path. Implement this rule with the following details:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rule Type:&lt;/strong&gt; Custom&lt;br /&gt;
&lt;strong&gt;Programs:&lt;/strong&gt; %SystemRoot%\Syswow64\Cscript.exe&lt;br /&gt;
&lt;strong&gt;Protocol Type:&lt;/strong&gt; Any&lt;br /&gt;
&lt;strong&gt;Local Port:&lt;/strong&gt; Any&lt;br /&gt;
&lt;strong&gt;Remote Port:&lt;/strong&gt; All Ports&lt;br /&gt;
&lt;strong&gt;Scope (Local):&lt;/strong&gt; Any IP Address&lt;br /&gt;
&lt;strong&gt;Scope (Remote):&lt;/strong&gt; Any IP Address&lt;br /&gt;
&lt;strong&gt;Action:&lt;/strong&gt; Block&lt;br /&gt;
&lt;strong&gt;Profile:&lt;/strong&gt; All&lt;br /&gt;
&lt;strong&gt;Name:&lt;/strong&gt; GPO-Block-Cscript-All&lt;/p&gt;

&lt;h5 id=&quot;blocking-wscriptexe&quot;&gt;Blocking Wscript.exe&lt;/h5&gt;

&lt;p&gt;Wscript.exe is commonly abused by attackers to execute malicious scripts. This is an example rule which prevents Wscript.exe from communicating with any network resources.&lt;/p&gt;

&lt;p&gt;Implement this rule with the following details:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rule Type:&lt;/strong&gt; Custom&lt;br /&gt;
&lt;strong&gt;Programs:&lt;/strong&gt; %SystemRoot%\System32\Wscript.exe&lt;br /&gt;
&lt;strong&gt;Protocol Type:&lt;/strong&gt; Any&lt;br /&gt;
&lt;strong&gt;Local Port:&lt;/strong&gt; Any&lt;br /&gt;
&lt;strong&gt;Remote Port:&lt;/strong&gt; All Ports&lt;br /&gt;
&lt;strong&gt;Scope (Local):&lt;/strong&gt; Any IP Address&lt;br /&gt;
&lt;strong&gt;Scope (Remote):&lt;/strong&gt; Any IP Address&lt;br /&gt;
&lt;strong&gt;Action:&lt;/strong&gt; Block&lt;br /&gt;
&lt;strong&gt;Profile:&lt;/strong&gt; All&lt;br /&gt;
&lt;strong&gt;Name:&lt;/strong&gt; GPO-Block-Wscript-All&lt;/p&gt;

&lt;p&gt;We’ll repeat this rule, but for the syswow64 path. Implement this rule with the following details:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rule Type:&lt;/strong&gt; Custom&lt;br /&gt;
&lt;strong&gt;Programs:&lt;/strong&gt; %SystemRoot%\Syswow64\Wscript.exe&lt;br /&gt;
&lt;strong&gt;Protocol Type:&lt;/strong&gt; Any&lt;br /&gt;
&lt;strong&gt;Local Port:&lt;/strong&gt; Any&lt;br /&gt;
&lt;strong&gt;Remote Port:&lt;/strong&gt; All Ports&lt;br /&gt;
&lt;strong&gt;Scope (Local):&lt;/strong&gt; Any IP Address&lt;br /&gt;
&lt;strong&gt;Scope (Remote):&lt;/strong&gt; Any IP Address&lt;br /&gt;
&lt;strong&gt;Action:&lt;/strong&gt; Block&lt;br /&gt;
&lt;strong&gt;Profile:&lt;/strong&gt; All&lt;br /&gt;
&lt;strong&gt;Name:&lt;/strong&gt; GPO-Block-Wscript-All&lt;/p&gt;

&lt;h5 id=&quot;blocking-runscripthelperexe&quot;&gt;Blocking RunScriptHelper.exe&lt;/h5&gt;

&lt;p&gt;RunScriptHelper.exe is commonly abused by attackers to execute malicious scripts. This is an example rule which prevents RunScriptHelper.exe from communicating with any network resources.&lt;/p&gt;

&lt;p&gt;Implement this rule with the following details:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rule Type:&lt;/strong&gt; Custom&lt;br /&gt;
&lt;strong&gt;Programs:&lt;/strong&gt; %SystemRoot%\System32\RunScriptHelper.exe&lt;br /&gt;
&lt;strong&gt;Protocol Type:&lt;/strong&gt; Any&lt;br /&gt;
&lt;strong&gt;Local Port:&lt;/strong&gt; Any&lt;br /&gt;
&lt;strong&gt;Remote Port:&lt;/strong&gt; All Ports&lt;br /&gt;
&lt;strong&gt;Scope (Local):&lt;/strong&gt; Any IP Address&lt;br /&gt;
&lt;strong&gt;Scope (Remote):&lt;/strong&gt; Any IP Address&lt;br /&gt;
&lt;strong&gt;Action:&lt;/strong&gt; Block&lt;br /&gt;
&lt;strong&gt;Profile:&lt;/strong&gt; All&lt;br /&gt;
&lt;strong&gt;Name:&lt;/strong&gt; GPO-Block-RunScriptHelper-All&lt;/p&gt;

&lt;p&gt;We’ll repeat this rule, but for the syswow64 path. Implement this rule with the following details:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rule Type:&lt;/strong&gt; Custom&lt;br /&gt;
&lt;strong&gt;Programs:&lt;/strong&gt; %SystemRoot%\Syswow64\RunScriptHelper.exe&lt;br /&gt;
&lt;strong&gt;Protocol Type:&lt;/strong&gt; Any&lt;br /&gt;
&lt;strong&gt;Local Port:&lt;/strong&gt; Any&lt;br /&gt;
&lt;strong&gt;Remote Port:&lt;/strong&gt; All Ports&lt;br /&gt;
&lt;strong&gt;Scope (Local):&lt;/strong&gt; Any IP Address&lt;br /&gt;
&lt;strong&gt;Scope (Remote):&lt;/strong&gt; Any IP Address&lt;br /&gt;
&lt;strong&gt;Action:&lt;/strong&gt; Block&lt;br /&gt;
&lt;strong&gt;Profile:&lt;/strong&gt; All&lt;br /&gt;
&lt;strong&gt;Name:&lt;/strong&gt; GPO-Block-RunScriptHelper-All&lt;/p&gt;

&lt;h2 id=&quot;server-configuration&quot;&gt;Server Configuration&lt;/h2&gt;

&lt;p&gt;The steps to require servers are mostly identical to the steps listed above for workstations. That said, there are a few important caveats to be mindful of:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;You will want to create a base Server Firewall Policy GPO with all of the default firewall settings configurations and connection security rules.&lt;/li&gt;
  &lt;li&gt;You will want multiple GPOs for different server types. For example, file servers will want their own policy GPO which allows SMB inbound (preferably with IPSEC authentication, integrity, and encryption).&lt;/li&gt;
  &lt;li&gt;Remember that Active Directory Organizational Units (OUs) are policy boundaries for GPOs. Try to put like-kind servers in the same OU or, failing that, use security filtering and security groups to apply firewall rules.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Again, it is very important to use the request option for security connection rules when testing. This will allow graceful fallback to the underlying protocol, which will prevent service availability issues.&lt;/p&gt;

&lt;h2 id=&quot;protips&quot;&gt;Protips&lt;/h2&gt;

&lt;p&gt;There are a few protips that I’ve learned while deploying this across my home environment:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Test slowly using security filtering. It is easy to accidentally roll out a bad firewall rule or security configuration profile, which could cause loss of access to your device. I recommend having a low frequency for GPO refreshes and a slow roll-out to quickly recover from any bad firewall rules.&lt;/li&gt;
  &lt;li&gt;These rules will override locally set rules. If you have specific applications that require inbound connectivity, you will need to ensure it’s managed via a relevant GPO. Failure to plan out what applications you’re using on your network will break connectivity.&lt;/li&gt;
  &lt;li&gt;If you intend to use Hyper-V on machines running the Windows Firewall, you will need to create a rule allowing inbound DNS (TCP/UDP 53) on all interfaces from all profiles. This is required to process DNS packets from Hyper-V guests to the hypervisor. Failure to do so will break default DNS resolution within Hyper-V guests.&lt;/li&gt;
  &lt;li&gt;You will need to ensure that UDP Port 500 (IKE) and ESP are not filtered by any network firewalls. Using IPSEC to protect protocols will initiate the tunnel via IPSEC (UDP 500) and then tunnel traffic over ESP, which could be filtered by firewalls inside your network. Use wireshark and validate all the connections look sane and reasonable.&lt;/li&gt;
  &lt;li&gt;If you’re looking to use bloodhound or Windows ATA on your network, you’ll need to ensure you have a rule allowing RPC from your trusted hosts. This is required to allow SAMR requests from these tools, which can provide deeper insight into the configuration of your endpoints.&lt;/li&gt;
  &lt;li&gt;I highly recommend installing &lt;a href=&quot;https://www.glasswire.com&quot;&gt;Glasswire&lt;/a&gt;, a freemium application which provides deeper insight into network connectivity on windows hosts. The paid upgrade for glasswire additionally allows for more restrictive firewall policies (e.g. ask for connectivity for new binaries), but these may require enabling local rule processing in your GPO.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;further-reading-and-acknowledgements&quot;&gt;Further Reading and Acknowledgements&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://channel9.msdn.com/Events/Ignite/New-Zealand-2016/M377&quot;&gt;Demystifying the Windows Firewall&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/security/threat-protection/windows-firewall/windows-firewall-with-advanced-security&quot;&gt;Windows Firewall Documentation&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://techcommunity.microsoft.com/t5/Core-Infrastructure-and-Security/bg-p/CoreInfrastructureandSecurityBlog&quot;&gt;Securing RDP with IPSEC&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://secattic.blogspot.com/2013/11/creating-ipsec-tunnel-with-windows.html&quot;&gt;Creating a IPSEC Tunnel with the Windows Firewall&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://gist.github.com/jaredhaight/e88b4323adce06395dace501841d3075&quot;&gt;Windows Hardening Script&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;The kind people who reviewed this post.&lt;/li&gt;
&lt;/ul&gt;</content><author><name>cryps1s</name></author><summary type="html">Over the last few weeks, I’ve had conversations with several individuals around mitigating lateral movement in a Windows environment. In all of these cases, I was surprised to learn that these defenders were not using the native Windows Firewall as one of their defense-in-depth layers. This was curious to me as the firewall is both present by default and is one of the easiest ways to limit remote access to many commonly-abused services.</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blog.dane.io/assets/img/posts/firewall-00.jpg" /><media:content medium="image" url="https://blog.dane.io/assets/img/posts/firewall-00.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry></feed>