I love blogging. One of my favorite parts of my job is figuring out details about an operationally useful topic and trying to explain it in a digestible way. I’ve found that blogging about (or teaching) a particular subject really helps solidify my knowledge, at least as I understand it at the time. It also teaches me how much I don’t know, and forces me to confront my past mistakes and misconceptions.
I’ve posted 63 posts over the last three years, totalling 70k+ words of content. Some posts were relatively simplistic, some were update notes for various projects, but I feel that at least some of the posts provided interesting content for other people in the field. I selected my ten favorite posts from the last three years, and wanted to detail what each one was about and why I selected it as something I’m proud of. Warning: this is a “soft” post that includes no new information, just a retrospective on past material, so this is your chance to bail now :)
I’ll start with the oldest first, working my way up to the most recent.
Post date: July 29, 2014
This was the first “real” post that I ever wrote, and the first one to gain any traction. It’s by far my most linked post of all time, despite many of the details actually being incorrect (see the “Pass-the-Hash Is Dead: Long Live LocalAccountTokenFilterPolicy” section below.) This was the start to my current blogging approach: spend time attempting to dive into a technical topic and doing my best to explain it to the rest of my team in a digestible way. Even though several aspects were flawed, I’m happy I took the plunge.
Post date: March 4, 2015
Domain trusts are one of my favorite topics. It perplexed me as to why there wasn’t a lot of information about domain trusts from an offensive perspective, with most public information on them either coming from MSDN or sysadmin-type resources. My best guess is that while various red teams had been abusing them since their existence, it was often time consuming to map everything out with dsquery/nltest/etc.
This post covered the start of my love affair with trusts and highlighted how to enumerate and abuse trusts efficiently with PowerShell/PowerView. While various aspects of the detailed PowerView syntax are now out of date due to PowerView’s continued evolution, the general enumeration and abuse approach detailed is still valid. Two additional domain trust-related functions have been added since the post was published, Get-DomainForeignUser and Get-DomainForeignGroupMember, which enumerate users in groups outside of their principal domain and groups with users outside of the group’s principal domain, respectively..
Post date: May 31, 2015
As I became more familiar with Matt Graeber‘s PSReflect toolkit, I started to look for additional interesting API calls to implement into PowerView. While messing around with some “living-off-the-land” tradecraft, I came across qwinsta.exe. Qwinsta “displays information about sessions on a Remote Desktop Session Host (RD Session Host) server” given admin privileges on a remote host. I wanted to repurpose this functionality in PowerShell and used my ghetto analysis of strings to pull out the API calls necessary. After reading up on similar “Remote Desktop Services API Functions,” I ran across WTSQuerySessionInformation, which allowed me to pull in even more context than qwinsta.exe. While this obviously isn’t some revolutionary information, it planted the bug in my brain of pushing to explain the thought process behind solving a problem, rather than just presenting a solution.
Post date: June 14, 2016
Years ago, someone described to me how they were able to map local administrator memberships across a domain while only sending traffic to a domain controller. At the time my brain couldn’t comprehend how this could be done, as I was only aware of SAMR type approaches (à la Get-NetLocalGroupMember) to enumerate this type of information. It took a few more years of experience and a tough engagement for all the pieces to fall into place, with the key being linking GPO restricted groups/group policy preferences settings to OUs, sites, and domain objects that contained systems to apply the settings to. This remains one of my favorite “holy shit” moments, even if it seems relatively simple now.
Post date: July 11, 2016
We encounter a lot of KeePass usage in corporate environments. That drove my colleague, Lee Christensen, and me to research how we could operationally “attack” these instances we came across. Our first post, “A Case Study in Attacking KeePass,” generated a reasonable amount of feedback, including sentiments along the lines of “all of this basically relies on getting the password from a keylogger.” Part 2 covered a new toolset Lee and I developed, KeeThief, which allows for the extraction of all key material from an unlocked database. For locked databases, we explored KeePass’ trigger system, the abuse of which allows for the automated export of database contents without malware. I’m extremely proud of the toolset and work, our explanation of the thought process behind solving the problems we encountered, and the chance to quiet the haters with good work instead of vitriol.
Post date: August 15, 2016
In early-mid 2016, I was busy developing the “Advanced PowerShell for Offensive Operations” BlackHat class with Matt Graeber. I was exploring Active Directory DACLs, and dove into property sets that contained ‘NT AUTHORITY\SELF’ as an IdentityReference, meaning what properties of itself an AD object could modify. It dawned on me that this method could allow for a one-to-many broadcast command and control (C2) mechanism, one that could even get around some firewall boundaries. I felt this was one of the few ideas I had that seemed original, and apparently the topic was interesting enough to inspire a BlackHat talk ;)
Post date: October 17, 2016
Some of the smartest people I know are the first to say “I don’t know,” and are the first to admit when they’ve made a mistake. I’ve tried to be as transparent as possible with errors I’ve made in the past through editing posts and issuing corrections when I’m wrong. I’m actually really excited when someone points out a flaw in material I’ve produced or finds interesting bugs in code I’ve written- it means that I get to better understand the topic or take responsibility for messing up. This post highlighted several serious flaws in the Empire project that accumulated over a year and a half, and showed what we tried to do to correct them. So going forward, if anyone finds flaws in something I published, please let me know!
Post date: January 17, 2017
I remember learning about Kerberos in college and thinking “why are we learning about this, I can’t imagine how this will ever be applicable to my job.” Every year that goes by I regret those thoughts more and more, as I’ve realized how interesting complex systems like Kerberos can be (especially when that knowledge leads to abuse methods ;) While Lee and myself were diving into some more complex parts of Kerberos like constrained delegation, we noticed that one attack that was detailed for years (cracking AS-REPs) didn’t have an effective associated toolkit for abuse. I dove into the Kerberos protocol more deeply and surfaced with with a PowerShell project that built the needed Kerberos packets by hand, as well as implemented modifications to current cracking projects to effectively crack the result. While I did not (in any way) find this flaw, it was rewarding to understand Kerberos better and produce an operational toolset that anyone could use. When I describe myself as an “Offensive Engineer” instead of a “Security Researcher,” this is the exact type of reason why.
Post date: January 19, 2017
This post covers one of the few other “novel” ideas I felt I came up with. While working on the previous ASREPRoast work, as well as heavily dealing with Active Directory DACLs for the recent BloodHound 1.3 update, I realized that (given modification rights to the specified user) you could flip the “Do not require Kerberos preauthentication” setting on a user, roast the AS-REP, and then reset the preauthentication value. It was a short leap to realizing that you could implement a Kerberoasting attack using the same approach, setting a nonsense SPN to a user you have edit rights over, Kerberoasting the user, resetting the SPN, and cracking the password offline. Fellow BloodHound developers Andy, Rohan, and I had been looking for something like this for a while as an alternative to destructively forcing a user’s password reset, and luckily we now have an additional attack primitive for at least some ACL-based AD attack paths.
Post date: March 16, 2017
I am particularly proud of this post. Several things detailed in my original “Pass-the-Hash is Dead” post always nagged me: why the RID-500 local account was treated as an exception, why domain accounts didn’t have this protection applied, and why the protection didn’t seem applicable to some environments despite the patch. I hate inconsistencies, and as Lee and I dove heavily into this material, we gained a significantly better understanding at what was happening under the hood. This post not only allowed us to deepen our own understanding and clarified some inconsistencies to the community, but it also provided another opportunity for me to own up to my mistakes. It pays to pay attention to operational details, and diving into how your tools work (as well as why edge cases appear) really can bear some interesting fruit.
My goals with this post were to show that it’s alright to be comfortable with your mistakes if you atone for them later, to highlight a few subject areas that I feel are (hopefully) useful to the community at large, and to encourage anyone who’s on the fence about whether to start a blog to just do it! You don’t have to start with anything crazy- my first post was a basic review of the Offensive Security “Cracking the Perimeter” course. The only way to get better at something is to do more of it, whether it’s coding, blogging, or presenting. Putting yourself out there can be nerve-racking at first, but the positive feedback you’ll get from this community more than outweighs the bad.