<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
  version="2.0">
  <channel>
    <title>Once upon a case...</title>
    <atom:link
      href="https://docs.microsoft.com/archive/blogs/pie/feed.xml"
      rel="self"
      type="application/rss+xml" />
    <link>https://docs.microsoft.com/archive/blogs/pie/feed.xml</link>
    <description />
    <lastBuildDate>Mon, 22 Oct 2018 17:55:31 GMT</lastBuildDate>
    <language>en-US</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>Use this free tool to kill lateral movement! And no, this is not about LAPS!</title>
      <link>https://docs.microsoft.com/archive/blogs/pie/use-this-free-tool-to-kill-lateral-movement-and-no-this-is-not-about-laps</link>
      <pubDate>Sun, 01 Apr 2018 00:58:24 GMT</pubDate>
      <dc:creator><![CDATA[Pierre Audonnet [MSFT]]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/pie/?p=1165</guid>
      <description><![CDATA[I, too, can do click-bait title BS! 

Alright, this has been in my draft folder for almost two...]]></description>
      <content:encoded><![CDATA[<span style="color: #808080">I, too, can do click-bait title BS! </span>

Alright, this has been in my draft folder for almost two years. I originally decided to create it after a customer discussion on Windows Firewall. <strong>BECAUSE YES, THIS IS ABOUT THE BUILT-IN WINDOWS FIREWALL!</strong> (oh no! I hope the screaming did not scare IT pros away!) An awesome security person at Microsoft, <a href="https://twitter.com/jepayneMSFT">Jessica Payne</a>, once presented something about the Windows Firewall with Advanced Security (that's the full name of the feature) in a conference. She pointed out that very simple configurations (all with no extra charge) can lead to a dramatic improvement of ones' security posture.

This post is presenting a quick way to kill one of the most used propagation techniques called lateral movement. So nothing new here. This stuff has been around for ever. You're just in denial...
<h3><a href="https://en.wikipedia.org/wiki/Crab#Behavior">Why do crabs walk sideways?</a></h3>
Lateral movement is the way the bad stuff propagates from one machine to another peer. Note that this is past the initial infection. Once one machine gets pwned, the bad stuff will try to connect to all the other machines nearby, using the credentials harvested in the first one (local accounts and domain accounts) or system vulnerabilities (unpatched SMBv1). It is usually possible because of different aggravating factors:
<ol>
 	<li><strong>Poor credential hygiene.</strong> Administrators are using their accounts on the same systems they are using their Outlook, their Chrome or their Tor browser. As a result, if this machine gets compromised, the administrator account gets compromised and it's already game over. I have seen pentests lasting 1 minute because the domain admins prepared the machine for the pentesters and has its credentials cached locally... Well, administrators should use <a href="https://docs.microsoft.com/en-us/windows-server/identity/securing-privileged-access/privileged-access-workstations">dedicated systems</a>, and should never connect to systems from a <a href="https://docs.microsoft.com/en-us/windows-server/identity/securing-privileged-access/securing-privileged-access-reference-material#ADATM_BM">lower tier</a>.</li>
 	<li><strong>Same local administrator password.</strong> This basically means that if one machine is compromised, the attacker gains Single-Sign-On on all the systems using the same local administrator password. That is easily fixable with <a href="https://technet.microsoft.com/en-us/library/security/3062591.aspx">LAPS</a>. If you never heard of LAPS as of today... Hum, you failed at your job. So please do check it out now.</li>
 	<li><strong>Insufficient network restrictions.</strong> Of course you have firewalls at the perimeter. Or even between different network zones (DMZ, super DMZ, ultra secure DMZ, whatever DMZ). But you don't usually have network firewalls between workstations sitting next to each other. Although you probably don't have a lot of applications doing peer-to-peer type communication. <strong>And for this, you have this post!</strong></li>
</ol>
<h3>Defense in depth</h3>
You don't cherry pick 1, 2 or 3. Here is the classic <a href="https://docs.microsoft.com/en-us/windows-server/identity/securing-privileged-access/securing-privileged-access">attack timeline </a>you probably have seen many times:

<a href="https://msdnshared.blob.core.windows.net/media/2018/02/TIMELINE-0.jpg"><img width="620" height="108" class="alignnone wp-image-1175" alt="" src="https://msdnshared.blob.core.windows.net/media/2018/02/TIMELINE-0.jpg" /></a>

Defense in depth is deploying all of them. You want to make the work for the bad stuff complicated, long and noisy. You want to become unattractive for commodity malware. You want to tend toward something like this:

<a href="https://msdnshared.blob.core.windows.net/media/2018/02/TIMELINE-1.jpg"><img width="619" height="105" class="alignnone wp-image-1185" alt="" src="https://msdnshared.blob.core.windows.net/media/2018/02/TIMELINE-1.jpg" /></a>

There is still some red, but making the lateral movement a tough journey for the bad guys will also buy you some time. We do not discuss the monitoring capabilities here (ATA, Windows event logs...). But we look at how we can make that yellow bar as long as we can... for... $0 (FYI $0 = ¥0  = 0€).
<h3>"It's not 100% bullet proof, so I don't want to do it"</h3>
This post suggests blocking certain ports and also introduces some exceptions (see later the section "oops, my admins can't work anymore"). So you might be tempted to give up. Thinking that something bad can still happen anyway. What if you were the chief of Police of your district. Would you say to your agents: "Listen up folks, no Kevlar vest anymore. Since you can get shot in the face, this is deemed useless." I am pretty sure some field agents might shyly raise their hands and state "what if they don't shoot in the face...". After all not everyone got CoD accuracy IRL (sorry, I had to put some gamer stuff here). You have to look at the ROI of your defense mechanisms. And here, since this is a built-in feature, beside the time required to read this post, test it on your lab and wrap your head around it, there is no other cost or investment. Also, we will block SMB in this article. SMB is just one way... We could also add RPC, or even all peer-to-peer (well that one probably not... legit applications are using P2P type of connections for our good, like Skype or some business apps). But eh, blocking SMB is a good start, and it'll show you one methodology.
<h3>"I once enabled the firewall and I almost got fired"</h3>
I hear that sometimes. Or the even better "I prefer to pay for an expensive third-party firewall because there is this great reporting feature that the built-in firewall doesn't have, well I never use it but the sales person was damn convincing (aka I got lots of goodies)". The firewall has changed. It has, really. And a long time ago. It changed back in Windows Vista. So the experience you might have had with the Windows Server 2003/Windows XP days is not relevant. The "new" firewall is not even close to working the same way. So it is time to reconsider... What is explained here requires to have the firewall enabled though. Jessica's presentation back in the day outlines possible scenarios when it comes to the built-in Windows firewall service status:
<ol>
 	<li>The firewall service is disabled.</li>
 	<li>The firewall service is enabled but all profiles are off.</li>
 	<li>The firewall service is enabled but all profiles are set to allow inbound traffic by default.</li>
 	<li>The firewall service is enabled, the default rules is Allow traffic only if a rule allows it, but then there is a rule which allows all traffic from any to any...</li>
 	<li>The firewall service is enabled and configured... 🤔</li>
</ol>
Number 1 is really bad. It actually can even break stuff.  But that's out of topic.
Number 2 is not protecting you at all... At least you're avoiding some glitches when you try to configure WinRM or install Operation Manager agents (damned! I said it would be another topic!).
Number 3 seems also useless... But it is not! Having the profile enabled means that you can start using the firewall logs feature! See the section "Show me the logs".
Number 4 is a poor attempt to pass security assessments. Well done, you are hiding stuff under the big carpet...
Number 5 just rarely happens... Although the default configuration of the firewall is just fine for 100% of the cases as long as you install well developed applications (and quite frankly, since we are also talking money, why would you buy poorly developed apps anyways right?). Application installation programs will create their firewall rules. Because by default all outbound traffic is allowed, usually only inbound rules need to be created. And if your system is a Windows server, when you install and configure a Windows role (like a DNS server, a ADDS domain controllers, ADFS, etc...) it enables its respective rules by default (I've actually seen many customers who thought the firewall was disabled because they never had issues with it and were very surprised when I showed them that it was in fact enabled).
<h3>Profiles... From good to great</h3>
The Windows Firewall has profiles which are automatically detected and enabled depending on some of the network conditions of the system. Like for example, if the machine can talk to a domain controller, we have the "Domain Profile" enabled. So for all the rules you created you are asked to pick the profiles for which the rules will apply. In my example I will pick all profiles all the time. It is not ideal, but it is better than nothing at all!
<h3>STEP 0 - Enable the firewall - My walls are on fire!</h3>
<span style="color: #ff0000">ACHTUNG!</span> You can really hurt yourself if you enable the firewall the wrong way... I have seen customers doing tests on a single server and breaking the RDP connection they were using to actually connect to it in the first place 😵 Test in a lab, and always scope the GPO to a subset of test machines first. If you fail just unlink the GPO and wait...

We will assume in this post that the firewall is not configured properly on your workstation and create rules to enforce our restrictions anyway. In a perfect world, your firewalls' rules should be well documented and enforced already with group policies.

We create a GPO that we do not link yet. You can disable the User section of the GPO as we will not use it.

<a href="https://msdnshared.blob.core.windows.net/media/2018/04/FW-1.jpg"><img src="https://msdnshared.blob.core.windows.net/media/2018/04/FW-1.jpg" alt="" width="534" height="409" class="alignnone wp-image-1205" /></a>

Let's enable the firewall for all profiles...

<a href="https://msdnshared.blob.core.windows.net/media/2018/04/FW-2.jpg"><img src="https://msdnshared.blob.core.windows.net/media/2018/04/FW-2.jpg" alt="" width="663" height="411" class="alignnone wp-image-1215" /></a>

Scared of breaking something<strong> because it was off before</strong>? Well in that case, you can do this:

<a href="https://msdnshared.blob.core.windows.net/media/2018/04/FW0.jpg"><img src="https://msdnshared.blob.core.windows.net/media/2018/04/FW0.jpg" alt="" width="285" height="268" class="alignnone wp-image-1195" /></a>

Then you wonder... Wait what is the point of doing this? If I open everything for inbound, it's like it was off. Not quite! If you create a block rule, it will override the default Allow rule you just selected. Ideally you should pick the Block.
<h3>STEP 1 - Block incoming traffic - Sorry, no sneakers allowed.</h3>
Now we create a new inbound rule as follows:

<a href="https://msdnshared.blob.core.windows.net/media/2018/04/FWRULE1.jpg"><img src="https://msdnshared.blob.core.windows.net/media/2018/04/FWRULE1.jpg" alt="" width="633" height="515" class="alignnone wp-image-1225" /></a>

<a href="https://msdnshared.blob.core.windows.net/media/2018/04/FWRULE2.jpg"><img src="https://msdnshared.blob.core.windows.net/media/2018/04/FWRULE2.jpg" alt="" width="634" height="515" class="alignnone wp-image-1235" /></a>

<a href="https://msdnshared.blob.core.windows.net/media/2018/04/FWRULE3.jpg"><img src="https://msdnshared.blob.core.windows.net/media/2018/04/FWRULE3.jpg" alt="" width="635" height="517" class="alignnone wp-image-1245" /></a>

<a href="https://msdnshared.blob.core.windows.net/media/2018/04/FWRULE4.jpg"><img src="https://msdnshared.blob.core.windows.net/media/2018/04/FWRULE4.jpg" alt="" width="635" height="516" class="alignnone wp-image-1255" /></a>

<a href="https://msdnshared.blob.core.windows.net/media/2018/04/FWRULE5.jpg"><img src="https://msdnshared.blob.core.windows.net/media/2018/04/FWRULE5.jpg" alt="" width="637" height="517" class="alignnone wp-image-1265" /></a>

If we apply this to a machine, even if the local firewall has the rules to allow both TCP 139 and TCP 445, the connection will fail because the one we created will take precedence.
<h3>STEP 2 - Allow exceptions - O<span>ops, my admins can't work anymore</span>.</h3>
First thing to do is to create an inbound rule that will allow the traffic only if authenticated. If we want to filter who is accessing SMB, we first need to authenticate them. So we create a new inbound rule as follows:

<a href="https://msdnshared.blob.core.windows.net/media/2018/04/FWRULE1.jpg"><img src="https://msdnshared.blob.core.windows.net/media/2018/04/FWRULE1.jpg" alt="" width="633" height="515" class="alignnone wp-image-1225" /></a>

<a href="https://msdnshared.blob.core.windows.net/media/2018/04/FWRULE2.jpg"><img src="https://msdnshared.blob.core.windows.net/media/2018/04/FWRULE2.jpg" alt="" width="634" height="515" class="alignnone wp-image-1235" /></a>

This time we pick "Allow the connection if it is secure".

<a href="https://msdnshared.blob.core.windows.net/media/2018/04/FWRULEOVER1.jpg"><img src="https://msdnshared.blob.core.windows.net/media/2018/04/FWRULEOVER1.jpg" alt="" width="636" height="518" class="alignnone wp-image-1275" /></a>

Click on "Customize". We are going to pick two options here:
<ul>
 	<li><strong>Allow the connection to use null encapsulation.</strong> This is great because we don't really care about encryption in our case. We just want to authenticate the traffic. Besides, by not doing encryption, the traffic will still be in the clear, hence if you are doing some troubleshooting (or smart QoS, smart in a sense that it can get over the fact that the SMB traffic is transported over an ESP layer...) we can still look at network traces.</li>
 	<li><strong>Override block rules. </strong>If we don't pick that option, our rule will not apply because of the first block rule we just created.</li>
</ul>
<a href="https://msdnshared.blob.core.windows.net/media/2018/04/FWRULEOVER2.jpg"><img src="https://msdnshared.blob.core.windows.net/media/2018/04/FWRULEOVER2.jpg" alt="" width="433" height="539" class="alignnone wp-image-1285" /></a>

Then we will select groups to create exceptions. One for the user accounts:

<a href="https://msdnshared.blob.core.windows.net/media/2018/04/FWRULEOVER3.jpg"><img src="https://msdnshared.blob.core.windows.net/media/2018/04/FWRULEOVER3.jpg" alt="" width="634" height="516" class="alignnone wp-image-1295" /></a>

One for the computer accounts:

<a href="https://msdnshared.blob.core.windows.net/media/2018/04/FWRULEOVER4.jpg"><img src="https://msdnshared.blob.core.windows.net/media/2018/04/FWRULEOVER4.jpg" alt="" width="636" height="517" class="alignnone wp-image-1305" /></a>

<a href="https://msdnshared.blob.core.windows.net/media/2018/04/FWRULE4.jpg"><img src="https://msdnshared.blob.core.windows.net/media/2018/04/FWRULE4.jpg" alt="" width="635" height="516" class="alignnone wp-image-1255" /></a>

<a href="https://msdnshared.blob.core.windows.net/media/2018/04/FWRULEOVER5.jpg"><img src="https://msdnshared.blob.core.windows.net/media/2018/04/FWRULEOVER5.jpg" alt="" width="636" height="518" class="alignnone wp-image-1315" /></a>
<h3>STEP 3 - Configure the exceptions - I'm joining somebody inside.</h3>
This is not over here... We need to provide a way for machines and users to authenticate. So far we just set the firewall to reject the connections unless authenticated and users and computers member of specific groups. Now we need to tell all participants how to authenticate.

Still on the same GPO, create a new security association rule as follows:

<a href="https://msdnshared.blob.core.windows.net/media/2018/04/FWSECRULE1.jpg"><img src="https://msdnshared.blob.core.windows.net/media/2018/04/FWSECRULE1.jpg" alt="" width="637" height="519" class="alignnone wp-image-1325" /></a>

Yes we went custom... In my opinion, the wizard is hiding a complexity that does not really exist...

<a href="https://msdnshared.blob.core.windows.net/media/2018/04/FWSECRULE2.jpg"><img src="https://msdnshared.blob.core.windows.net/media/2018/04/FWSECRULE2.jpg" alt="" width="639" height="520" class="alignnone wp-image-1335" /></a>

In the next one we have several options, as long as we require authentication for inbound.

<a href="https://msdnshared.blob.core.windows.net/media/2018/04/FWSECRULE3.jpg"><img src="https://msdnshared.blob.core.windows.net/media/2018/04/FWSECRULE3.jpg" alt="" width="639" height="522" class="alignnone wp-image-1345" /></a>

<a href="https://msdnshared.blob.core.windows.net/media/2018/04/FWSECRULE4.jpg"><img src="https://msdnshared.blob.core.windows.net/media/2018/04/FWSECRULE4.jpg" alt="" width="638" height="521" class="alignnone wp-image-1355" /></a>

There is room for an accident here! Watch out! We have selected "Require authentication for inbound...". If you do not select specific protocol and/or ports here, the rule will apply for EVERYTHING! And very likely prevent you from establishing any type of remote connection to that system...

<a href="https://msdnshared.blob.core.windows.net/media/2018/04/FWSECRULE5.jpg"><img src="https://msdnshared.blob.core.windows.net/media/2018/04/FWSECRULE5.jpg" alt="" width="639" height="521" class="alignnone wp-image-1365" /></a>

<a href="https://msdnshared.blob.core.windows.net/media/2018/04/FWSECRULE6.jpg"><img src="https://msdnshared.blob.core.windows.net/media/2018/04/FWSECRULE6.jpg" alt="" width="639" height="517" class="alignnone wp-image-1375" /></a>

<a href="https://msdnshared.blob.core.windows.net/media/2018/04/FWSECRULE7.jpg"><img src="https://msdnshared.blob.core.windows.net/media/2018/04/FWSECRULE7.jpg" alt="" width="640" height="520" class="alignnone wp-image-1385" /></a>

Now we need to create the reciprocal rules on the machine we want to grant access (the help-desk users and machines, the SCCM servers and service accounts, the administrative systems, etc...). Again we create a policy. We disable the user's section and will configure the firewall. But this time, we just configure a security association. You can also force the firewall to be on and so on and so forth, you got the drift.

<a href="https://msdnshared.blob.core.windows.net/media/2018/04/FWSECRULE1.jpg"><img src="https://msdnshared.blob.core.windows.net/media/2018/04/FWSECRULE1.jpg" alt="" width="637" height="519" class="alignnone wp-image-1325" /></a>

For the next one, we can also restrict the rule to certain subnets if all your workstations are in a specific one, or a few.

<a href="https://msdnshared.blob.core.windows.net/media/2018/04/FWSECRULE2.jpg"><img src="https://msdnshared.blob.core.windows.net/media/2018/04/FWSECRULE2.jpg" alt="" width="639" height="520" class="alignnone wp-image-1335" /></a>

<a href="https://msdnshared.blob.core.windows.net/media/2018/04/FWSECRULE8.jpg"><img src="https://msdnshared.blob.core.windows.net/media/2018/04/FWSECRULE8.jpg" alt="" width="639" height="519" class="alignnone wp-image-1395" /></a>

<a href="https://msdnshared.blob.core.windows.net/media/2018/04/FWSECRULE4.jpg"><img src="https://msdnshared.blob.core.windows.net/media/2018/04/FWSECRULE4.jpg" alt="" width="638" height="521" class="alignnone wp-image-1355" /></a>

This time we pick the Endpoint 2. And again, we accommodate the NetBIOS fallback, but we can also just specify 445. Enough with legacy stuff.

<a href="https://msdnshared.blob.core.windows.net/media/2018/04/FWSECRULE9.jpg"><img src="https://msdnshared.blob.core.windows.net/media/2018/04/FWSECRULE9.jpg" alt="" width="636" height="519" class="alignnone wp-image-1405" /></a>

&nbsp;

<a href="https://msdnshared.blob.core.windows.net/media/2018/04/FWSECRULE10.jpg"></a><a href="https://msdnshared.blob.core.windows.net/media/2018/04/FWSECRULE6.jpg"><img src="https://msdnshared.blob.core.windows.net/media/2018/04/FWSECRULE6.jpg" alt="" width="639" height="517" class="alignnone wp-image-1375" /></a>

<a href="https://msdnshared.blob.core.windows.net/media/2018/04/FWSECRULE6.jpg"><img src="https://msdnshared.blob.core.windows.net/media/2018/04/FWSECRULE6.jpg" alt="" width="639" height="517" class="alignnone wp-image-1375" /></a>

<a href="https://msdnshared.blob.core.windows.net/media/2018/04/FWSECRULE10.jpg"><img src="https://msdnshared.blob.core.windows.net/media/2018/04/FWSECRULE10.jpg" alt="" width="638" height="520" class="alignnone wp-image-1415" /></a>

That's it. Then you apply the GPO to the right OUs, with the right security filter (and why not apply a WMI filter looking for OS version to limit the first GPO only on workstations).
<h3>STEP 4 - Now what? - Show me the logs!</h3>
Let's verify that everything works... Let's connect with SMB from one machine which is allowed to connect and from one who is not. On the machine applying the first GPO, we should see this in the firewall console (wf.msc):

<a href="https://msdnshared.blob.core.windows.net/media/2018/04/FWGPO3JPG.jpg"><img src="https://msdnshared.blob.core.windows.net/media/2018/04/FWGPO3JPG.jpg" alt="" width="782" height="112" class="alignnone wp-image-1425" /></a>

<a href="https://msdnshared.blob.core.windows.net/media/2018/04/FWGPO4JPG.jpg"><img src="https://msdnshared.blob.core.windows.net/media/2018/04/FWGPO4JPG.jpg" alt="" width="734" height="408" class="alignnone wp-image-1435" /></a>

And on the machine which is allowed to connect:

<a href="https://msdnshared.blob.core.windows.net/media/2018/04/FWGPO1.jpg"><img src="https://msdnshared.blob.core.windows.net/media/2018/04/FWGPO1.jpg" alt="" width="778" height="146" class="alignnone wp-image-1445" /></a>

<a href="https://msdnshared.blob.core.windows.net/media/2018/04/FWGPO2JPG.jpg"><img src="https://msdnshared.blob.core.windows.net/media/2018/04/FWGPO2JPG.jpg" alt="" width="767" height="430" class="alignnone wp-image-1455" /></a>

Don't forget to enable some log (useful for troubleshooting... and for more...). Easy, go back to your GPOs and enable it that way:

<a href="https://msdnshared.blob.core.windows.net/media/2018/04/FWGPOLOG.jpg"><img src="https://msdnshared.blob.core.windows.net/media/2018/04/FWGPOLOG.jpg" alt="" width="583" height="489" class="alignnone wp-image-1465" /></a>

Go fancy, enable it on all the profiles for DROP and ALLOW and with the maximum size (32Kb ~ <em>32,768b</em>). It will create a log file of up to 32Kb. When it is full, it will be renamed and saved and another one will be created. When that other one is full, we delete the old one and replace it automatically. So you always have at least 32Kb of logs (and at best 64Kb). This is what the logs look like:
<pre>2017-01-04 21:15:44 ALLOW TCP 10.0.0.80 104.40.69.64 52028 5671 0 - 0 0 0 - - - SEND
2017-01-04 21:16:46 DROP TCP 10.0.0.10 10.0.0.80 61564 445 52 S 2716891960 0 8192 - - - RECEIVE
2017-01-04 21:16:46 ALLOW UDP 10.0.0.80 10.0.0.10 60674 53 0 - - - - - - - SEND
2017-01-04 21:16:46 ALLOW TCP 10.0.0.80 104.40.69.64 52030 5671 0 - 0 0 0 - - - SEND
2017-01-04 21:16:49 DROP TCP 10.0.0.10 10.0.0.80 61564 445 52 S 2716891960 0 8192 - - - RECEIVE
2017-01-04 21:16:49 ALLOW ICMP 10.0.0.10 10.0.0.80 - - 0 - - - - 8 0 - RECEIVE
2017-01-04 21:16:49 ALLOW UDP 10.0.0.10 10.0.0.80 137 137 0 - - - - - - - RECEIVE
2017-01-04 21:16:49 DROP TCP 10.0.0.10 10.0.0.80 61567 139 52 S 1261083587 0 8192 - - - RECEIVE

</pre>
The biggest problem with efficient defenses is that you don't necessarily know if it actually blocked a lateral movement or did nothing. At the end of the day, you learn how to use the firewall, so it's not nothing! But you can do geekier than that. You can parse all the DROP of your workstations' logs and then use PowerBI to see what's up. It would look something like this:

<a href="https://msdnshared.blob.core.windows.net/media/2018/04/FWPBI.jpg"><img src="https://msdnshared.blob.core.windows.net/media/2018/04/FWPBI.jpg" alt="" width="718" height="301" class="alignnone wp-image-1475" /></a>

In this post, we looked at what some of you might call a "dirty way" to stop the lateral movement. Why dirty? Because I believe it is better to configure only the right inbound rules on your workstations to start with instead of doing block/override like we do. But it works. And it is damn cheap!  If you want to see a more elegant way to manage the firewall rules with GPO and the Windows audit (instead of the old school text log file) etc... Please let me know in the comment section.]]></content:encoded>
    </item>
    <item>
      <title>All you need to know about Keytab files</title>
      <link>https://docs.microsoft.com/archive/blogs/pie/all-you-need-to-know-about-keytab-files</link>
      <pubDate>Wed, 03 Jan 2018 02:14:27 GMT</pubDate>
      <dc:creator><![CDATA[Pierre Audonnet [MSFT]]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/pie/?p=1126</guid>
      <description><![CDATA[Whether you are currently using them or planning to issue one, here is (I hope) all you need to know...]]></description>
      <content:encoded><![CDATA[Whether you are currently using them or planning to issue one, here is (I hope) all you need to know about those little binary files.
<h2>It's a Kerberos thing</h2>
If you use or plan to use keytabs, it means that you are planning to add Kerberos support to a system which can't do it otherwise (Kerberos being the native authentication protocol used in Active Directory since the Windows 2000 family, not the only one though). Windows systems which are joined to an Active Directory domain are automatically set up for Kerberos. There is nothing to do to "enable" Kerberos on Windows. Applications running on Unix/Linux or applications running on Windows but within a Java environment (those could but do not really access Windows APIs) which want to be a part of the forest <strong>Single-Sign-On</strong> might need a keytab file. The keytab file contains the identity of an Active Directory account (userPrincipalName) as well as the encryption keys necessary to encrypt/decrypt Kerberos tickets.

<strong>In other words, you need Keytab files to bring SSO to non domain-joined applications.</strong>
<h2>How do I generate a Keytab?</h2>
You will use the utility <strong>KTPASS.EXE</strong>. It is a part of the <a href="https://support.microsoft.com/en-us/help/2693643/remote-server-administration-tools-rsat-for-windows-operating-systems">RSAT</a> and will be present if you enabled the Active Directory Directory Services tools (always use the most recent version of ktpass, see the section: Why should I always use the most recent version of ktpass?).

Let's take an example. You have a "service/application" account in the verenatex.com domain with the following information:
<ul>
 	<li>sAMAccountName: app1</li>
 	<li>userPrincipalName: app1@verenatex.com</li>
 	<li>servicePrincipalName: &lt;not set&gt;</li>
 	<li>"password" (not an actual attribute): Password1</li>
</ul>
Now I run the following command to generate a keytab file for this account:
<pre>ktpass /out app1.keytab /princ http/app1.verenatex.com@verenatex.com /mapuser app1 /crypto AES256-SHA1 /ptype KRB5_NT_PRINCIPAL /pass Password2 /target vdc01.verenatex.com</pre>
<ul>
 	<li>/out specifies the name of the output file, here app1.keytab</li>
 	<li>/princ specifies the userPrincipalName as well as a value which will be added to the servicePrincipalName of the mapped account</li>
 	<li>/mapuser is the account for which the keytab will be generated</li>
 	<li>/crypto is the encrytion type used for the keytab, here AES256-SHA1</li>
 	<li>/ptype is set to KRB5_NT_PRINCIPAL which is in general what you should use unless instructed otherwise by the application documentation</li>
 	<li>/pass is the new password for the mapped account (by default it will perform a password reset operation)</li>
 	<li>/target is used to indicate which domain controller will be queried (it is optional, but can be useful if you have more than one domain in your forest)</li>
</ul>
And here is the output:
<pre>Successfully mapped http/app1.verenatex.com to app1.
Password successfully set!
Key created.
Output keytab to app1.keytab:
Keytab version: 0x502
keysize 90 http/app1.verenatex.com@verenatex.com ptype 1 (KRB5_NT_PRINCIPAL)</pre>
And this is what the account looks like now:
<ul>
 	<li>sAMAccountName: app1</li>
 	<li>userPrincipalName: http/app1.verenatex.com@verenatex.com</li>
 	<li>servicePrincipalName: http/app1.verenatex.com@verenatex.com</li>
 	<li>"password" (not an actual attribute): Password2</li>
</ul>
Note that the userPrincipalName has been updated with the value you provided in the parameter /princ. You can prevent this with the parameter -SetUPN at the end of the command. In that case, the UPN will not be touched and the value specified with /princ will only be added to the servicePrincipalName (SPN).

Also note that if the account already had a SPN, the new value will be added to the list of SPNs (it is a multi-value attribute). Unless you specify the parameter /mapop set. In that case the previous values are overwritten by the new value.

There are several things to consider for the password. You can specify it and set it during the creation of the keytab, or if you already know the password, you can just specify it in the command line. Then it will be used to generate the key but the password will not be reset. Or you can even ask for a random password. Because after all, if the keytab is solely used for an application or a service, we don't really enter the password anywhere, why not a random password?

I will share these examples and their final results with highlighted differences, so you can understand what those commands do and pick the one you need:
<table border="1">
<tbody>
<tr>
<td><strong>Command line</strong></td>
<td><strong>Object Before</strong></td>
<td width="208"><strong>Object After</strong></td>
</tr>
<tr>
<td>ktpass
/out app1.keytab
/princ http/app1.verenatex.com@verenatex.com
/mapuser app1
/crypto AES256-SHA1
/ptype KRB5_NT_PRINCIPAL
/pass Password2
/target vdc01.verenatex.com</td>
<td>sAMAccountName: app1
userPrincipalName: app1@verenatex.com
servicePrincipalName: &lt;not set&gt;
"password": Password1</td>
<td>sAMAccountName: app1
<span style="color: #ff0000">userPrincipalName: http/app1.verenatex.com@verenatex.com</span>
<span style="color: #ff0000"> servicePrincipalName: http/app1.verenatex.com@verenatex.com</span>
<span style="color: #ff0000"> "password": Password2</span></td>
</tr>
<tr>
<td>ktpassktpass
/out app1.keytab
/princ http/app1.verenatex.com@verenatex.com
<span style="color: #ff0000">-SetUPN</span>
/mapuser app1
/crypto AES256-SHA1
/ptype KRB5_NT_PRINCIPAL
/pass Password2
/target vdc01.verenatex.com</td>
<td>sAMAccountName: app1
userPrincipalName: app1@verenatex.com
servicePrincipalName: &lt;not set&gt;
"password": Password1</td>
<td>sAMAccountName: app1
userPrincipalName: app1@verenatex.com
<span style="color: #ff0000">servicePrincipalName: http/app1.verenatex.com@verenatex.com</span>
<span style="color: #ff0000"> "password": Password2</span></td>
</tr>
<tr>
<td>ktpass
/out app1.keytab
/princ http/app1.verenatex.com@verenatex.com
/mapuser app1
/crypto AES256-SHA1
/ptype KRB5_NT_PRINCIPAL
/pass Password2
/target vdc01.verenatex.com</td>
<td>sAMAccountName: app1
userPrincipalName: app1@verenatex.com
servicePrincipalName: <span style="color: #800080">http/test</span>
"password": Password1</td>
<td>sAMAccountName: app1
<span style="color: #ff0000">userPrincipalName: http/app1.verenatex.com@verenatex.com</span>
<span style="color: #ff0000"> servicePrincipalName: <span style="color: #800080">http/test</span>, http/app1.verenatex.com@verenatex.com</span>
<span style="color: #ff0000"> "password": Password2</span></td>
</tr>
<tr>
<td>ktpass
/out app1.keytab
/princ http/app1.verenatex.com@verenatex.com
/mapuser app1
<span style="color: #ff0000">/mapop set</span>
/crypto AES256-SHA1
/ptype KRB5_NT_PRINCIPAL
/pass Password2
/target vdc01.verenatex.com</td>
<td>sAMAccountName: app1
userPrincipalName: app1@verenatex.com
servicePrincipalName: http/test
"password": Password1</td>
<td>sAMAccountName: app1
<span style="color: #ff0000">userPrincipalName: http/app1.verenatex.com@verenatex.com</span>
<span style="color: #ff0000"> servicePrincipalName: http/app1.verenatex.com@verenatex.com</span>
<span style="color: #ff0000"> "password": Password2</span></td>
</tr>
<tr>
<td>ktpass
/out app1.keytab
/princ http/app1.verenatex.com@verenatex.com
/mapuser app1
/crypto AES256-SHA1
/ptype KRB5_NT_PRINCIPAL
/pass Password1
<span style="color: #ff0000">-SetPass</span>
/target vdc01.verenatex.com</td>
<td>sAMAccountName: app1
userPrincipalName: app1@verenatex.com
servicePrincipalName: &lt;not set&gt;
"password": Password1</td>
<td>sAMAccountName: app1
<span style="color: #ff0000">userPrincipalName: <span>http/app1.verenatex.com@verenatex.com</span></span>
<span style="color: #ff0000"> servicePrincipalName: http/app1.verenatex.com@verenatex.com</span>
"password": Password1</td>
</tr>
<tr>
<td>ktpass
/out app1.keytab
/princ http/app1.verenatex.com@verenatex.com
/mapuser app1
/crypto AES256-SHA1
/ptype KRB5_NT_PRINCIPAL
<span style="color: #ff0000">+RdnPass</span>
<span style="color: #ff0000"> +maxPass 45</span>
/target vdc01.verenatex.com</td>
<td>sAMAccountName: app1
userPrincipalName: app1@verenatex.com
servicePrincipalName: &lt;not set&gt;
"password": Password1</td>
<td>sAMAccountName: app1
<span style="color: #ff0000">userPrincipalName: <span>http/app1.verenatex.com@verenatex.com</span></span>
<span style="color: #ff0000"> servicePrincipalName: http/app1.verenatex.com@verenatex.com</span>
<span style="color: #ff0000">"password": mN=q!{/YBz95v1^doS2=QK#|lRFG</span></td>
</tr>
</tbody>
</table>
I know that those parameters -SetUPN or -SetPass look counter intuitive since they do the opposite of what it suggests. But this is because the "-" in the front means the negation of the parameter. The default value for those two are actually +SetUPN and +SetPass. Hope that clears the confusion.

The account in AD doesn't have to be a user account by the way. It could also be a computer account. Although I don't really see why you'd go that way. The main difference that comes to my mind is that the password expiration policy does not apply to computer accounts. But that's not very different from a user account with the password set not to expire.
<h2>It is not encrypted!</h2>
This is what a keytab file looks like if you open it with notepad:

<img width="755" height="217" class="alignnone wp-image-1135" alt="" src="https://msdnshared.blob.core.windows.net/media/2018/01/keytab_1.jpg" />

We can see the principal name specified during the creation and a bit of gibberish. Looks like encrypted stuff BUT IT IS NOT. This is the plain text (well plain bytes) of the Kerberos encryption key. This is what it looks like if you parse the binary file in PowerShell (I used a self-written parser) :

<a href="https://msdnshared.blob.core.windows.net/media/2018/01/keytab_2.jpg"><img width="597" height="201" class="alignnone wp-image-1145" alt="" src="https://msdnshared.blob.core.windows.net/media/2018/01/keytab_2.jpg" /></a>

It's the output of a small code I wrote that parses the content according to the <a href="https://www.gnu.org/software/shishi/manual/html_node/The-Keytab-Binary-File-Format.html">documented structure</a>. There is no decryption involved since it is in the clear. And because the encryption type in this case is rc4-hmac (see: <a href="https://tools.ietf.org/html/rfc4757#section-2">RFC4757 The RC4-HMAC Kerberos Encryption Types Used by Microsoft Windows</a>), the key that you see here in the clear is the actual NTHash of the user (which is way enough to impersonate the user by performing <a href="https://technet.microsoft.com/en-us/dn785092.aspx">pass the hash</a> or even to try some <a href="https://www.bing.com/search?q=Kerberos+roasting">Kerberos roasting</a>). If you've used AES encryption, it would be the AES key used by Windows to encrypt/decrypt Kerberos tickets. <a href="https://msdnshared.blob.core.windows.net/media/2018/01/keytab_1.jpg"></a>

So, it seems pretty obvious that you will have to <strong>deal with Keytab files with the same precautions you use when dealing with passwords</strong>.
<ol>
 	<li>Do not share them over not encrypted emails</li>
 	<li>Do not store them in a file share</li>
 	<li>Once deployed on the application, make sure the file is also protected from other users (chmod, or ACL for Java on Windows) and follow credentials hygiene principals (ie. making sure that only the actual admins of the server can access that server's file system)</li>
</ol>
If you have some data classification project going on in your organization, it is maybe the occasion to also clarify the level of confidentiality required by keytab files in your policy.
<h2>What permissions do I need to generate a keytab?</h2>
First, I'll emphasize on the following: you don't need to be connected locally on a domain controller to generate a Keytab file. I see this so often that I had to add it. To generate a Keytab you might need a few permissions on the directory but the "Allow logon locally" privilege on the domain controllers is not one of them. As a matter of fact the only permission required to generate a keytab file is the NTFS "write" permission on the folder where the file will be written (specified by the /out parameter). And you can do that from your workstation or from an administration server as long as you have the right feature installed (RSAT with ADDS tools to use ktpass). That's it.

Now, depending on the parameter you chose in the ktpass command line, you might need more, but that's your choice, not because it is a requirement.

Here are a few things which <strong>could</strong> take place behind the scenes when you generate a Keytab file:
<ul>
 	<li>The password of of the account for which the keytab file will be generated will be reset with the a provided value. Unless specified otherwise with the parameter -SetPass.</li>
 	<li>If the userPrincipalName of the account in Active Directory is different than the one specified in the command line, then it will be updated. Unless you set the parameter -SetUPN.</li>
 	<li>If the mapped account does not have a servicePrincipalName with the value specified in the /princ parameter, a servicePrincipalName with the value equal to the value of the /princ paramter will be added to the account (added or replaced if the parameter "/modop set" is also specified). If you don't have the permissions, it will display a warning but the keytab will still be generated.</li>
 	<li>If you want the account to be a DES encryption only account, you will need the permission to change the userAccountControl attribute (BUT, you don't want that, YOU DO NOT WANT DES, see the section What Encryption Types should I pick?)</li>
</ul>
I summarize the permissions you need on the object depending on the parameter you specify on the ktpass command:
<table border="1">
<tbody>
<tr>
<td><strong>Parameter</strong></td>
<td><strong>Permissions on the account</strong></td>
</tr>
<tr>
<td>/princ</td>
<td>If the value is already set with the same value: none

Else permission to modify the userPrincipalName

Permission to modify the servicePrincipalName</td>
</tr>
<tr>
<td>/princ -SetUPN</td>
<td>None</td>
</tr>
<tr>
<td>/pass</td>
<td>Permission to reset the password</td>
</tr>
<tr>
<td>/pass -SetPass</td>
<td>None</td>
</tr>
</tbody>
</table>
So if you already know the password of the account, do not wish to modify the userPrincipalName and that the servicePrincipalName is already set as you need, you can generate the keytab file for an account with no permissions at all on Active Directory:
<pre>ktpass /out app1.keytab /princ app1@verenatex.com -SetUPN /mapuser app1 /crypto AES256-SHA1 /ptype KRB5_NT_PRINCIPAL /pass Password1 -SetPass /target vdc01.verenatex.com</pre>
You will receive this message: "WARNING: Unable to set SPN mapping data." that you can safely ignore if the SPN was already set on the account.

So, can I delegate the creation of keytabs? Well, as you can see just above, in certain conditions, you don't even need to delegate anything. If the UPN and SPN are not changing and if the password is known, then you really have nothing to do from a delegation perspective. You just need to use the ktpass tool with the right parameters. What if you want to delegate the creation because the conditions mentioned are not met? It depends. If you already have a team in your organization in charge of managing "service/application" accounts, you can ask them to do it. But very often the team in charge of managing those accounts is the AD team anyways. And if you'd like to extend this to another team, you need to understand that giving the permissions to a non AD savvy person to create/modify/delete servicePrincipalName is a bad idea. Not to mention changing the userPrincipalName. There are security implications to these decisions (account spoofing, incorrect or duplicate SPN...).
You can cut the work in two, and let the team already in charge of "service/application" accounts do the modification of the UPN and SPN (if required), and leave the team asking for the keytab the duty to generate it assuming that they know the password. Then you don't have the challenge of sharing the generated  keytab with the asking team, since they would already have it.
You can also keep the generation of the keytab in the AD team (or again the team within your organization already in charge of "service/application" accounts) then you keep control of everything (including the encryption type, which is important). And you also have a clear trace of what keytabs have been generated (this can be useful, see the next section: When do I need to regenerate the keytab). But there is the issue of sending the keytab back to the asking team...
<h2>When do I need to regenerate the keytab?</h2>
There are only a few events on an account that will invalidate a keytab and require the file to be regenerated.

If you change the principal names you might have to change it. "Might" because it depends on how the client asks for a ticket and what the application is actually doing with the keytab file. But because there are some aspects of it which you do not control (you don't know how the applications or systems parsed the keytab nor how they planned to use it), if you changed the userPrincipalName, you will certainly have to regenerate the keytab.

If you want to change the encryption type, you will also have to regenerate the keytab file with the right /crypto parameter (see the section What Encryption Type should I pick? for more details on that).

If you change the password, it is obvious that the encryption keys (derived from the password) will change. Hence you will have to regenerate the keytab file. What could be a bit more obscure is that you also have to regenerate the keytab even if you reset the password of the account with the same value! Why? Because of the Vno (also called KVno for Key Version Number). Not only do we use the password to generate the encryption keys, we also store the version of the password in the keytab file. So if the password changed 10 times on the account before generating the keytab, and you do not specify -SetPass parameter, the keytab you generate now will be good for the version 11 of the password. The Key version is a part of the Kerberos ticket generated by the domain controllers and sent by the user. So if it is not matching what is on the keytab, even if the value of the password is the same, then the ticket will be discarded. If you want to know what is the current version number of the key, you can query the calculated attribute: msDS-KeyVersionNumber. You can find it on the Attribute Editor of the Users and Computer console:

<a href="https://msdnshared.blob.core.windows.net/media/2018/01/keytab_3.jpg"><img width="503" height="642" class="alignnone wp-image-1146" alt="" src="https://msdnshared.blob.core.windows.net/media/2018/01/keytab_3.jpg" /></a>

Or in PowerShell (note that because it is a calculated attribute, if you were to perform a search the scope has to be "base" and the attribute has to be explicitly asked):

[code language="PowerShell"]Get-ADUser -Identity app1 -Properties &quot;msDS-KeyVersionNumber&quot;[/code]

The output will be:
<pre>DistinguishedName : CN=app1,OU=Accounts,DC=verenatex,DC=com
... 
msDS-KeyVersionNumber : 12
UserPrincipalName : app1@verenatex.com
...</pre>
And this value really represents how many times the password attribute has changed since the account exists . You can also see it that way, by looking at the replication metadata of the account (if you want to play with metadata, have a look <a href="https://blogs.technet.microsoft.com/pie/2014/08/25/metadata-0-metadata-what-is-it-and-why-do-we-care/">here</a>):

[code language="PowerShell"]Get-ADUser -Identity app1 | Get-ADReplicationAttributeMetadata -Properties unicodePwd -Server vdc01.verenatex.com[/code]

The output will be:
<pre>AttributeName : unicodePwd
...
Version : 12
...</pre>
This also explains why, if the account is <a href="https://technet.microsoft.com/en-us/library/cc816878(v=ws.10).aspx">authoritatively restored</a>, keytab files also have to be regenerated. To ensure the restored objects will win all replication conflicts, the attribute version of all the attributes of the objects in the scope of an authoritative restore will by default be incremented by 100.000. Then in my example, if you restore the account app1, the new msDS-KeyVersionNumber value will be 100.012 and the keytab already generated would have an incorrect Vno. Unless! (yes it can get complicated), you want all tickets to be generated with the Vno 1 (like Windows 2000 Server domain controllers used to do). Then there is a way, see the dsHeuristics documentation <a href="https://msdn.microsoft.com/en-us/library/cc223392.aspx">here</a>. My recommendation: ensure that you include a section about keytabs in your Disaster Recovery document. If you recover the object from the AD Recycle Bin, there is nothing to do, this will restore the version as it was before being deleted.

If you want to know what the key version of your keytab is and you did not save the output of the ktpass command, have a look at the next section: I found a keyab, what should I do?
<h2>I found a keytab, what should I do?</h2>
If you "found" a keytab in an open and unexpected location, you will have to assume it is compromised and change the keys it contains. In other words, you'll have to reset the password of the account and regenerate the keytab. But wait, how do I know what account the keytab has been generated for? You can simply use ktpass with the /in parameter:
<pre>ktpass /in test.keytab</pre>
This will be the output telling you what is the principal and the encryption key. It even tells you what the version of the key (vno) was:
<pre>Existing keytab:

Keytab version: 0x502
keysize 61 test@verenatex.com ptype 1 (KRB5_NT_PRINCIPAL) vno 24 etype 0x17 (RC4-HMAC) keylength 16 (0xfdbbac01d5608b5d8ae1adbde5ddb459)

WARNING: No principal name specified.</pre>
You can ignore the warning. Technically a keytab can contain several keys and principals (although the Windows version of ktpass doesn't offer the capability to have multiple principals), if it was the case you can ask ktpass to show only the key material of a specific principal by specifying /princ too.
<h2>What Encryption Type should I pick?</h2>
This one is a bit tricky because the good practices sometimes go against what the application can support. The encryption type algorithm has to be supported by the system (or Java framework) the application is running on and by the domain controllers. Since the <a href="https://docs.microsoft.com/en-us/windows-server/identity/ad-ds/active-directory-functional-levels">Windows Server 2008 domain functional level</a> (DFL), and assuming that the password of the account has been set after the DFL has been raised, Active Directory can and will do AES. And that will be the recommendation, to pick the AES256-SHA1. But what if the application cannot? Well, you will have to pick another one... And maybe the old school one (RC4-HMAC-NT, used by legacy Windows operating systems).

You should not use any DES based encryptions. The IETF is pretty clear for awhile now, see section Security Considerations on the Kerberos <a href="https://tools.ietf.org/html/rfc3961#page-33">RFC3061</a>. DES encryption for Kerberos is even <a href="https://support.microsoft.com/en-us/help/977321/kdc-event-id-16-or-27-is-logged-if-des-for-kerberos-is-disabled">disabled by default</a> since Windows Server 2008 domain controllers.

More on encryption types here: <a href="https://blogs.msdn.microsoft.com/openspecification/2011/05/30/windows-configurations-for-kerberos-supported-encryption-type/">Windows Configurations for Kerberos Supported Encryption Type</a>.

So pick the highest the application can support. What if the application supports only DES based encryption? Well, then it is time to update the application. Why would you lower the security of your entire domain just to accommodate an application which clearly lives in the past?

Do not opt for /crypto all but rather for /crypto AES256-SHA1.

Now, let's say you wish to just change the crypto. Then you do not need any permission assuming that you already know the password. Just proceed with:
<pre>ktpass /out app1.keytab /princ app1@verenatex.com -SetUPN /mapuser app1 /crypto AES256-SHA1 /ptype KRB5_NT_PRINCIPAL /pass Password1 -SetPass /target vdc01.verenatex.com</pre>
As long as you specify the right password, the keytab will contain the right keys.
<h2><span>Why should I always use the most recent version of ktpass?</span></h2>
The latest version on ktpass has always more parameters than the old ones. You can use the ktpass locally on the Windows Server 2016 server (or RSAT of Windows 10) even if the domain controllers are still running Windows Server 2008 R2. Also, some versions of ktpass have different default behavior (different default parameters) to avoid surprises, always use the most recent one available. Wait, there's even better... If you use ktpass from the Windows Server 2003 Support Tools SP2, there is quite a weird a bug. When you use that version, and if LDAPs is enabled in your environment, the tool will incorrectly set the attribute userPassword of the account with the actual cleartext password, available for every single authenticated user to read (lol?). What is the userPassword attribute? It is mostly there for LDAP compliance, but it is not used by Windows for logon (unless you <a href="https://msdn.microsoft.com/en-us/library/cc223249.aspx">enable it</a>, which I have never seen anywhere). So make sure you (or your one of your predecessors) have not done this in the past by running an LDAP query with the following filter:

[code language="PowerShell"]Get-ADObject -LDAPFilter &quot;(&amp;(servicePrincipalName=*)(userPassword=*))&quot;[/code]

If you have something in the output, and if it is an actual password, then delete the value for account and reset the password and regenerate the keytab file. And speaking on bugs, the <a href="https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/ktpass">current documentation</a> is also a bit weird (will be update soon, I hope)... I'd say if you want a more accurate version of the help file, you'll have to stick to the good old: ktpass /?.
<h2>More questions about keytabs?</h2>
Please send them in the comments section, I'll add them up here!]]></content:encoded>
    </item>
    <item>
      <title>Extract pictures from a Steps Recorder file</title>
      <link>https://docs.microsoft.com/archive/blogs/pie/extract-pictures-from-a-steps-recorder-file</link>
      <pubDate>Fri, 03 Nov 2017 20:28:48 GMT</pubDate>
      <dc:creator><![CDATA[Pierre Audonnet [MSFT]]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/pie/?p=1085</guid>
      <description><![CDATA[For those who don't know, there is a pretty cool feature built-in in Windows since Windows...]]></description>
      <content:encoded><![CDATA[For those who don't know, there is a pretty cool feature built-in in Windows since Windows Vista/Windows Server 2008 called <strong>Steps Recorder</strong>. It is there by default in your Windows folder: <strong>%windir%\system32\psr.exe</strong>. When you run it, it will capture a screenshot of each click that you perform on the system where it runs (if you want to capture the click from an RDP session, then you need to run it on the machine where you RDP to). This is what the tool interface looks like:

<a href="https://msdnshared.blob.core.windows.net/media/2017/11/PSR1.jpg"><img width="419" height="83" class="alignnone wp-image-1095" alt="" src="https://msdnshared.blob.core.windows.net/media/2017/11/PSR1.jpg" /></a>

It creates a nice <a href="https://en.wikipedia.org/wiki/MHTML">MHT</a> file that contains some information about the user running it, information about the system where it runs and a screenshot of everything you click and type. This is what the output looks like:

<a href="https://msdnshared.blob.core.windows.net/media/2017/11/PSR2.jpg"><img width="576" height="725" class="alignnone wp-image-1105" alt="" src="https://msdnshared.blob.core.windows.net/media/2017/11/PSR2.jpg" /></a><a href="https://msdnshared.blob.core.windows.net/media/2017/11/PSR11.jpg"></a>

The idea is to repro a problem, capture all the steps, save this as a ZIP file and send that to your support team. Although I have seen customers using it to create a quick document of what they have done. And even using it to "record" what they do during a change for later peer review.
Whatever the reason you have, you might hit two limitations when you use it:
<ol>
 	<li>It takes only the last 25 actions. That you can fix it with the Settings menu:
<a href="https://msdnshared.blob.core.windows.net/media/2017/11/PSR3.jpg"><img width="778" height="231" class="alignnone wp-image-1115" alt="" src="https://msdnshared.blob.core.windows.net/media/2017/11/PSR3.jpg" /></a></li>
 	<li>It is not super handy to use the picture you've taken from the MHT file as they are base64 encoded in the file.</li>
</ol>
And for that second point, I created the following script:

[code language="PowerShell"].\Extract-StepsRecorderPictures.ps1 -ZipFile C:\users\Bob\Documents\ClockIssue.zip -PicturesPath C:\temp\[/code]

<a href="https://msdnshared.blob.core.windows.net/media/2017/11/PSR4.jpg"><img width="583" height="273" class="alignnone wp-image-1116" alt="" src="https://msdnshared.blob.core.windows.net/media/2017/11/PSR4.jpg" /></a>

That you can download here:
<ul>
 	<li>Extract pictures from a Steps Recorder file: <a href="https://gallery.technet.microsoft.com/Extract-pictures-from-a-c0b0ad6e">https://gallery.technet.microsoft.com/Extract-pictures-from-a-c0b0ad6e</a></li>
</ul>
&nbsp;]]></content:encoded>
    </item>
    <item>
      <title>Why did I rename my Administrator account?</title>
      <link>https://docs.microsoft.com/archive/blogs/pie/why-did-i-rename-my-administrator-account</link>
      <pubDate>Tue, 17 Oct 2017 23:22:55 GMT</pubDate>
      <dc:creator><![CDATA[Pierre Audonnet [MSFT]]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/pie/?p=1045</guid>
      <description><![CDATA[The question of whether you should rename the built-in administrator account in Active Directory...]]></description>
      <content:encoded><![CDATA[The question of whether you should rename the built-in administrator account in Active Directory surprisingly resurfaced. I recently had chats about it with customer's security teams and it is a subject that is also coming back internally at Microsoft. <a href="https://technet.microsoft.com/en-us/library/2008.06.obscurity.aspx">It has always been a battle royale</a> with the arguments that "obscurity is not security" on one side and "ROI of implementation wins" on the other. In a nutshell, even if you rename the account, the objectSid of the account remains the same (so easily identifiable) but at the same time, renaming it is virtually free, so why not doing it and slowing down script kiddies.

So here is my take on it: <strong>I would do it.</strong> And this is <em>in part</em> why:
<ul>
 	<li>Network access validation algorithms and examples for Windows Server 2003, Windows XP, and Windows 2000 <a href="https://support.microsoft.com/kb/103390">https://support.microsoft.com/kb/103390</a></li>
</ul>
Yes, an old school KB article.
<h3>Some bits before we start...</h3>
They might seem unrelated, but you'll see that everything connects at the end like in a Tarantino movie.
<ol>
 	<li>The built-in Administrator of the domain is applying the account policy you defined in your domain but does not get locked out once the badPwdcount reaches the threshold of your account lockout policy. Why? Because it is your emergency account to access the environment in a situation when all the other accounts have been locked out (case of an annoying password discovery attack or malware). Well, technically it is possible to make the built-in account behave like the other and locking out, but that's too much of a tangent at this point (see here if you are curious: <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/aa375371(v=vs.85).aspx">DOMAIN_LOCKOUT_ADMINS</a>).</li>
 	<li>The built-in administrator account on Windows has the same name everywhere: Administrator. Unless you have changed it as well.</li>
 	<li>Although it is not a good practice, some desktop and server administrators are using the built-in Administrator to do local admin stuff on domain joined machines (if you really need to use that account, make sure you at least use <a href="https://technet.microsoft.com/en-us/mt227395.aspx">LAPS</a>).</li>
</ol>
<h3>Let's connect the dots</h3>
Remember back in the day when you had your two Windows XP in a LAN at home and you didn't want to be prompted when you were accessing a network share? Well, you had two ways to do it. You could enable anonymous access... Or you could have the same set of username/password on both machines. And looking at the latter, and following the logic described in the kb 103390, you will try to perform a network logon with the currently used account because you have an account with the same name in the remote machine. Well kinda the same thing happens in a domain environment. With a difference that if the remote machine is domain joined, this access might be forwarded to the domain controller. Let's look at some examples in action:

&nbsp;

<a href="https://msdnshared.blob.core.windows.net/media/2017/10/ADMIN1-corr.jpg"><img width="742" height="190" class="alignnone wp-image-1065" alt="" src="https://msdnshared.blob.core.windows.net/media/2017/10/ADMIN1-corr.jpg" /></a><a href="https://msdnshared.blob.core.windows.net/media/2017/10/ADMIN1.jpg"></a>
<ol>
 	<li>An operator opens a session on a server with the built-in local Administrator account. Or opens a command prompt or a PowerShell console with "runas" as a the built-in Administrator.</li>
 	<li>In the previous context, the operator runs a script or a console which tries to read Active Directory.</li>
 	<li>Each attempt will generate a failed authentication on the domain controller for the built-in domain Administrator account. Here are the events we see in the DC's security event log:
<ul>
 	<li>Event ID:      4625
Task Category: Logon

An account failed to log on.
Subject:
Security ID:  NULL SID
Account Name:  -
Account Domain:  -
Logon ID:  0x0
Logon Type:   3
Account For Which Logon Failed:
Security ID:  NULL SID
Account Name:  administrator
Account Domain:  VFILE01Failure Information:
Failure Reason:  Unknown user name or bad password.
Status:   0xC000006D
Sub Status:  0xC000006A
Process Information:
Caller Process ID: 0x0
Caller Process Name: -
Network Information:
Workstation Name: VFILE01
Source Network Address: 10.10.0.8
Source Port:  52444
Detailed Authentication Information:
Logon Process:  NtLmSsp
Authentication Package: NTLM
Transited Services: -
Package Name (NTLM only): -
Key Length:  0</li>
 	<li>Event ID:      4776
Task Category: Credential Validation

The computer attempted to validate the credentials for an account.
Authentication Package: MICROSOFT_AUTHENTICATION_PACKAGE_V1_0
Logon Account: administrator
Source Workstation: VFILE01
Error Code: 0xC000006A</li>
</ul>
</li>
</ol>
Another scenario:

<a href="https://msdnshared.blob.core.windows.net/media/2017/10/ADMIN2.jpg"><img width="742" height="353" class="alignnone wp-image-1066" alt="" src="https://msdnshared.blob.core.windows.net/media/2017/10/ADMIN2.jpg" /></a>
<ol>
 	<li>An operator opens a session on a server with the built-in local Administrator account. Or opens a command prompt or a PowerShell console with "runas" as a the built-in Administrator.</li>
 	<li>The operator tries to access a resource located on VSRV01. In that case it is using NET USE and explicitly specified the name of the account that has to be used (but not the password).</li>
 	<li>The server VSRV01 doesn't have an account called administrator (or it has one, but it is disabled).</li>
 	<li>The authentication is forwarded to the DC and an authentication attempt is performed for the built-in domain Administrator account resulting in an event 4625 being logged <span style="text-decoration: underline">on VSRV01</span> and the following event in the DC's security logs:
<ul>
 	<li>Event ID:      4776
Task Category: Credential Validation

The computer attempted to validate the credentials for an account.
Authentication Package: MICROSOFT_AUTHENTICATION_PACKAGE_V1_0
Logon Account: Administrator
Source Workstation: VFILE01
Error Code: 0xC000006A</li>
</ul>
</li>
</ol>
Those are just two examples. So you see it coming, these actions will at some point lock out the built-in domain administrator. But wait... I just said it won't lock out. True, but you will still see the event 4740 on the domain controller (and on the ePDC) although the account can still be used. Potentially quite confusing.
<h3>Soundproofing the security event logs</h3>
The problem of the behavior described above is that it will make you think your built-in domain administrator is under password discovery type of attacks when in fact, it is just some local user with the same name being used somewhere. Are you "affected" by this? Run the following PowerShell cmdLet:

[code language="PowerShell"]$_default_admin = Get-ADUser -Identity &quot;$((Get-ADDomain).DomainSID.Value)-500&quot; 
$_metadata_lockoutTime = Get-ADReplicationAttributeMetadata -Object $_default_admin -Properties lockoutTime -Server VDC01
$_metadata_lockoutTime.Version
$_metadata_lockoutTime.LastOriginatingChangeTime[/code]

This will tell you how many times the built-in domain admin has been locked out since the creation of the domain as well as the date and time of the last occurrence.
<strong>You will be surprised to see that it is often a very high number and that the last time was a few minutes ago.
So are you under attack?</strong>
<strong>Maybe. Or maybe you're just observing the behavior described here.</strong>

In case you don't have PowerShell handy (shame on you!), here is the equivalent in command line with REPADMIN:

[code]FOR /F %S IN ('dsquery * domainroot -scope base -attr objectSid ^| find /v &quot;objectSid&quot;') DO SET SID=%S
FOR /F &quot;TOKENS=4,5 DELIMS= &quot; %A IN ('repadmin /showobjmeta fsmo_pdc: &quot;&lt;SID=%SID%-500&gt;&quot; ^| find &quot;lockoutTime&quot;') DO ECHO %A %B[/code]

<em>Yes I know, it is a super fancy way to call REPADMIN...</em>

So if you rename the built-in administrator account with something different than what you use on your workstations and servers, you'll avoid that noise and the next lockout for the built-in domain administrator will maybe be worth being investigated.

But really, that's up to you :)

&nbsp;

&nbsp;]]></content:encoded>
    </item>
    <item>
      <title>Good news everyone! We are under brute force attack!</title>
      <link>https://docs.microsoft.com/archive/blogs/pie/good-news-everyone-we-are-under-brute-force-attack</link>
      <pubDate>Wed, 19 Jul 2017 22:16:45 GMT</pubDate>
      <dc:creator><![CDATA[Pierre Audonnet [MSFT]]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/pie/?p=925</guid>
      <description><![CDATA[The title is a tribute to Professor Farnsworth... I mentioned it because my jokes usually never...]]></description>
      <content:encoded><![CDATA[The title is a tribute to Professor Farnsworth... I mentioned it because my jokes usually never land... And just to make it clear, this post is not a guidance on what to do in case of brute force attacks (bummer... eh?), it is a just testimony of my recent experience with the topic and how I leveraged Windows built-in features, free Microsoft products and Azure services to sort it out.

So, it is a quiet Friday afternoon and I feel like testing the free subscription of Operations Management Suite. I was curious to see how much data the security logs of my 5 machines would take in one week. So I deployed the agents and... Saved by the weekend bell, I kinda forgot about it.

The week after I connected to the portal, and I saw something like this:

<a href="https://msdnshared.blob.core.windows.net/media/2017/07/BRUTE1.jpg"><img width="312" height="178" class="alignnone wp-image-926" alt="" src="https://msdnshared.blob.core.windows.net/media/2017/07/BRUTE1.jpg" /></a>

At first I was like 20K successful authentications? Hum... Ok, I have only 10 users in the lab but I am running a s###load of scripts. So why not. But then: 23K authentication failures! And that I couldn't explain it. So I look at the detailed reports that the <strong>Audit and Security OMS </strong>package is providing by default:

<a href="https://msdnshared.blob.core.windows.net/media/2017/07/BRUTE2.jpg"><img width="312" height="485" class="alignnone wp-image-935" alt="" src="https://msdnshared.blob.core.windows.net/media/2017/07/BRUTE2.jpg" /></a>

It is clear that it is not me. And I was even wondering if one of my account might be compromised by now. But not really... Brute force attacks with my passwords is very unlikely to succeed. So what are those? Looking at the details, they all hit the same machine...

This brings me back to a presentation I have delivered few weeks before. I needed to connect to my lab using RDP but the only port allowed in the premises was TCP 443. So I changed the random RDP port I was using to 443. And voila! I did my demo and everybody was happy. By doing this I actually exposed by lab to an army of RDP brute force zombies. I looked at my machine and I indeed see the thousands of random attempts, all generating 4625 events in my security logs:

<a href="https://msdnshared.blob.core.windows.net/media/2017/07/BRUTE3.jpg"><img width="395" height="339" class="alignnone wp-image-945" alt="" src="https://msdnshared.blob.core.windows.net/media/2017/07/BRUTE3.jpg" /></a>

The problem with the 4625 coming from a failed authentication on a RDP connection is that you don't have the source IP address:

<a href="https://msdnshared.blob.core.windows.net/media/2017/07/BRUTE4.jpg"><img width="475" height="443" class="alignnone wp-image-955" alt="" src="https://msdnshared.blob.core.windows.net/media/2017/07/BRUTE4.jpg" /></a>

So I enabled the firewall logs on the three profiles of my machine like this:

<a href="https://msdnshared.blob.core.windows.net/media/2017/07/BRUTE5.jpg"><img width="390" height="368" class="alignnone wp-image-965" alt="" src="https://msdnshared.blob.core.windows.net/media/2017/07/BRUTE5.jpg" /></a>

And I was indeed seeing an IP getting crazy on the logs (the log shows port TCP 3389, my port 443 publication is in fact a done at the perimeter by a NAT/PAT device):
<pre>2017-07-09 12:45:29 ALLOW TCP 89.163.148.77 10.10.0.6 22556 3389 0 - 0 0 0 - - - RECEIVE
2017-07-09 12:45:31 ALLOW TCP 89.163.148.77 10.10.0.6 42610 3389 0 - 0 0 0 - - - RECEIVE
2017-07-09 12:45:33 ALLOW TCP 89.163.148.77 10.10.0.6 26244 3389 0 - 0 0 0 - - - RECEIVE
2017-07-09 12:45:37 ALLOW TCP 89.163.148.77 10.10.0.6 29731 3389 0 - 0 0 0 - - - RECEIVE
2017-07-09 12:45:39 ALLOW TCP 89.163.148.77 10.10.0.6 46383 3389 0 - 0 0 0 - - - RECEIVE
2017-07-09 12:45:41 ALLOW TCP 89.163.148.77 10.10.0.6 33357 3389 0 - 0 0 0 - - - RECEIVE
2017-07-09 12:45:45 ALLOW TCP 89.163.148.77 10.10.0.6 37050 3389 0 - 0 0 0 - - - RECEIVE
2017-07-09 12:45:46 ALLOW TCP 89.163.148.77 10.10.0.6 50106 3389 0 - 0 0 0 - - - RECEIVE
2017-07-09 12:45:49 ALLOW TCP 89.163.148.77 10.10.0.6 40662 3389 0 - 0 0 0 - - - RECEIVE</pre>
Even a quick search on my favorite search engine revealed very quickly that this IP was already well-known for RDP brute force attacks. So I create a rule to block at on my host firewall:

<a href="https://msdnshared.blob.core.windows.net/media/2017/07/BRUTE6.jpg"><img width="414" height="429" class="alignnone wp-image-975" alt="" src="https://msdnshared.blob.core.windows.net/media/2017/07/BRUTE6.jpg" /></a>

Quick look at the firewall logs:
<pre>2017-07-09 12:45:49 ALLOW TCP 89.163.148.77 10.10.0.6 40662 3389 0 - 0 0 0 - - - RECEIVE
2017-07-09 12:48:51 DROP TCP 89.163.148.77 10.10.0.6 40662 3389 0 - 0 0 0 - - - RECEIVE
2017-07-09 12:48:55 DROP TCP 89.163.148.77 10.10.0.6 40662 3389 0 - 0 0 0 - - - RECEIVE</pre>
Cool. It's getting dropped. That was fun, but still, next time I want to be aware of this way quicker that this! And not figure out just by checking the OMS portal because I was bored. So let's create an alert in OMS, and next time I will know right away! Very simple logic: every 5 minutes I check for the number of event 4625 for the last 5 minutes. And if it is more than 10, I send an email:

<a href="https://msdnshared.blob.core.windows.net/media/2017/07/BRUTE7.jpg"><img width="561" height="476" class="alignnone wp-image-976" alt="" src="https://msdnshared.blob.core.windows.net/media/2017/07/BRUTE7.jpg" /></a>

The story could end here but later in the week... This happened:

<a href="https://msdnshared.blob.core.windows.net/media/2017/07/BRUTE8.jpg"><img width="431" height="358" class="alignnone wp-image-985" alt="" src="https://msdnshared.blob.core.windows.net/media/2017/07/BRUTE8.jpg" /></a>

LOL - Well I kinda asked for it. So being notified is one thing... But I want it to stop too! So let's take it up a notch. Let's have the following:
<ol>
 	<li>Create a scheduled task which runs every 5 minutes on the attacked server which check on how many events 4625 I have on the server for the last 5 minutes.</li>
 	<li>If it is more than 10, then look at the firewall log to see if it is the same IPs all the time.</li>
 	<li>If it is the same IP, then add it automatically to the firewall list.</li>
</ol>
So the scheduled task is a no challenge. I spare the details on it (unless you want me to elaborate).

The script is very basic, again this is not for you to copy/paste and implement in your environment, it is just sharing my rough ideas:

[code language="PowerShell"]
#Create some sort of logs
$_brute_log = &quot;C:\Brute\Log.txt&quot;
Function WriteLog($__msg) {
$__ts = (Get-Date).ToString(&quot;yyyy/MM/dd HH:mm:ss&quot;)
&quot;$($__ts) - $($__msg)&quot; | Out-File $_brute_log -Append
}
WriteLog &quot;NEW ENTRY _______________&quot;
#Filter to look for all the 4625 for the last 5 minutes
$filter = @&quot;
&amp;lt;QueryList&amp;gt;
&amp;lt;Query Id=&quot;0&quot; Path=&quot;Security&quot;&amp;gt;
&amp;lt;Select Path=&quot;Security&quot;&amp;gt;*[System[Provider[@Name='Microsoft-Windows-Security-Auditing'] and Task = 12544 and (EventID=4625) and TimeCreated[timediff(@SystemTime) &amp;amp;lt;= 300000]]]&amp;lt;/Select&amp;gt;
&amp;lt;/Query&amp;gt;
&amp;lt;/QueryList&amp;gt;
&quot;@
#Calculate the time the query take... That's for the sake it is fine as long as it takes less than 5 minutes.
$query_start = Get-Date
$querylogs = Get-WinEvent -ComputerName localhost -FilterXml $filter -ErrorAction SilentlyContinue
$query_stop = Get-Date
#Spit some logs
WriteLog &quot;Execution time: $($query_stop - $query_start)&quot;
WriteLog &quot;Result Count:&amp;nbsp; $($querylogs.Count)&quot;
#If it is highetr than 15, something fishy it happening
If ( $querylogs.Count -ge 15 ) {
#We parse the firewall logs (only the last 5000 lines)
Get-Content C:\Windows\system32\LogFiles\Firewall\pfirewall.log -Tail 5000 | `
Where-Object { $_ -like &quot;*ALLOW*3389*&quot;} | `
ForEach-Object { $_.Split(&quot; &quot;)[4]} | `
Group-Object | `
Sort-Object Count -Descending | `
ForEach-Object {
$IP = $_.Name
$count = $_.Count
#We don't care about local IPs
If ( $IP -like &quot;10.*&quot; ) {
WriteLog &quot;Local IP are skipped&quot;
} Else {
#It's not local, let's see how many attempt I have if it is more than 10 I don't like it
If ( $count -gt 10 ) {
WriteLog &quot;$IP doesn't look good with $count hits&quot;
$blockrule = Get-NetFirewallRule -DisplayName &quot;Block Brute Force&quot;
[array] $currentlist = (Get-NetFirewallAddressFilter -AssociatedNetFirewallRule $blockrule).RemoteAddress
#Check if the IP is already on the block list
If ( $currentlist -contains $IP ) {
WriteLog &quot;$IP is already blocked&quot;
} ELse {
#If not, we add it to the list
WriteLog &quot;$IP Will be added to the filter&quot;
$currentlist += $IP
Get-NetFirewallAddressFilter -AssociatedNetFirewallRule $blockrule | Set-NetFirewallAddressFilter -RemoteAddress $currentlist
WriteLog &quot;$IP added to the list&quot;
#Let's leave a message for OMS to pick up
EVENTCREATE /L APPLICATION /T ERROR /ID 666 /D &quot;$IP had $count hits, it has been added to the Block Brute Force firewall rule&quot;
}

} Else {
WriteLog &quot;$IP has only $count hits&quot;
}
}
}
} Else {
WriteLog &quot;Not enough 4625, looking good here&quot;
}
[/code]

Notice the EVENTCREATE at the end? (well I know I could have done it in PowerShell...) I plant an event that I will collect with OMS and alert on:

<a href="https://msdnshared.blob.core.windows.net/media/2017/07/BRUTE9.jpg"><img width="531" height="418" class="alignnone wp-image-995" alt="" src="https://msdnshared.blob.core.windows.net/media/2017/07/BRUTE9.jpg" /></a>

And this is the result in my mailbox:

<a href="https://msdnshared.blob.core.windows.net/media/2017/07/BRUTE10.jpg"><img width="478" height="92" class="alignnone wp-image-996" alt="" src="https://msdnshared.blob.core.windows.net/media/2017/07/BRUTE10.jpg" /></a>

And the current state of my firewall rule scope:

<a href="https://msdnshared.blob.core.windows.net/media/2017/07/BRUTE11.jpg"><img width="293" height="133" class="alignnone wp-image-1005" alt="" src="https://msdnshared.blob.core.windows.net/media/2017/07/BRUTE11.jpg" /></a>

Anyhow, that was fun  Oh wait, what about looking at where the different connection attempts I have are coming from, since I block only the most stupid attacks? Let's do some <a href="https://powerbi.microsoft.com/en-us/documentation/powerbi-desktop-get-the-desktop/">PowerBI </a>to parse the firewall logs:

<a href="https://msdnshared.blob.core.windows.net/media/2017/07/BRUTE12.jpg"><img width="609" height="300" class="alignnone wp-image-1015" alt="" src="https://msdnshared.blob.core.windows.net/media/2017/07/BRUTE12.jpg" /></a>

Now <em>that</em> is cool :)]]></content:encoded>
    </item>
    <item>
      <title>🐶🐶🐶 Credential theft made easy with Kerberos delegation</title>
      <link>https://docs.microsoft.com/archive/blogs/pie/credential-theft-made-easy-with-kerberos-delegation</link>
      <pubDate>Fri, 30 Jun 2017 22:12:00 GMT</pubDate>
      <dc:creator><![CDATA[Pierre Audonnet [MSFT]]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/pie/?p=836</guid>
      <description><![CDATA[Yes it takes just 2 lines of PowerShell to impersonate whoever you want... A small preamble: things...]]></description>
      <content:encoded><![CDATA[Yes it takes just 2 lines of PowerShell to impersonate whoever you want... A small preamble: things discussed here are not hacking techniques, nor innovative ways to impersonate a user. These are intended behaviors, and they all have been around for a very long time. Why talk about it now? Because as a part of my job, I deliver security assessments for Premier customers. And when it comes to Kerberos delegations risks, it is rare to have the appropriate attention. "Kerberos S4U2Proxy is a risk" sounds probably too geeky to be worried about 🤓.

Si tu parles français, ce billet est inspiré de ce celui-ci: <a href="https://blogs.technet.microsoft.com/frid/2017/06/29/kerberos-deleguerais-tu-vraiment-tes-credentials-a-un-chien/">Kerberos, déléguerais-tu vraiment tes credentials à un chien ?</a>
<h2>What is Kerberos delegation?</h2>
It is important to note that it has nothing to do with the right-click Delegate in the Users and Computers MMC. It has nothing to do with permissions on objects. In fact, it is way more powerful than that. Kerberos delegation is giving an account the permission to impersonate another account. Well, just reading this should help to foreseen how we can abuse it.
<h2>A necessary evil</h2>
Well it is not really evil, but we easily see what could be used for bad things. So how did all that stuff started? Kerberos delegation is actually solving an ancestral problem with multi-tiers applications. When you have a front-end server, like a web server, using back-end services like a database, or a SQL reporting, the application running on the front-end is accessing those back-end services on behalf a service account. It isn't fantastic from an accountability perspective because every access is always using the service account.  And from a permission perspective you have to give permissions to the service account and not the end-user. If we want to provide the context of the user to the back-end services, we'll need to request for the user's credentials again. This is the "double-hop" effect. And this can cause an ugly pop-up in which a disgruntle user will have to type its password again. But if we allow the front-end server (or rather its service account) to do Kerberos delegation, then the service will ask for tickets on behalf the user and the context of the user will be provided end-to-end.
<h2>3 ways to do Kerberos delegation</h2>
In the following example, I am looking at the Delegation tab of the computer account of VSRV01. Note that the delegation tab is not present on a user account unless it has a servicePrincipalName attribute defined (no SPN = no delegation).
<ol>
 	<li>Windows 2000 Server delegation aka Old school delegation
<a href="https://msdnshared.blob.core.windows.net/media/2017/06/FR-DELEG11.jpg"><img width="472" height="124" class="alignnone wp-image-845" alt="" src="https://msdnshared.blob.core.windows.net/media/2017/06/FR-DELEG11.jpg" /></a></li>
 	<li>Then there is the Windows Server 2003 using Kerberos end-to-end
<a href="https://msdnshared.blob.core.windows.net/media/2017/06/FR-DELEG21.jpg"><img width="478" height="146" class="alignnone wp-image-855" alt="" src="https://msdnshared.blob.core.windows.net/media/2017/06/FR-DELEG21.jpg" /></a></li>
 	<li>And the Windows Server 2003 with protocol transition
<a href="https://msdnshared.blob.core.windows.net/media/2017/06/FR-DELEG31.jpg"><img width="508" height="151" class="alignnone wp-image-865" alt="" src="https://msdnshared.blob.core.windows.net/media/2017/06/FR-DELEG31.jpg" /></a></li>
</ol>
Back in the Windows 2000 Server days, we just had the <em>Trust this computer for any service (Kerberos only</em>). From a risk perspective, it means that if Norma the attacker 👧 controls VSRV01, she can impersonate any users connected to the service running under local-system. So for if VSRV01 is running a web-service in local system, and Adam 👨 is browsing it, Norma can use his identity to access any Kerberos service in the domain (like his mailbox, his personal data...), without even Adam's knowledge. Pretty scary eh? We should do something about it...

Then arrive the two other options. They aims at correcting the risk mentioned above. When we configure it, we are asked to specify what service the account can impersonate the user to. This is called <strong>constrained delegation</strong>. So with <em>Trust this computer for delegation to specified services only</em> if VSRV01 can just do delegation to the SQL server VSQL01, then Norma 👧 can just impersonate Adam to VSQLo1. No more access to his emails... Less fun. Still a risk though.

The last option is the more interesting one: <em>Use any authentication protocol</em>. So why do we even have this options? It is to fix a truism. Kerberos delegation works only when we do Kerberos. So what if Adam authenticates against the VSRV01 using another protocol than Kerberos? Like NTLM 😱 or any other ways like a web form with some custom authentication provider. No Kerberos = No delegation. So the protocol transition kicks in. If the application has the privileges <em>Act as part of the operating system </em>as well as <em>Impersonate a client after </em>and the account set with the appropriate Kerberos delegation then the application will transform the user's authentication into Kerberos. In other words, <strong>it gives to the application the permission to impersonate any users</strong>. And <em>that</em> is fun.
<h2>Practical example</h2>
Still not convinced of the risks, or it is still not clear why you should care? Let's put it in practice. Here is my current delegation settings on VSRV01:

<a href="https://msdnshared.blob.core.windows.net/media/2017/06/FR-DELEG41.jpg"><img width="798" height="309" class="alignnone wp-image-875" alt="" src="https://msdnshared.blob.core.windows.net/media/2017/06/FR-DELEG41.jpg" /></a>

I connect to my server VSRV01 with an local account member of the local administrators group. And I try to access the C$ administrative share of VFILE01:

<a href="https://msdnshared.blob.core.windows.net/media/2017/06/FR-DELEG61.jpg"><img width="306" height="37" class="alignnone wp-image-885" alt="" src="https://msdnshared.blob.core.windows.net/media/2017/06/FR-DELEG61.jpg" /></a>

So I open a PowerShell console in the local system context (why? because the delegation permissions are given to the computer account VSRV01). Let's use PSEXEC:
<pre>PSEXEC -i -s -d PowerShell</pre>
Then I just decide to change my identity to... Hum. Let's pick the domain admin account. For my lab it is piaudonnmsdn@vereantex.com:

[code language="PowerShell"]$u = New-Object System.Security.Principal.WindowsIdentity(&quot;piaudonnmsdn@verenatex.com&quot;)
$u.Impersonate()[/code]

And let's try again to access VFILE01 C$ share:

<a href="https://msdnshared.blob.core.windows.net/media/2017/06/FR-DELEG81.jpg"><img width="548" height="221" class="alignnone wp-image-895" alt="" src="https://msdnshared.blob.core.windows.net/media/2017/06/FR-DELEG81.jpg" /></a>

What does it look like on the cable? We see the TGT request (no password required for protocol transition) followed by a service ticket request for CIFS/VFILE01:

<a href="https://msdnshared.blob.core.windows.net/media/2017/06/FR-DELEG71.jpg"><img width="697" height="313" class="alignnone wp-image-905" alt="" src="https://msdnshared.blob.core.windows.net/media/2017/06/FR-DELEG71.jpg" /></a>

You can see the flag <strong>S4U2Proxy</strong> flag. It means that we are using that protocol transition here.

I chosed to impersonate the domain admin. I could have picked up any other account. If I try to access VSQL01 SQL service, I could do it with the admin of the service or even the service account. The PSEXEC here is just to switch to the machine's context. If the delegation was set on a service account, I could retrieve the credential of the service account with any credential theft tool and then use it to request the ticket.
<h2>OMG! We're all gonna die! We need to disable delegation!</h2>
Hehe, no<strong>.</strong>

The delegation and even the protocol transition are great features! They even help to strengthen application's security by providing accountability for each access and providing the user's context end-to-end. So we need them! But we need to be careful. Rigor is the way to go. Here is a to-do list when you are facing an account with delegation.
<ol>
 	<li>Make sure than only domain admins can configure delegation. It is a privilege on domain controller. You can control it with a group policy linked to the Domain Controllers OU, it is called <em>Enable computer and user accounts to be trusted for delegation:
</em><a href="https://msdnshared.blob.core.windows.net/media/2017/06/KDELEGPRIV.jpg"><img width="573" height="193" class="alignnone wp-image-915" alt="" src="https://msdnshared.blob.core.windows.net/media/2017/06/KDELEGPRIV.jpg" /></a></li>
 	<li>Make sure that all accounts allowed for delegation are <em>actually</em> requiring the settings. Configuring Kerberos delegation can be tricky and we rarely get it right in the first place (unless your initials are AM 🤐). So it wouldn't be surprising that you have some bribes of delegations set here and there. If Kerberos delegation is not expected. It should not be configured.</li>
 	<li>If you need delegation, use the constrained delegation! It's been around for a while now. So no more excuses for the old school delegation to be around... Well unless there is a supportability issue for your application... Then you have an application to upgrade 😜</li>
 	<li>Make sure that the accounts allowed for protocol transition are actually requiring the settings! Like for point 2, it is not rare to see multiples attempts to set it right. So maybe you have it set but you don't need it. It's time to RTFM of the application!</li>
 	<li>This one is not specific for Kerberos delegation risk mitigation, it's general guidance, some of us would even say common sense. Make sure you lock down the local administrators groups of your servers for which is account is allowed for delegation. And if you have delegation enabled on a service account, well all the local administrators of the machines where is account is used. But really, you should already be doing this.</li>
 	<li>Make sure that accounts which are not using delegation cannot be delegated. It's the case of your admins accounts. They do not access LOB apps. Therefore you can prevent them from being delegated. It is the option called: The account is sensitive and cannot be delegated.
<a href="https://msdnshared.blob.core.windows.net/media/2017/06/FR-DELEG91.jpg"><img width="560" height="207" class="alignnone wp-image-916" alt="" src="https://msdnshared.blob.core.windows.net/media/2017/06/FR-DELEG91.jpg" /></a>
Well this or any other way to delegate Kerberos delegation like with Windows Server 2012 R2 Authentication Policies and Silos. If I had this checked in my practical example, the local admin of VSRV01 couldn't have impersonate the account. There is actually one situation where AD admin accounts are using Kerberos delegation. It is when you are moving a user from one domain to another within the same forest using MOVETREE of ADMT. But you are not doing this everyday. So you can easily get around this by unchecking the option, doing the move and re-checking the option.</li>
</ol>
For the finicky Kerberos aficionados, I know, I completely skipped (purposely?) the Resource Based Delegation feature of Windows Server 2012. If you want to blog about it, and explain how that affect things, let me know I link you up here!
<h2>Alright, I feel better now. How do I get the list of accounts to check?</h2>
There are tons of articles and posts giving examples of query and stuff. I will let you find them and give you a quick and easy way n the mean time:
<ol>
 	<li>List all machine accounts enabled for old school delegation:

[code language="PowerShell"]Get-ADObject -LDAPFilter:&quot;(&amp;(objectCategory=computer)(objectClass=computer)(userAccountControl:1.2.840.113556.1.4.803:=524288))&quot;[/code]

Note that this also returns the domain controllers. This is an expected configuration and does not need to be corrected.</li>
 	<li>List all user accounts enabled for old school delegation:

[code language="PowerShell"]Get-ADObject -LDAPFilter:&quot;(&amp;(objectCategory=person)(objectClass=user)(userAccountControl:1.2.840.113556.1.4.803:=524288))&quot;[/code]

</li>
 	<li>List all machine accounts enabled for protocol transition:

[code language="PowerShell"]Get-ADObject -LDAPFilter:&quot;(&amp;(objectCategory=computer)(objectClass=computer)(userAccountControl:1.2.840.113556.1.4.803:=16777216))&quot;[/code]

</li>
 	<li>List all user accounts enabled for protocol transition:

[code language="PowerShell"]Get-ADObject -LDAPFilter:&quot;(&amp;(objectCategory=person)(objectClass=user)(userAccountControl:1.2.840.113556.1.4.803:=16777216))&quot;[/code]

</li>
</ol>
That's it for now. Questions? Comments? Too many emoticons?]]></content:encoded>
    </item>
    <item>
      <title>Do I really need ADFS?</title>
      <link>https://docs.microsoft.com/archive/blogs/pie/do-i-really-need-adfs</link>
      <pubDate>Mon, 06 Feb 2017 00:50:10 GMT</pubDate>
      <dc:creator><![CDATA[Pierre Audonnet [MSFT]]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/pie/?p=825</guid>
      <description><![CDATA[Update 2018-01-06: Lots of new things came up so I updated this article.
Update 2018-04-10: Few...]]></description>
      <content:encoded><![CDATA[<strong><em><span style="color: #ff0000">Update 2018-01-06: Lots of new things came up so I updated this article.
</span></em></strong><span style="color: #ff0000"><b><i>Update 2018-04-10: Few updates again, thanks to your contributions! </i></b></span>

I often hear and read misconceptions on whether or not you should or must deploy an ADFS farm <strong>when Office 365 is in the picture</strong>. So I will try to give you my version (well it is a collection of feedback from my peers as well), hoping that might help you to sort out your thoughts.
<h4>ADFS and Office 365</h4>
Even when you have deployed an ADFS farm as a part of your Office 365 adoption, your ADFS farm doesn't trust Office 365. Your ADFS farm trusts Azure Active Directory. It seems that I am just being finicky with the wording but it has its importance. You can use Azure AD without using any of the workloads of Office 365. Although we sometimes use that shortcut, keep in mind that ADFS is in fact trusting your Azure Active Directory.
<h4>ADFS and Azure AD Connect</h4>
Those are two different things. They do not talk to each other, they have their own database... The only thing they have in common is that they are domain joined. That is about it.
<h3>Why do I need ADFS to use Office 365 or Azure AD?</h3>
Well, <strong>you don't</strong>. The primary reason why you want ADFS deployed in conjunction with your Office 365 deployment or your Azure AD is that you want <strong>Single Sign-On</strong>, aka SSO. And I am talking about a real SSO, in other words, if you entered your credentials when you sign-in to your device in the morning, you should not be asked to re-enter them when you are accessing applications trusting your Azure AD during the day (so SSO with your Office 365 applications as well as other SaaS applications you might have signed up for). So SSO here means Single Sign-On. Not Same Sign-On (Same Sign-On is when you can use the same credentials to access your applications but it is not seamless, the user is prompted to re-enter them). Why do you need ADFS for SSO? Because you need your STS to be able to perform <strong>Windows Integrated Authentication</strong>. And long story short, your STS needs to be domain joined.
<h3>What am I losing if I am not using ADFS (or any other STS)?</h3>
It seems quite obvious if you read the previous section. You are losing SSO. So if you do not care about SSO, you could just use Azure AD and no federation STS at all (STS is Security Token Service, it is the generic term for ADFS, ADFS is the on-premises STS from Microsoft). But if we dig a bit deeper, there are some other reasons that might seem to you like corner cases but often turn out to be deal breakers for Azure AD and Office 365 projects.
<ol>
 	<li><strong>If you want to use Office 365, and you do not want to store your password in the cloud.</strong><strong> </strong>
First of all, when you are synchronizing your object in Azure AD with Azure AD Connect and you select the password synchronization feature, we do not store the password in the cloud. Then, in ADDS on-premises, we do not store your passwords either! We store the hash of your passwords. And when we synchronize passwords with Azure AD Connect, we hash the hash and store the hash of the hash in Azure AD. But still, if you do not want this, then you might consider not enabling the password sync feature and federate with ADFS.
<span style="color: #ff0000"><em>Update: Can do that with Azure AD Pass-through Authentication since this is now GA.</em></span></li>
 	<li><strong>If you want the authentication to take place on-premises.</strong>
I have run into this situation a couple of times. You have a requirement to have all users authenticated on premises. Usually it is tied to the point above, the passwords need to be stored only on-premises. But I have also run into situations where the authentication process itself has to take place on premises. In that case you might consider federating your Azure AD with an ADFS farm.</li>
 	<li><strong>If you want to create a trust between SharePoint on-premises and Azure AD.</strong>
You don't mind much about SSO, but there is this neat intranet on-premises running SharePoint that you'd like to federate with Azure AD. It is actually not possible to do as of today. SharePoint is expecting a SAML 1.1 token and Azure AD cannot issue this format of token. SharePoint isn't the only application in that case, in fact any application expecting a SAML 1.1 token cannot trust Azure AD directly. So here you might consider deploying an ADFS farm to do the transition.
<span style="color: #ff0000"><em>Update: Azure AD Premium can handle it: https://docs.microsoft.com/en-us/office365/enterprise/using-azure-ad-for-sharepoint-server-authentication (thanks Steve!)</em></span></li>
 	<li><strong>If you need to send a very custom claim to your trusted application.</strong>
If you need to transform an incoming claim into something that doesn't fit in what's available on the Azure AD portal, then you might need to use an ADFS farm to be able to craft the token the way you wish. I have seen customers with custom attribute stores in ADFS that they cannot reproduce in Azure AD.
<span style="color: #ff0000"><em><span>Update: </span>New stuff available now: Customizing claims issued in the SAML token for enterprise applications in Azure Active Directory https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-saml-claims-customization</em></span></li>
 	<li><strong>If you need to use your own MFA provider.</strong>
Azure AD comes with Azure AD MFA. However, if you need to use another MFA provider than the Azure one (like one for your own on-premises security token solution), you might consider deploying an ADFS farm and deploying the custom MFA adapters on all the ADFS nodes.
<em><span style="color: #ff0000"><span>Update: </span>About to change with the integration of a bunch of MFA vendors in the Conditional Access options.</span> </em></li>
 	<li><strong>If you need to go beyond the Azure Conditional Access Policies you can choose from in the Azure AD portal.</strong>
If you want to ensure legacy clients are not by-passing any of your policies, or you want to add some custom authorization rules that you cannot achieve with the Azure AD portal, then you might also consider deploying an ADFS farm.
<span style="color: #ff0000"><em>Update: The list of capabilities of Azure AD Conditional Access keeps growing. Although you cannot block legacy clients with Azure AD CA, you can force the legacy client to comply with MFA and not configure AppPassword. As a result, they won't be able to connect anymore. </em></span></li>
 	<li><strong>You need to use auto-registration for Windows 7 and 8.1 domain joined devices.</strong>
This is to accommodate the "only domain joined machines can access Office 365" type of scenario for <a href="https://docs.microsoft.com/en-us/azure/active-directory/active-directory-conditional-access-automatic-device-registration">Windows 7 and Windows 8.1 domain joined</a>. And this might require you to deploy an ADFS farm.
<span style="color: #ff0000"><em>Update: You can now use</em></span><em> <span style="color: #ff0000">Azure AD Seamless SSO for this scenario, see: Update: https://docs.microsoft.com/en-us/azure/active-directory/connect/active-directory-aadconnect-sso</span></em></li>
 	<li><b>Update: You want to avoid the Home Realm Discovery prompt with Azure AD Connect Seamless SSO. </b><span style="float: none;background-color: transparent;color: #333333;cursor: text;font-family: Georgia,'Times New Roman','Bitstream Charter',Times,serif;font-size: 16px;font-style: normal;font-variant: normal;font-weight: 400;letter-spacing: normal;line-height: 24px;text-align: left;text-decoration: none;text-indent: 0px">Despite the name, it is not so seamless. Well to be fair, you will be asked your email address when it is the first time you connect to your apps from your machine. Not too bad, but it seems that the only way to avoid this so far is to have a local STS supporting WS-Trust endpoint. </span></li>
</ol>
<h3>I will miss you ADFS... Or the <del>new</del> feature that shrinks the list.</h3>
For points 1 and 2 there is a new feature to consider: <a href="https://docs.microsoft.com/en-us/azure/active-directory/connect/active-directory-aadconnect-pass-through-authentication">Azure AD Pass-Through Authentication</a>. So in a nutshell, you don't care about SSO. So you might consider the Azure AD Password sync. But you are in case 1 or 2. No passwords in the cloud or authentications have to be performed on-premises. This is what that looks like:
<ul>
 	<li>On-premises you have an agent (Microsoft AAD App Proxy Connector) constantly polling your Azure AD to check if there are credentials to check (it is important to note here that it is your agent contacting Azure AD and not Azure AD contacting your agent, so there are no incoming ports to open).</li>
 	<li>When the user typed its credentials, they are put in a queue in Azure AD and retrieved by the on-premises agent.</li>
 	<li>The agent verifies them and updates the queue with something like "good creds" or "bad creds".</li>
 	<li>Azure AD validates the authentication or prompts the user for its credentials again if they were incorrect.</li>
</ul>
So, great that we don't rely on ADFS to authenticate but still do not have SSO for your domain joined machines...
<h3>Wait a minute, why don't we do that the same way with domain joined machines and then we have SSO?</h3>
<del>This is coming :)</del> <span style="color: #ff0000">Update: It is here now.</span> The preview feature is called <a href="https://docs.microsoft.com/en-us/azure/active-directory/connect/active-directory-aadconnect-sso">Azure AD Connect Seamless SSO</a>. The idea is that you would have SSO for your domain joined machines when they are connected on-premises. Like if you had an ADFS farm on-premises. Hum... To have a Kerberos type of SSO, the targeted services (identified by a SPN) have to be domain joined too. So the Azure AD "server" will be domain joined? Almost :) Will I have to open ports to my DC? No. In fact resources wanting to do Kerberos SSO do not need to be domain joined, but they need to exist as an entity holding a SPN in the forest and the resources need the cryptographic material to decrypt Kerberos tickets. You would have guessed, we create an account for that purpose in your ADDS (it is created by the AAD Connect wizard), with an SPN, we configure the user-agents (aka Internet browsers) to accept to perform Windows Integrated Authentication over the Internet <strong>but just for a specified Azure AD URL</strong>. And the magic takes place:
<ul>
 	<li>The user connects to an application trusting Azure AD from a domain joined machine.</li>
 	<li>The application redirects the user to Azure AD for authentication.</li>
 	<li>Azure AD <em><span style="color: #ff0000">(Update: Thanks to a JavaScript trick running in the background)</span> </em>responds with a HTTP 401.</li>
 	<li>The user then requests a Kerberos ticket for a specific SPN like it would do for any Windows Integrated Authentication.</li>
 	<li>The user sends the ticket to Azure AD.</li>
 	<li>Azure AD has the cryptographic material to decrypt it and to validate it.</li>
 	<li>SSO :)</li>
</ul>
<h3>So should I stop training or investing in ADFS?</h3>
Not at all! The list of scenarios where you need ADFS for Office 365 and Azure AD is getting smaller, but you can still use ADFS for other stuff than Office 365 and Azure AD. For example, you can use it for your own applications with no cloud involved. ADFS on Windows Server 2016 now supports all OAuth 2.0 profiles and OpenID Connect. So there are plenty of scenarios where it will do a great job federating applications.]]></content:encoded>
    </item>
    <item>
      <title>ADFS 2016 - Change the Active Directory claim provider display name in the Home Realm Discovery page</title>
      <link>https://docs.microsoft.com/archive/blogs/pie/adfs-2016-change-the-active-directory-claim-provider-display-name-in-the-home-realm-discovery-page</link>
      <pubDate>Fri, 02 Dec 2016 16:19:44 GMT</pubDate>
      <dc:creator><![CDATA[Pierre Audonnet [MSFT]]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/pie/?p=745</guid>
      <description><![CDATA[In Windows Server 2012 R2 ADFS (well that everybody calls ADFS 3), the display name of the ADFS farm...]]></description>
      <content:encoded><![CDATA[In Windows Server 2012 R2 ADFS (well that everybody calls ADFS 3), the display name of the ADFS farm was also the display name of the Active Directory claim provider name in the Home Realm Discovery page.

[code language="PowerShell"]Get-AdfsProperties | Select-Object DisplayName
#Output:
#DisplayName
#-----------
#Yoga Corp.[/code]

Here what it looked like:

<a href="https://msdnshared.blob.core.windows.net/media/2016/12/HRD_NAME_0.jpg"><img width="742" height="421" class="alignnone size-full wp-image-755" alt="hrd_name_0" src="https://msdnshared.blob.core.windows.net/media/2016/12/HRD_NAME_0.jpg" /></a>

And this regardless of the actual name of the claim provider trust for AD:

[code language="PowerShell"]Get-AdfsClaimsProviderTrust -Identifier &quot;AD AUTHORITY&quot; | Select-Object Name
#Output:
#Name
#----
#Active Directory[/code]

In Windows Server 2016 ADFS (also known as ADFS 4...) this isn't the case anymore. The display name of the farm is no longer the display name of the Active Directory claim provider trust. As a result, the Home Realm Discovery page will look like this:

<a href="https://msdnshared.blob.core.windows.net/media/2016/12/HRD_NAME_1.jpg"><img width="654" height="405" class="alignnone size-full wp-image-765" alt="hrd_name_1" src="https://msdnshared.blob.core.windows.net/media/2016/12/HRD_NAME_1.jpg" /></a>

We can see that the display name of my farm is Piaudonn ADFS 2016 and that the display name of my AD claim provider is Active Directory. Some PowerShell to illustrate the difference:

[code language="PowerShell"]Get-AdfsProperties | Select-Object DisplayName
#Output:
#DisplayName
#-----------
#Piaudonn ADFS 2016

Get-AdfsClaimsProviderTrust -Identifier &quot;AD AUTHORITY&quot; | Select-Object Name
#Output:
#Name
#----
#Active Directory[/code]

So the first reflex we have to change it since it is no longer the display name of the farm, is to change the name of the AD claim provider trust directly:

[code language="PowerShell"]Get-AdfsClaimsProviderTrust -Identifier &quot;AD AUTHORITY&quot; | Set-AdfsClaimsProviderTrust -Name &quot;Corp Users&quot;[/code]

But here is the output:
<pre><strong><span style="color: #ff0000">Set-AdfsClaimsProviderTrust : PS0027: No properties except AcceptanceTransformRules and AcceptanceTransformRulesFile</span></strong>
<strong><span style="color: #ff0000">can be modified on the ADAuthority claims provider trust.</span></strong></pre>
So, here is a workaround.
<h3>JavaTrick</h3>
We will use the OnLoad.js JavaScript present in all rendered page to dynamically change the display name "Active Directory" into what ever we want. In my case: Corp Users.
<ol>
 	<li><strong>Create a custom web theme for you ADFS farm.</strong>
Note that JavaScript customization cannot be done for the default web theme. If you already have a custom web theme, you can skip this and go to step 2.

[code language="PowerShell"]New-AdfsWebTheme -Name CorpWebTheme -SourceName Default[/code]

If you already have set a logo and an illustration picture in the default theme, because I used the Default as the source, they will automatically be present in the newly created CorpWebTheme.</li>
 	<li><strong>Export the current OnLoad.js to be able to modify it.</strong>
We create the folder C:\CorpWebTheme and run the following cmdLet:

[code language="PowerShell"]Export-AdfsWebTheme -Name CorpWebTheme -DirectoryPath C:\CorpWebTheme[/code]

This is what we get in our folder:
<pre>C:\&gt;tree /F C:\CorpWebTheme
Folder PATH listing
Volume serial number is 5C78-23B0
C:\CORPWEBTHEME
├───css
│       style.css
│       style.rtl.css
│
├───illustration
│       illustration.png
│
├───images
│   └───idp
│           idp.png
│           localsts.png
│           otherorganizations.png
│
└───script
        onload.js</pre>
We can see the onload.js in the script subfolder.</li>
 	<li><strong>Modify the JavaScript.</strong>
We need to detect what is the identifier of the Active Directory display name in the HTML rendering. I use the developer mode of IE (just pressed F12) and use the DOM selector to identify where in is the string is in the page:
<a href="https://msdnshared.blob.core.windows.net/media/2016/12/HRD_NAME_2.jpg"><img width="986" height="457" class="alignnone size-full wp-image-775" alt="hrd_name_2" src="https://msdnshared.blob.core.windows.net/media/2016/12/HRD_NAME_2.jpg" /></a>
Not a good news, it seems that the claim provider trust display names do not have a unique identifier and they all have the same class:
<a href="https://msdnshared.blob.core.windows.net/media/2016/12/HRD_NAME_3.jpg"><img width="528" height="63" class="alignnone size-full wp-image-785" alt="hrd_name_3" src="https://msdnshared.blob.core.windows.net/media/2016/12/HRD_NAME_3.jpg" /></a>
<del datetime="2016-12-03T01:54:36+00:00">And it seems that the Active Directory claim provider trust is always the last one (bottom of the list, at least it my labs, if it is not the case in yours, please let me know).</del> Update: I changed the orignal code since it appears that the Active Directory claim provider trust is not always at the end of the list. Hence, the code is looking for the AD trust before replacing its display name.
So I open the onload.js and add the following code at the end of it:

[code language="JavaScript"]//Check if we are in the HRD page
if ( document.getElementById(&quot;hrdArea&quot;) ) {
	var strADCPName = &quot;Corp Users&quot; ;
	//Create an array of all claim provider trust section in the page
	var listAllSpanForIdp = document.getElementsByClassName(&quot;idpDescription float&quot;) ;
	var inc;
	for (inc = 0; inc &lt; listAllSpanForIdp.length; inc++) {
		if ( listAllSpanForIdp[ inc ].innerHTML == &quot;&lt;span class=\&quot;largeTextNoWrap indentNonCollapsible\&quot;&gt;Active Directory&lt;/span&gt;&quot; ) {
			//Change the HTML content of the matching section to the value specified in the strADCPName variable
			listAllSpanForIdp[ inc ].innerHTML = &quot;&lt;span class=\&quot;largeTextNoWrap indentNonCollapsible\&quot;&gt;&quot;+ strADCPName +&quot;&lt;/span&gt;&quot; ;
		}
	}
}[/code]

The code is quite self explanatory, I change the HTML content last occurrence of the class "idpDescription float" and replace it with "Corp Users". I save the file with the same name (we can actually give it the name you want, it does not matter).</li>
 	<li><strong>Import the modified OnLoad.js script back into the web theme.</strong>
I import the script back into the web theme:

[code language="PowerShell"]Set-AdfsWebTheme -TargetName CorpWebTheme -AdditionalFileResource @{Uri=&quot;/adfs/portal/script/onload.js&quot;;path=&quot;C:\CorpWebTheme\script\onload.js&quot;}[/code]

Once imported you can delete the CorpWebTheme folder. It is no longer used (you imported your JavaScript directly into the ADFS database). And if the webtheme is not the active one, remember to enable it:

[code language="PowerShell"]Set-AdfsWebConfig -ActiveThemeName CorpWebTheme[/code]

</li>
</ol>
And here is the final result:

<a href="https://msdnshared.blob.core.windows.net/media/2016/12/HRD_NAME_4.jpg"><img width="595" height="382" class="alignnone size-full wp-image-795" alt="hrd_name_4" src="https://msdnshared.blob.core.windows.net/media/2016/12/HRD_NAME_4.jpg" /></a>

Let me know how it goes in the comments section!]]></content:encoded>
    </item>
    <item>
      <title>List all possible security events and their descriptions in PowerShell</title>
      <link>https://docs.microsoft.com/archive/blogs/pie/list-all-possible-security-events-and-their-descriptions-in-powershell</link>
      <pubDate>Sat, 05 Nov 2016 01:13:01 GMT</pubDate>
      <dc:creator><![CDATA[Pierre Audonnet [MSFT]]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/pie/?p=685</guid>
      <description><![CDATA[If you'd like to know all the possible security event in your system, the best way to do it is to...]]></description>
      <content:encoded><![CDATA[If you'd like to know all the possible security event in your system, the best way to do it is to download the spreadsheet that has the full list:
<ul>
 	<li><a href="http://www.microsoft.com/en-us/download/details.aspx?id=50034">Windows security audit events </a></li>
</ul>
This is great, very complete but also implies that you have an Internet connection and Excel to open the file. An other geek way to do it is to leverage PowerShell to list all possible events from one specific provider. The provider for security events is: Microsoft-Windows-Security-Auditing. So here is the extended one-liner which will enable you to do that:

[code language="PowerShell"](Get-WinEvent -ListProvider &quot;Microsoft-Windows-Security-Auditing&quot;).Events | `
    Select-Object @{Name='Id';Expression={$_.Id -band 0xffffff}}, Description, @{Name='Parameters';Expression={($_.Template).template.data}} | `
        Out-GridView -Title &quot;Audit Event IDs&quot; -PassThru | `
            Format-List[/code]

And here is the output:

<a href="https://msdnshared.blob.core.windows.net/media/2016/11/AUDIT_PS_1.jpg"><img width="846" height="605" class="alignnone size-full wp-image-695" alt="audit_ps_1" src="https://msdnshared.blob.core.windows.net/media/2016/11/AUDIT_PS_1.jpg" /></a>

Because this is an <strong>Out-GridView </strong>output, you can easily navigate, and filter. For example, if you don't recall the event ID for the account lockout:

<a href="https://msdnshared.blob.core.windows.net/media/2016/11/AUDIT_PS_2.jpg"><img width="832" height="337" class="alignnone size-full wp-image-705" alt="audit_ps_2" src="https://msdnshared.blob.core.windows.net/media/2016/11/AUDIT_PS_2.jpg" /></a>

And because you can also use the <strong>-PassThrough</strong> parameter, you can even select one or more events, click on <strong>OK</strong> and get the details into the PowerShell console:

<a href="https://msdnshared.blob.core.windows.net/media/2016/11/AUDIT_PS_3.jpg"><img width="1014" height="317" class="alignnone size-full wp-image-715" alt="audit_ps_3" src="https://msdnshared.blob.core.windows.net/media/2016/11/AUDIT_PS_3.jpg" /></a>

Give it a try! And try other providers, you can get the list of provider in the system with the following:

[code language="PowerShell"]Get-WinEvent -ListProvider *[/code]

<em>Special thanks to my colleague Chris Wu for sharing the tips of listing events for a specific provider. A french version of this article is available <a href="https://blogs.technet.microsoft.com/frid/2016/10/25/lister-tous-les-evenements-de-securite-possibles-et-leurs-descriptions-en-powershell/">here</a>.</em>]]></content:encoded>
    </item>
    <item>
      <title>ADFS 2016 - Cannot add/update Relying Parties from the GUI from metadata files "Method not found"</title>
      <link>https://docs.microsoft.com/archive/blogs/pie/adfs-2016-cannot-addupdate-relying-party-from-the-gui-from-metadata-files</link>
      <pubDate>Sun, 23 Oct 2016 21:27:50 GMT</pubDate>
      <dc:creator><![CDATA[Pierre Audonnet [MSFT]]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/pie/?p=655</guid>
      <description><![CDATA[UPDATE: The following update is fixing this issue:

 	Cumulative Update for Windows 10 Version...]]></description>
      <content:encoded><![CDATA[<span style="color: #ff0000">UPDATE: The following update is fixing this issue:</span>
<ul>
 	<li><span style="color: #ff0000">Cumulative Update for Windows 10 Version 1607 and Windows Server 2016: December 9, 2016 https://support.microsoft.com/en-us/kb/3201845</span></li>
</ul>
If you are currently using the October release of Windows Server 2016 (build: 10.0.14393 N/A Build 14393) you might experience a weird error message when you try to add a relying party trust or update a relying party trust with the metadata files. Whether it is from an HTTPs source or even a local XML files that you previously saved, you have the following message:

<a href="https://msdnshared.blob.core.windows.net/media/2016/10/GUI_METADATA_1.jpg"><img width="657" height="189" class="alignnone size-full wp-image-665" alt="GUI_METADATA_1" src="https://msdnshared.blob.core.windows.net/media/2016/10/GUI_METADATA_1.jpg" /></a>

It seems that adding or updating a relying party from the console currently does not work as expected. If you don't know what version of Windows you are running, you can run the command "systeminfo" in command prompt and look at the build line.

But no worry, you can still do the job thanks to our good old friend PowerShell.

Adding a relying party trust from an online metadata file:

[code language="PowerShell"]Add-AdfsRelyingPartyTrust -Name &quot;My App&quot; -MetadataUrl &quot;https://web.piaudonn.com/app/federationmetadata/2007-06/federationmetadata.xml&quot;[/code]

Adding a relying party trust from a metadata saved on the your ADFS server:

[code language="PowerShell"]Add-AdfsRelyingPartyTrust -Name &quot;My App&quot; -MetadataFile &quot;C:\Temp\FederationMetadata.xml&quot;[/code]

Updating the relying party trust from the metadata file already set on the properties of the trust:

[code language="PowerShell"]Update-AdfsRelyingPartyTrust -TargetName &quot;My App&quot; [/code]

This will probably be fixed very soon!

&nbsp;]]></content:encoded>
    </item>
  </channel>
</rss>