This is a Windows 2019 server machine running an Apache 2.4.56 server on port 80. A web app recovers visual studio projects from external gits, compiles them and stores them in the server. The web application can be abused leveraging "pre events" on visual studio project files. Once inside the machine, we can move laterally to a local service user and restore its privileges with Full Powers binary. Finally, system shell is obtained with God Potato.
KEYWORDS
Git, Visual Studio, pre/post events, Full Powers, God Potato.
> nmap $target -p- -T4 -Pn --open --reason
Starting Nmap 7.93 ( https://nmap.org ) at 2023-10-02 06:42 EDT
Stats: 0:04:21 elapsed; 0 hosts completed (1 up), 1 undergoing Connect Scan
Nmap scan report for 10.129.131.71
Host is up, received user-set (0.20s latency).
Not shown: 65534 filtered tcp ports (no-response)
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
PORT STATE SERVICE REASON
80/tcp open http syn-ack
Nmap done: 1 IP address (1 host up) scanned in 495.11 seconds
Enumerate the open ports.
> nmap $target -p80 -sV -sC -Pn -v
Starting Nmap 7.93 ( https://nmap.org ) at 2023-10-02 06:53 EDT
Nmap scan report for 10.129.131.71
Host is up (0.15s latency).
PORT STATE SERVICE VERSION
80/tcp open http Apache httpd 2.4.56 ((Win64) OpenSSL/1.1.1t PHP/8.1.17)
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: Apache/2.4.56 (Win64) OpenSSL/1.1.1t PHP/8.1.17
|_http-favicon: Unknown favicon MD5: 556F31ACD686989B1AFCF382C05846AA
|_http-title: Visual - Revolutionizing Visual Studio Builds
Nmap done: 1 IP address (1 host up) scanned in 13.43 seconds
There is an Apache 2.4.56 web server running on port 80. We inspect the site with Firefox, a web app which compiles and stores visual studio projects comes into view. After supplying a Git repository link, the app pulls the files, compiles the Net 6.0 and C# projects and uploads them in the site.
USER
Our goal is to prepare a local HTTP Git repository serving a Visual Studio solution. For this, we start making a directory called repo and create a new Visual Studio solution called repo.sln
> mkdir repo
> cd repo
> dotnet new sln -n repo
The template "Solution File" was created successfully.
From the repo directory, create a new project (specifically, a console C# app) called myapp
> dotnet new console -o myapp
The template "Console App" was created successfully.
Processing post-creation actions...
Running 'dotnet restore' on /home/kali/htb/repo/myapp/myapp.csproj...
Determining projects to restore...
Restored /home/kali/htb/repo/myapp/myapp.csproj (in 106 ms).
Restore succeeded.
This will generate a new folder called myapp containing a project file called myapp.csproj and a C# source file called Program.cs. Finally, we add the C# project to the Visual Studio solution.
> dotnet sln repo.sln add myapp/myapp.csproj
Project `myapp/myapp.csproj` added to the solution.
Once Visual Studio part is finished, we need to initialize a Git repository in the repo directory and serve it via HTTP. For this, firstly initialize the Git repository on directory repo
> cd repo
> git init
The directory repo/.git is created after this. The .git directory contains the repository files and metadata. Next step is to add all files on the repo directory to the git.
> git add .
Check there are no more untracked files in the Git repo to be added.
> git status
On branch master
No commits yet
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: myapp/Program.cs
new file: myapp/myapp.csproj
new file: myapp/obj/myapp.csproj.nuget.dgspec.json
new file: myapp/obj/myapp.csproj.nuget.g.props
new file: myapp/obj/myapp.csproj.nuget.g.targets
new file: myapp/obj/project.assets.json
new file: myapp/obj/project.nuget.cache
new file: repo.sln
Commit changes.
> git commit -m 'first commit'
[master (root-commit) c1149ed] first commit
Committer: Kali <kali@kali>
Your name and email address were configured automatically based
on your username and hostname. Please check that they are accurate.
You can suppress this message by setting them explicitly. Run the
following command and follow the instructions in your editor to edit
your configuration file:
git config --global --edit
After doing this, you may fix the identity used for this commit with:
git commit --amend --reset-author
8 files changed, 254 insertions(+)
create mode 100644 myapp/Program.cs
create mode 100644 myapp/myapp.csproj
create mode 100644 myapp/obj/myapp.csproj.nuget.dgspec.json
create mode 100644 myapp/obj/myapp.csproj.nuget.g.props
create mode 100644 myapp/obj/myapp.csproj.nuget.g.targets
create mode 100644 myapp/obj/project.assets.json
create mode 100644 myapp/obj/project.nuget.cache
create mode 100644 repo.sln
Finally, move to the .git directory and update server info.
> git update-server-info
Now the git is ready to be served on HTTP. We can test it, move to .git and serve the repository with a Python HTTP server. Then, in the web app, enter the local machine IP. Shortly after, the app starts downloading the C# files and uploading them into the server. Once they are complied, they are stored in a random folder and the app supplies the user with the resulting URL.
Once we are sure our Git repo works, we have to find a way to make the server execute the code after compiling it. This can be done manipulating "pre" and "post" events in the C# .csproj project file.
These events are triggered by the msbuild compiler before or after the compiling process ends. We will add a "pre event", calling a powercat reverse shell before the building process begins. Just create any simple Program.cs source file and, in the myapp.csproj file, add the "pre event".
Start another Python HTTP serving powercat.ps1 and start a listener. Enter red box IP in the web app URL box, when the C# files are pulled and processed a reverse shell is received on port 1919.
SYSTEM
Enumerate the system.
> systeminfo
Host Name: VISUAL
OS Name: Microsoft Windows Server 2019 Standard
OS Version: 10.0.17763 N/A Build 17763
System Type: x64-based PC
Enumerate current user privileges.
> 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
After enumeration, we discover we have write access to web root folder so if we copy a .php shell in the web root, we could move laterally to the user who is running the web server. Let's check who is running the HTTP service.
> wmic service where started=true get name,startname
Name StartName
ApacheHTTPServer NT AUTHORITY\Local Service
BFE NT AUTHORITY\LocalService
BrokerInfrastructure LocalSystem
camsvc LocalSystem
CDPSvc NT AUTHORITY\LocalService
The user turns to be ApacheHTTPServer, who is nt authority\local service. Copy a simple-backdoor.php and an EXE msfvenom payload into the web root folder (download with certutil). Then start a listener and execute the payload using a browser and the simple-backdoor.php. A reverse shell for user nt authority\local service is received on the listener.
Enumerate ApacheHTTPService user's permissions
> whoami
nt authority\local service
> 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
It's the same as before, seems we have not progressed so much; however, there is a tool which restores original privileges (including impersonation) to local services account.
Download and use fullpowers.exe (https://github.com/itm4n/FullPowers) on the local service account shell, verify impersonation privilege is restored afterwards.
> fp.exe
[+] Started dummy thread with id 2388
[+] 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.
> 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
Once we have impersonation privilege restored, we can try all range of potatoes. The working one is God Potato (https://github.com/BeichenDream/GodPotato). We need another msfvenom shell to execute with God Potato.